Merge public-gh/master into review/pr-162
This commit is contained in:
@@ -20,7 +20,7 @@ The `claude_local` adapter runs Anthropic's Claude Code CLI locally. It supports
|
||||
| `env` | object | No | Environment variables (supports secret refs) |
|
||||
| `timeoutSec` | number | No | Process timeout (0 = no timeout) |
|
||||
| `graceSec` | number | No | Grace period before force-kill |
|
||||
| `maxTurnsPerRun` | number | No | Max agentic turns per heartbeat |
|
||||
| `maxTurnsPerRun` | number | No | Max agentic turns per heartbeat (defaults to `300`) |
|
||||
| `dangerouslySkipPermissions` | boolean | No | Skip permission prompts (dev only) |
|
||||
|
||||
## Prompt Templates
|
||||
@@ -47,6 +47,14 @@ If resume fails with an unknown session error, the adapter automatically retries
|
||||
|
||||
The adapter creates a temporary directory with symlinks to Paperclip skills and passes it via `--add-dir`. This makes skills discoverable without polluting the agent's working directory.
|
||||
|
||||
For manual local CLI usage outside heartbeat runs (for example running as `claudecoder` directly), use:
|
||||
|
||||
```sh
|
||||
pnpm paperclipai agent local-cli claudecoder --company-id <company-id>
|
||||
```
|
||||
|
||||
This installs Paperclip skills in `~/.claude/skills`, creates an agent API key, and prints shell exports to run as that agent.
|
||||
|
||||
## Environment Test
|
||||
|
||||
Use the "Test Environment" button in the UI to validate the adapter config. It checks:
|
||||
|
||||
@@ -30,6 +30,16 @@ Codex uses `previous_response_id` for session continuity. The adapter serializes
|
||||
|
||||
The adapter symlinks Paperclip skills into the global Codex skills directory (`~/.codex/skills`). Existing user skills are not overwritten.
|
||||
|
||||
When Paperclip is running inside a managed worktree instance (`PAPERCLIP_IN_WORKTREE=true`), the adapter instead uses a worktree-isolated `CODEX_HOME` under the Paperclip instance so Codex skills, sessions, logs, and other runtime state do not leak across checkouts. It seeds that isolated home from the user's main Codex home for shared auth/config continuity.
|
||||
|
||||
For manual local CLI usage outside heartbeat runs (for example running as `codexcoder` directly), use:
|
||||
|
||||
```sh
|
||||
pnpm paperclipai agent local-cli codexcoder --company-id <company-id>
|
||||
```
|
||||
|
||||
This installs any missing skills, creates an agent API key, and prints shell exports to run as that agent.
|
||||
|
||||
## Environment Test
|
||||
|
||||
The environment test checks:
|
||||
|
||||
@@ -6,7 +6,7 @@ summary: Guide to building a custom adapter
|
||||
Build a custom adapter to connect Paperclip to any agent runtime.
|
||||
|
||||
<Tip>
|
||||
If you're using Claude Code, the `create-agent-adapter` skill can guide you through the full adapter creation process interactively. Just ask Claude to create a new adapter and it will walk you through each step.
|
||||
If you're using Claude Code, the `.agents/skills/create-agent-adapter` skill can guide you through the full adapter creation process interactively. Just ask Claude to create a new adapter and it will walk you through each step.
|
||||
</Tip>
|
||||
|
||||
## Package Structure
|
||||
|
||||
45
docs/adapters/gemini-local.md
Normal file
45
docs/adapters/gemini-local.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Gemini Local
|
||||
summary: Gemini CLI local adapter setup and configuration
|
||||
---
|
||||
|
||||
The `gemini_local` adapter runs Google's Gemini CLI locally. It supports session persistence with `--resume`, skills injection, and structured `stream-json` output parsing.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Gemini CLI installed (`gemini` command available)
|
||||
- `GEMINI_API_KEY` or `GOOGLE_API_KEY` set, or local Gemini CLI auth configured
|
||||
|
||||
## Configuration Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `cwd` | string | Yes | Working directory for the agent process (absolute path; created automatically if missing when permissions allow) |
|
||||
| `model` | string | No | Gemini model to use. Defaults to `auto`. |
|
||||
| `promptTemplate` | string | No | Prompt used for all runs |
|
||||
| `instructionsFilePath` | string | No | Markdown instructions file prepended to the prompt |
|
||||
| `env` | object | No | Environment variables (supports secret refs) |
|
||||
| `timeoutSec` | number | No | Process timeout (0 = no timeout) |
|
||||
| `graceSec` | number | No | Grace period before force-kill |
|
||||
| `yolo` | boolean | No | Pass `--approval-mode yolo` for unattended operation |
|
||||
|
||||
## Session Persistence
|
||||
|
||||
The adapter persists Gemini session IDs between heartbeats. On the next wake, it resumes the existing conversation with `--resume` so the agent retains context.
|
||||
|
||||
Session resume is cwd-aware: if the working directory changed since the last run, a fresh session starts instead.
|
||||
|
||||
If resume fails with an unknown session error, the adapter automatically retries with a fresh session.
|
||||
|
||||
## Skills Injection
|
||||
|
||||
The adapter symlinks Paperclip skills into the Gemini global skills directory (`~/.gemini/skills`). Existing user skills are not overwritten.
|
||||
|
||||
## Environment Test
|
||||
|
||||
Use the "Test Environment" button in the UI to validate the adapter config. It checks:
|
||||
|
||||
- Gemini CLI is installed and accessible
|
||||
- Working directory is absolute and available (auto-created if missing and permitted)
|
||||
- API key/auth hints (`GEMINI_API_KEY` or `GOOGLE_API_KEY`)
|
||||
- A live hello probe (`gemini --output-format json "Respond with hello."`) to verify CLI readiness
|
||||
@@ -20,6 +20,7 @@ When a heartbeat fires, Paperclip:
|
||||
|---------|----------|-------------|
|
||||
| [Claude Local](/adapters/claude-local) | `claude_local` | Runs Claude Code CLI locally |
|
||||
| [Codex Local](/adapters/codex-local) | `codex_local` | Runs OpenAI Codex CLI locally |
|
||||
| [Gemini Local](/adapters/gemini-local) | `gemini_local` | Runs Gemini CLI locally |
|
||||
| OpenCode Local | `opencode_local` | Runs OpenCode CLI locally (multi-provider `provider/model`) |
|
||||
| OpenClaw | `openclaw` | Sends wake payloads to an OpenClaw webhook |
|
||||
| [Process](/adapters/process) | `process` | Executes arbitrary shell commands |
|
||||
@@ -54,7 +55,7 @@ Three registries consume these modules:
|
||||
|
||||
## Choosing an Adapter
|
||||
|
||||
- **Need a coding agent?** Use `claude_local`, `codex_local`, or `opencode_local`
|
||||
- **Need a coding agent?** Use `claude_local`, `codex_local`, `gemini_local`, or `opencode_local`
|
||||
- **Need to run a script or command?** Use `process`
|
||||
- **Need to call an external service?** Use `http`
|
||||
- **Need something custom?** [Create your own adapter](/adapters/creating-an-adapter)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
title: Issues
|
||||
summary: Issue CRUD, checkout/release, comments, and attachments
|
||||
summary: Issue CRUD, checkout/release, comments, documents, and attachments
|
||||
---
|
||||
|
||||
Issues are the unit of work in Paperclip. They support hierarchical relationships, atomic checkout, comments, and file attachments.
|
||||
Issues are the unit of work in Paperclip. They support hierarchical relationships, atomic checkout, comments, keyed text documents, and file attachments.
|
||||
|
||||
## List Issues
|
||||
|
||||
@@ -29,6 +29,12 @@ GET /api/issues/{issueId}
|
||||
|
||||
Returns the issue with `project`, `goal`, and `ancestors` (parent chain with their projects and goals).
|
||||
|
||||
The response also includes:
|
||||
|
||||
- `planDocument`: the full text of the issue document with key `plan`, when present
|
||||
- `documentSummaries`: metadata for all linked issue documents
|
||||
- `legacyPlanDocument`: a read-only fallback when the description still contains an old `<plan>` block
|
||||
|
||||
## Create Issue
|
||||
|
||||
```
|
||||
@@ -100,6 +106,54 @@ POST /api/issues/{issueId}/comments
|
||||
|
||||
@-mentions (`@AgentName`) in comments trigger heartbeats for the mentioned agent.
|
||||
|
||||
## Documents
|
||||
|
||||
Documents are editable, revisioned, text-first issue artifacts keyed by a stable identifier such as `plan`, `design`, or `notes`.
|
||||
|
||||
### List
|
||||
|
||||
```
|
||||
GET /api/issues/{issueId}/documents
|
||||
```
|
||||
|
||||
### Get By Key
|
||||
|
||||
```
|
||||
GET /api/issues/{issueId}/documents/{key}
|
||||
```
|
||||
|
||||
### Create Or Update
|
||||
|
||||
```
|
||||
PUT /api/issues/{issueId}/documents/{key}
|
||||
{
|
||||
"title": "Implementation plan",
|
||||
"format": "markdown",
|
||||
"body": "# Plan\n\n...",
|
||||
"baseRevisionId": "{latestRevisionId}"
|
||||
}
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- omit `baseRevisionId` when creating a new document
|
||||
- provide the current `baseRevisionId` when updating an existing document
|
||||
- stale `baseRevisionId` returns `409 Conflict`
|
||||
|
||||
### Revision History
|
||||
|
||||
```
|
||||
GET /api/issues/{issueId}/documents/{key}/revisions
|
||||
```
|
||||
|
||||
### Delete
|
||||
|
||||
```
|
||||
DELETE /api/issues/{issueId}/documents/{key}
|
||||
```
|
||||
|
||||
Delete is board-only in the current implementation.
|
||||
|
||||
## Attachments
|
||||
|
||||
### Upload
|
||||
|
||||
569
docs/plans/2026-03-13-issue-documents-plan.md
Normal file
569
docs/plans/2026-03-13-issue-documents-plan.md
Normal file
@@ -0,0 +1,569 @@
|
||||
# Issue Documents Plan
|
||||
|
||||
Status: Draft
|
||||
Owner: Backend + UI + Agent Protocol
|
||||
Date: 2026-03-13
|
||||
Primary issue: `PAP-448`
|
||||
|
||||
## Summary
|
||||
|
||||
Add first-class **documents** to Paperclip as editable, revisioned, company-scoped text artifacts that can be linked to issues.
|
||||
|
||||
The first required convention is a document with key `plan`.
|
||||
|
||||
This solves the immediate workflow problem in `PAP-448`:
|
||||
|
||||
- plans should stop living inside issue descriptions as `<plan>` blocks
|
||||
- agents and board users should be able to create/update issue documents directly
|
||||
- `GET /api/issues/:id` should include the full `plan` document and expose the other available documents
|
||||
- issue detail should render documents under the description
|
||||
|
||||
This should be built as the **text-document slice** of the broader artifact system, not as a replacement for attachments/assets.
|
||||
|
||||
## Recommended Product Shape
|
||||
|
||||
### Documents vs attachments vs artifacts
|
||||
|
||||
- **Documents**: editable text content with stable keys and revision history.
|
||||
- **Attachments**: uploaded/generated opaque files backed by storage (`assets` + `issue_attachments`).
|
||||
- **Artifacts**: later umbrella/read-model that can unify documents, attachments, previews, and workspace files.
|
||||
|
||||
Recommendation:
|
||||
|
||||
- implement **issue documents now**
|
||||
- keep existing attachments as-is
|
||||
- defer full artifact unification until there is a second real consumer beyond issue documents + attachments
|
||||
|
||||
This keeps `PAP-448` focused while still fitting the larger artifact direction.
|
||||
|
||||
## Goals
|
||||
|
||||
1. Give issues first-class keyed documents, starting with `plan`.
|
||||
2. Make documents editable by board users and same-company agents with issue access.
|
||||
3. Preserve change history with append-only revisions.
|
||||
4. Make the `plan` document automatically available in the normal issue fetch used by agents/heartbeats.
|
||||
5. Replace the current `<plan>`-in-description convention in skills/docs.
|
||||
6. Keep the design compatible with a future artifact/deliverables layer.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- full collaborative doc editing
|
||||
- binary-file version history
|
||||
- browser IDE or workspace editor
|
||||
- full artifact-system implementation in the same change
|
||||
- generalized polymorphic relations for every entity type on day one
|
||||
|
||||
## Product Decisions
|
||||
|
||||
### 1. Keyed issue documents
|
||||
|
||||
Each issue can have multiple documents. Each document relation has a stable key:
|
||||
|
||||
- `plan`
|
||||
- `design`
|
||||
- `notes`
|
||||
- `report`
|
||||
- custom keys later
|
||||
|
||||
Key rules:
|
||||
|
||||
- unique per issue, case-insensitive
|
||||
- normalized to lowercase slug form
|
||||
- machine-oriented and stable
|
||||
- title is separate and user-facing
|
||||
|
||||
The `plan` key is conventional and reserved by Paperclip workflow/docs.
|
||||
|
||||
### 2. Text-first v1
|
||||
|
||||
V1 documents should be text-first, not arbitrary blobs.
|
||||
|
||||
Recommended supported formats:
|
||||
|
||||
- `markdown`
|
||||
- `plain_text`
|
||||
- `json`
|
||||
- `html`
|
||||
|
||||
Recommendation:
|
||||
|
||||
- optimize UI for `markdown`
|
||||
- allow raw editing for the others
|
||||
- keep PDFs/images/CSVs/etc as attachments/artifacts, not editable documents
|
||||
|
||||
### 3. Revision model
|
||||
|
||||
Every document update creates a new immutable revision.
|
||||
|
||||
The current document row stores the latest snapshot for fast reads.
|
||||
|
||||
### 4. Concurrency model
|
||||
|
||||
Do not use silent last-write-wins.
|
||||
|
||||
Updates should include `baseRevisionId`:
|
||||
|
||||
- create: no base revision required
|
||||
- update: `baseRevisionId` must match current latest revision
|
||||
- mismatch: return `409 Conflict`
|
||||
|
||||
This is important because both board users and agents may edit the same document.
|
||||
|
||||
### 5. Issue fetch behavior
|
||||
|
||||
`GET /api/issues/:id` should include:
|
||||
|
||||
- full `planDocument` when a `plan` document exists
|
||||
- `documentSummaries` for all linked documents
|
||||
|
||||
It should not inline every document body by default.
|
||||
|
||||
This keeps issue fetches useful for agents without making every issue payload unbounded.
|
||||
|
||||
### 6. Legacy `<plan>` compatibility
|
||||
|
||||
If an issue has no `plan` document but its description contains a legacy `<plan>` block:
|
||||
|
||||
- expose that as a legacy read-only fallback in API/UI
|
||||
- mark it as legacy/synthetic
|
||||
- prefer a real `plan` document when both exist
|
||||
|
||||
Recommendation:
|
||||
|
||||
- do not auto-rewrite old issue descriptions in the first rollout
|
||||
- provide an explicit import/migrate path later
|
||||
|
||||
## Proposed Data Model
|
||||
|
||||
Recommendation: make documents first-class, but keep issue linkage explicit via a join table.
|
||||
|
||||
This preserves foreign keys today and gives a clean path to future `project_documents` or `company_documents` tables later.
|
||||
|
||||
## Tables
|
||||
|
||||
### `documents`
|
||||
|
||||
Canonical text document record.
|
||||
|
||||
Suggested columns:
|
||||
|
||||
- `id`
|
||||
- `company_id`
|
||||
- `title`
|
||||
- `format`
|
||||
- `latest_body`
|
||||
- `latest_revision_id`
|
||||
- `latest_revision_number`
|
||||
- `created_by_agent_id`
|
||||
- `created_by_user_id`
|
||||
- `updated_by_agent_id`
|
||||
- `updated_by_user_id`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
### `document_revisions`
|
||||
|
||||
Append-only history.
|
||||
|
||||
Suggested columns:
|
||||
|
||||
- `id`
|
||||
- `company_id`
|
||||
- `document_id`
|
||||
- `revision_number`
|
||||
- `body`
|
||||
- `change_summary`
|
||||
- `created_by_agent_id`
|
||||
- `created_by_user_id`
|
||||
- `created_at`
|
||||
|
||||
Constraints:
|
||||
|
||||
- unique `(document_id, revision_number)`
|
||||
|
||||
### `issue_documents`
|
||||
|
||||
Issue relation + workflow key.
|
||||
|
||||
Suggested columns:
|
||||
|
||||
- `id`
|
||||
- `company_id`
|
||||
- `issue_id`
|
||||
- `document_id`
|
||||
- `key`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Constraints:
|
||||
|
||||
- unique `(company_id, issue_id, key)`
|
||||
- unique `(document_id)` to keep one issue relation per document in v1
|
||||
|
||||
## Why not use `assets` for this?
|
||||
|
||||
Because `assets` solves blob storage, not:
|
||||
|
||||
- stable keyed semantics like `plan`
|
||||
- inline text editing
|
||||
- revision history
|
||||
- optimistic concurrency
|
||||
- cheap inclusion in `GET /issues/:id`
|
||||
|
||||
Documents and attachments should remain separate primitives, then meet later in a deliverables/artifact read-model.
|
||||
|
||||
## Shared Types and API Contract
|
||||
|
||||
## New shared types
|
||||
|
||||
Add:
|
||||
|
||||
- `DocumentFormat`
|
||||
- `IssueDocument`
|
||||
- `IssueDocumentSummary`
|
||||
- `DocumentRevision`
|
||||
|
||||
Recommended `IssueDocument` shape:
|
||||
|
||||
```ts
|
||||
type DocumentFormat = "markdown" | "plain_text" | "json" | "html";
|
||||
|
||||
interface IssueDocument {
|
||||
id: string;
|
||||
companyId: string;
|
||||
issueId: string;
|
||||
key: string;
|
||||
title: string | null;
|
||||
format: DocumentFormat;
|
||||
body: string;
|
||||
latestRevisionId: string;
|
||||
latestRevisionNumber: number;
|
||||
createdByAgentId: string | null;
|
||||
createdByUserId: string | null;
|
||||
updatedByAgentId: string | null;
|
||||
updatedByUserId: string | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
Recommended `IssueDocumentSummary` shape:
|
||||
|
||||
```ts
|
||||
interface IssueDocumentSummary {
|
||||
id: string;
|
||||
key: string;
|
||||
title: string | null;
|
||||
format: DocumentFormat;
|
||||
latestRevisionId: string;
|
||||
latestRevisionNumber: number;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
## Issue type enrichment
|
||||
|
||||
Extend `Issue` with:
|
||||
|
||||
```ts
|
||||
interface Issue {
|
||||
...
|
||||
planDocument?: IssueDocument | null;
|
||||
documentSummaries?: IssueDocumentSummary[];
|
||||
legacyPlanDocument?: {
|
||||
key: "plan";
|
||||
body: string;
|
||||
source: "issue_description";
|
||||
} | null;
|
||||
}
|
||||
```
|
||||
|
||||
This directly satisfies the `PAP-448` requirement for heartbeat/API issue fetches.
|
||||
|
||||
## API endpoints
|
||||
|
||||
Recommended endpoints:
|
||||
|
||||
- `GET /api/issues/:issueId/documents`
|
||||
- `GET /api/issues/:issueId/documents/:key`
|
||||
- `PUT /api/issues/:issueId/documents/:key`
|
||||
- `GET /api/issues/:issueId/documents/:key/revisions`
|
||||
- `DELETE /api/issues/:issueId/documents/:key` optionally board-only in v1
|
||||
|
||||
Recommended `PUT` body:
|
||||
|
||||
```ts
|
||||
{
|
||||
title?: string | null;
|
||||
format: "markdown" | "plain_text" | "json" | "html";
|
||||
body: string;
|
||||
changeSummary?: string | null;
|
||||
baseRevisionId?: string | null;
|
||||
}
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
- missing document + no `baseRevisionId`: create
|
||||
- existing document + matching `baseRevisionId`: update
|
||||
- existing document + stale `baseRevisionId`: `409`
|
||||
|
||||
## Authorization and invariants
|
||||
|
||||
- all document records are company-scoped
|
||||
- issue relation must belong to same company
|
||||
- board access follows existing issue access rules
|
||||
- agent access follows existing same-company issue access rules
|
||||
- every mutation writes activity log entries
|
||||
|
||||
Recommended delete rule for v1:
|
||||
|
||||
- board can delete documents
|
||||
- agents can create/update, but not delete
|
||||
|
||||
That keeps automated systems from removing canonical docs too easily.
|
||||
|
||||
## UI Plan
|
||||
|
||||
## Issue detail
|
||||
|
||||
Add a new **Documents** section directly under the issue description.
|
||||
|
||||
Recommended behavior:
|
||||
|
||||
- show `plan` first when present
|
||||
- show other documents below it
|
||||
- render a gist-like header:
|
||||
- key
|
||||
- title
|
||||
- last updated metadata
|
||||
- revision number
|
||||
- support inline edit
|
||||
- support create new document by key
|
||||
- support revision history drawer or sheet
|
||||
|
||||
Recommended presentation order:
|
||||
|
||||
1. Description
|
||||
2. Documents
|
||||
3. Attachments
|
||||
4. Comments / activity / sub-issues
|
||||
|
||||
This matches the request that documents live under the description while still leaving attachments available.
|
||||
|
||||
## Editing UX
|
||||
|
||||
Recommendation:
|
||||
|
||||
- use markdown preview + raw edit toggle for markdown docs
|
||||
- use raw textarea editor for non-markdown docs in v1
|
||||
- show explicit save conflicts on `409`
|
||||
- show a clear empty state: "No documents yet"
|
||||
|
||||
## Legacy plan rendering
|
||||
|
||||
If there is no stored `plan` document but legacy `<plan>` exists:
|
||||
|
||||
- show it in the Documents section
|
||||
- mark it `Legacy plan from description`
|
||||
- offer create/import in a later pass
|
||||
|
||||
## Agent Protocol and Skills
|
||||
|
||||
Update the Paperclip agent workflow so planning no longer edits the issue description.
|
||||
|
||||
Required changes:
|
||||
|
||||
- update `skills/paperclip/SKILL.md`
|
||||
- replace the `<plan>` instructions with document creation/update instructions
|
||||
- document the new endpoints in `docs/api/issues.md`
|
||||
- update any internal planning docs that still teach inline `<plan>` blocks
|
||||
|
||||
New rule:
|
||||
|
||||
- when asked to make a plan for an issue, create or update the issue document with key `plan`
|
||||
- leave a comment that the plan document was created/updated
|
||||
- do not mark the issue done
|
||||
|
||||
## Relationship to the Artifact Plan
|
||||
|
||||
This work should explicitly feed the broader artifact/deliverables direction.
|
||||
|
||||
Recommendation:
|
||||
|
||||
- keep documents as their own primitive in this change
|
||||
- add `document` to any future `ArtifactKind`
|
||||
- later build a deliverables read-model that aggregates:
|
||||
- issue documents
|
||||
- issue attachments
|
||||
- preview URLs
|
||||
- workspace-file references
|
||||
|
||||
The artifact proposal currently has no explicit `document` kind. It should.
|
||||
|
||||
Recommended future shape:
|
||||
|
||||
```ts
|
||||
type ArtifactKind =
|
||||
| "document"
|
||||
| "attachment"
|
||||
| "workspace_file"
|
||||
| "preview"
|
||||
| "report_link";
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
## Phase 1: Shared contract and schema
|
||||
|
||||
Files:
|
||||
|
||||
- `packages/db/src/schema/documents.ts`
|
||||
- `packages/db/src/schema/document_revisions.ts`
|
||||
- `packages/db/src/schema/issue_documents.ts`
|
||||
- `packages/db/src/schema/index.ts`
|
||||
- `packages/db/src/migrations/*`
|
||||
- `packages/shared/src/types/issue.ts`
|
||||
- `packages/shared/src/validators/issue.ts` or new document validator file
|
||||
- `packages/shared/src/index.ts`
|
||||
|
||||
Acceptance:
|
||||
|
||||
- schema enforces one key per issue
|
||||
- revisions are append-only
|
||||
- shared types expose plan/document fields on issue fetch
|
||||
|
||||
## Phase 2: Server services and routes
|
||||
|
||||
Files:
|
||||
|
||||
- `server/src/services/issues.ts` or `server/src/services/documents.ts`
|
||||
- `server/src/routes/issues.ts`
|
||||
- `server/src/services/activity.ts` callsites
|
||||
|
||||
Behavior:
|
||||
|
||||
- list/get/upsert/delete documents
|
||||
- revision listing
|
||||
- `GET /issues/:id` returns `planDocument` + `documentSummaries`
|
||||
- company boundary checks match issue routes
|
||||
|
||||
Acceptance:
|
||||
|
||||
- agents and board can fetch/update same-company issue documents
|
||||
- stale edits return `409`
|
||||
- activity timeline shows document changes
|
||||
|
||||
## Phase 3: UI issue documents surface
|
||||
|
||||
Files:
|
||||
|
||||
- `ui/src/api/issues.ts`
|
||||
- `ui/src/lib/queryKeys.ts`
|
||||
- `ui/src/pages/IssueDetail.tsx`
|
||||
- new reusable document UI component if needed
|
||||
|
||||
Behavior:
|
||||
|
||||
- render plan + documents under description
|
||||
- create/update by key
|
||||
- open revision history
|
||||
- show conflicts/errors clearly
|
||||
|
||||
Acceptance:
|
||||
|
||||
- board can create a `plan` doc from issue detail
|
||||
- updated plan appears immediately
|
||||
- issue detail no longer depends on description-embedded `<plan>`
|
||||
|
||||
## Phase 4: Skills/docs migration
|
||||
|
||||
Files:
|
||||
|
||||
- `skills/paperclip/SKILL.md`
|
||||
- `docs/api/issues.md`
|
||||
- `doc/SPEC-implementation.md`
|
||||
- relevant plan/docs that mention `<plan>`
|
||||
|
||||
Acceptance:
|
||||
|
||||
- planning guidance references issue documents, not inline issue description tags
|
||||
- API docs describe the new document endpoints and issue payload additions
|
||||
|
||||
## Phase 5: Legacy compatibility and follow-up
|
||||
|
||||
Behavior:
|
||||
|
||||
- read legacy `<plan>` blocks as fallback
|
||||
- optionally add explicit import/migration command later
|
||||
|
||||
Follow-up, not required for first merge:
|
||||
|
||||
- deliverables/artifact read-model
|
||||
- project/company documents
|
||||
- comment-linked documents
|
||||
- diff view between revisions
|
||||
|
||||
## Test Plan
|
||||
|
||||
### Server
|
||||
|
||||
- document create/read/update/delete lifecycle
|
||||
- revision numbering
|
||||
- `baseRevisionId` conflict handling
|
||||
- company boundary enforcement
|
||||
- agent vs board authorization
|
||||
- issue fetch includes `planDocument` and document summaries
|
||||
- legacy `<plan>` fallback behavior
|
||||
- activity log mutation coverage
|
||||
|
||||
### UI
|
||||
|
||||
- issue detail shows plan document
|
||||
- create/update flows invalidate queries correctly
|
||||
- conflict and validation errors are surfaced
|
||||
- legacy plan fallback renders correctly
|
||||
|
||||
### Verification
|
||||
|
||||
Run before implementation is declared complete:
|
||||
|
||||
```sh
|
||||
pnpm -r typecheck
|
||||
pnpm test:run
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Should v1 documents be markdown-only, with `json/html/plain_text` deferred?
|
||||
Recommendation: allow all four in API, optimize UI for markdown only.
|
||||
|
||||
2. Should agents be allowed to create arbitrary keys, or only conventional keys?
|
||||
Recommendation: allow arbitrary keys with normalized validation; reserve `plan` as special behavior only.
|
||||
|
||||
3. Should delete exist in v1?
|
||||
Recommendation: yes, but board-only.
|
||||
|
||||
4. Should legacy `<plan>` blocks ever be auto-migrated?
|
||||
Recommendation: no automatic mutation in the first rollout.
|
||||
|
||||
5. Should documents appear inside a future Deliverables section or remain a top-level Issue section?
|
||||
Recommendation: keep a dedicated Documents section now; later also expose them in Deliverables if an aggregated artifact view is added.
|
||||
|
||||
## Final Recommendation
|
||||
|
||||
Ship **issue documents** as a focused, text-first primitive now.
|
||||
|
||||
Do not try to solve full artifact unification in the same implementation.
|
||||
|
||||
Use:
|
||||
|
||||
- first-class document tables
|
||||
- issue-level keyed linkage
|
||||
- append-only revisions
|
||||
- `planDocument` embedded in normal issue fetches
|
||||
- legacy `<plan>` fallback
|
||||
- skill/docs migration away from description-embedded plans
|
||||
|
||||
This addresses the real planning workflow problem immediately and leaves the artifact system room to grow cleanly afterward.
|
||||
Reference in New Issue
Block a user