mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
## Thinking Path > - Paperclip is a control plane for AI-agent companies, with the CLI acting as a scriptable operator and agent interface to that control plane. > - The REST API surface has grown across companies, agents, issues, routines, plugins, auth, workspaces, secrets, and operational inspection commands. > - The CLI had drifted from that API surface: some commands were missing, some command shapes differed from docs/reference material, and several edge cases only failed during end-to-end local-source testing. > - The local development runbook requires these tests to be disposable and isolated from a real `~/.paperclip`, `~/.codex`, or `~/.claude` installation. > - This pull request adds broad CLI/API parity coverage, fixes the actionable bugs found during that pass, and records the reproducible test log under `doc/logs`. > - The benefit is a more complete, scriptable CLI surface with regression coverage for the command families exercised by the parity run. ## What Changed - Added or expanded CLI command coverage for access/auth, companies, agents, projects, goals, issues and subresources, routines, plugins, workspaces, activity/run/cost/dashboard inspection, assets, skills, secrets, tokens, prompt/wake flows, and local setup helpers. - Fixed CLI/API parity bugs found during the run, including context profile patching, issue interaction optional payloads, malformed tree-hold errors, environment duplicate handling, configure invalid-section exit codes, worktree pnpm invocation, token agent ID resolution, plugin tool worker lookup, and routine webhook secret cleanup. - Added missing CLI wrappers and route coverage for health/access, invite resolution URL forwarding, join status normalization, secret lifecycle commands, LLM docs routes, available-skill isolation, positive board-claim coverage, and interactive `connect` prompt-flow tests. - Added a schema-backed `/api/openapi.json` route sufficient for CLI parity and `paperclipai openapi --json` smoke coverage. - Added `doc/logs/2026-05-24-cli-api-parity-e2e-log.md` with the detailed living test/bug log and renamed the log directory from `doc/bugs` to `doc/logs`. - Added `doc/plans/2026-05-23-cli-api-parity.md` and the OpenAPI parity reference used during the pass. OpenAPI note: this PR intentionally does not try to subsume `feature/openapi-spec`. The OpenAPI implementation here is schema-backed and better than the earlier route-inventory stub, but `feature/openapi-spec` is the fuller/better OpenAPI branch because it includes exact mounted-route coverage tests and additional current route coverage. That branch should stay as its own PR and can supersede this OpenAPI route implementation. ## Verification Targeted automated checks run: - `pnpm exec vitest run server/src/__tests__/openapi-routes.test.ts` - `pnpm exec vitest run server/src/__tests__/board-claim.test.ts` - `pnpm exec vitest run cli/src/__tests__/connect.test.ts` - `pnpm exec vitest run cli/src/__tests__/agent-lifecycle.test.ts` - `pnpm exec vitest run server/src/__tests__/plugin-database.test.ts` - `pnpm exec vitest run server/src/__tests__/routines-service.test.ts` - `pnpm --dir cli typecheck` - `pnpm --dir server typecheck` Manual/local E2E verification: - Ran the full disposable local-source CLI/API parity pass with isolated `PAPERCLIP_HOME`, `PAPERCLIP_CONFIG`, `PAPERCLIP_CONTEXT`, `PAPERCLIP_AUTH_STORE`, `CODEX_HOME`, and `CLAUDE_HOME` under `tmp/cli-api-parity`. - Verified `DATABASE_URL` and `DATABASE_MIGRATION_URL` stayed unset for the scratch server. - Verified live health and schema-backed OpenAPI responses on non-default port `3197`. - Revoked created board/agent tokens and cleaned up temporary plugins, secrets, non-default environments, and project workspaces. - See `doc/logs/2026-05-24-cli-api-parity-e2e-log.md` for the full command-by-command reproduction log. Not run: - Full `pnpm test`, `pnpm test:run`, or `pnpm build` were not run after the entire branch because the branch is broad and the parity pass used focused test/typecheck verification plus live isolated CLI reruns. ## Risks - This is a broad PR and touches many CLI command modules, so review surface is high. The changes are grouped around one theme, but a split may be easier if maintainers prefer narrower PRs. - The OpenAPI route in this PR is not the final/best OpenAPI implementation. `feature/openapi-spec` has stronger exact-route coverage and should remain the source for the dedicated OpenAPI PR. - The living log is intentionally detailed and large. It is useful for reproducibility but adds documentation weight. - No UI changes are intended; screenshots are not applicable. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5-based coding agent in Codex desktop. Exact served model/context-window identifier was not exposed in the local app. Work used shell/Git/GitHub CLI tooling, local source inspection, targeted test execution, and live isolated Paperclip CLI/API smoke testing. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Devin Foley <devin@devinfoley.com>
127 KiB
127 KiB
2026-05-24 CLI API Parity E2E Log
Scope
Full Paperclip CLI/API parity smoke pass against a disposable local source-tree instance.
Isolation Contract
- Repo:
/Users/aronprins/Documents/PaperclipAI/paperclip - Scratch root:
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity PAPERCLIP_HOME:/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/homePAPERCLIP_INSTANCE_ID:cli-api-parityPAPERCLIP_CONFIG:/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.jsonPAPERCLIP_CONTEXT:/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/context.jsonPAPERCLIP_AUTH_STORE:/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/auth.jsonPAPERCLIP_API_URL:http://127.0.0.1:3197PAPERCLIP_SERVER_PORT:3197PORT:3197CODEX_HOME:/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/codex-homeCLAUDE_HOME:/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/claude-homeDATABASE_URL: unsetDATABASE_MIGRATION_URL: unset
Current IDs
- Company ID:
12e9db4b-f66c-459b-959e-d645002240fb - Imported Company ID:
0bdc6f69-733d-4b1c-b5c6-2246f9582598(deleted from DB) - Agent ID:
1dd601a1-031a-4225-b005-419427fd059f - Goal ID:
5b2a9135-1044-48d6-a17d-6b91dd9fdc74 - Project ID:
d32032ce-d95e-4c4e-a942-dd98498025fb - Issue ID:
f0250734-95f1-4c28-9e10-f1954649fffb(CLI-1) - Checkout/release Issue ID:
1f7540d3-a3d3-48d2-b6c5-00d72c064e8f - Prompt Issue ID:
38b89e46-a775-43bc-a39a-c44ccd1f7f30 - Board token ID:
45d843a2-9334-4dda-b53a-cd6f7e62149a(revoked) - Agent token ID:
d464c3fe-c760-4c1c-b6cd-f8f0cd6c1797(revoked)
Command Log
2026-05-24T11:06:22+02:00 - Read runbook and docs
- Command:
sed -n ... paperclip-localdev-runbook.md,doc/DEVELOPING.md,doc/CLI.md,doc/DATABASE.md,doc/GOAL.md,doc/PRODUCT.md,doc/SPEC-implementation.md,doc/DEPLOYMENT-MODES.md,doc/plans/2026-05-23-cli-api-parity-openapi-reference.ts - Purpose: Establish the required isolated local-dev workflow and CLI/API parity reference.
- Prerequisites/IDs used: none.
- Expected result: Docs confirm scratch home, non-default port, embedded DB, and CLI command shapes.
- Actual result: Runbook requires explicit scratch paths, port
3197, unset database env vars,pnpm paperclipai onboard --yes --run --bind loopback, and pre-test isolation checks. - Status: PASS.
- Output summary: No destructive command run yet.
doc/bugsdid not exist, so this file defines the log format. - Follow-up: Start isolated instance only after environment verification.
2026-05-24T11:06:22+02:00 - Pre-start isolation check
- Command:
env -u DATABASE_URL -u DATABASE_MIGRATION_URL ... zsh -lc 'printf ...';lsof -nP -iTCP:3197 -sTCP:LISTEN || true - Purpose: Confirm all required environment variables resolve to the scratch instance and the non-default server port is free.
- Prerequisites/IDs used: none.
- Expected result: All Paperclip/Codex/Claude paths point under
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity;DATABASE_URLandDATABASE_MIGRATION_URLare unset; port3197has no listener. - Actual result: All required variables matched the isolation contract, database URLs were
<unset>, and no listener was present on3197. - Status: PASS.
- Output summary: No references to
~/.paperclip,~/.codex,~/.claude, orlocalhost:3100. - Follow-up: Start Paperclip with the runbook command.
2026-05-24T11:06:45+02:00 - Start isolated instance
- Command:
env -u DATABASE_URL -u DATABASE_MIGRATION_URL ... pnpm paperclipai onboard --yes --run --bind loopback - Purpose: Create and start the disposable source-tree Paperclip instance.
- Prerequisites/IDs used: scratch env from Isolation Contract.
- Expected result: Onboarding writes config,
.env, secrets key, logs, storage, and embedded DB under the scratch instance; server listens on127.0.0.1:3197. - Actual result: Server started in
local_trusted/privatemode on127.0.0.1:3197, with embedded PostgreSQL data at/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/db. - Status: PASS.
- Output summary: Doctor passed 9 checks. Server selected embedded PostgreSQL port
54330after54329was already in use. Health URL:http://127.0.0.1:3197/api/health. - Follow-up: Run second-shell isolation checks before parity mutations.
2026-05-24T11:07:15+02:00 - Verify started instance isolation
- Command:
pnpm paperclipai env;pnpm paperclipai context show --json;curl -sS http://127.0.0.1:3197/api/health;find tmp/cli-api-parity/home -maxdepth 4 -type d - Purpose: Confirm the CLI and API target the disposable instance.
- Prerequisites/IDs used: isolated env; server session from previous step.
- Expected result: Config/context/auth paths are scratch paths; context path is scratch; health succeeds on
127.0.0.1:3197; DB directory is under scratch home. - Actual result: Config path, context path, storage path, secrets key path, and DB directory all resolve under
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity; health returnedstatus: ok, version0.3.1,deploymentMode: local_trusted,companyDeletionEnabled: true. - Status: PASS.
- Output summary:
paperclipai envredacted here because it prints the generatedPAPERCLIP_AGENT_JWT_SECRET. Context existed at the scratch path with an emptydefaultprofile. - Follow-up: Set API context and begin CLI parity checks.
2026-05-24T11:08:20+02:00 - Basic context/auth/connectivity
- Command:
pnpm paperclipai context set --api-base http://127.0.0.1:3197 --use --json;pnpm paperclipai whoami --json;pnpm paperclipai company list --json;pnpm paperclipai access whoami --json - Purpose: Exercise context setup/show, auth/access identity, and initial company listing.
- Prerequisites/IDs used: isolated env; no company ID yet.
- Expected result: Context stores non-default API base;
whoamireports the implicit local board; company list is empty; documentedaccess whoamieither works or reveals current command drift. - Actual result:
context set --api-basewroteapiBase: http://127.0.0.1:3197;whoamireturnedlocal-boardwithisInstanceAdmin: true; company list returned[];access whoamifailed withunknown command 'access'. - Status: PASS with docs/runbook mismatch.
- Output summary: Current CLI exposes
whoamias a top-level command. The runbook/docs commandaccess whoamiis stale for this checkout. - Follow-up: Use top-level
whoamifor access checks and record the mismatch below.
2026-05-24T11:09:14+02:00 - Company create/get/update/context
- Command:
pnpm paperclipai company create --payload-json '{"name":"CLI API Parity Test","description":"Disposable company for CLI API parity testing","goal":"Exercise the CLI API surface end to end"}' --json;pnpm paperclipai context set --company-id 12e9db4b-f66c-459b-959e-d645002240fb --use --json;pnpm paperclipai company get 12e9db4b-f66c-459b-959e-d645002240fb --json;pnpm paperclipai company update 12e9db4b-f66c-459b-959e-d645002240fb --payload-json '{"description":"Updated by CLI API parity test","budgetMonthlyCents":12345}' --json - Purpose: Exercise company creation, retrieval, update, and default company context.
- Prerequisites/IDs used: board identity; API base context.
- Expected result: Company is created, can be fetched, update persists, and context keeps both
apiBaseandcompanyId. - Actual result: Company create/get/update succeeded. Created company
12e9db4b-f66c-459b-959e-d645002240fb. Update changed description andbudgetMonthlyCentsto12345.context set --company-idunexpectedly removed the previously storedapiBase. - Status: PASS with fixed bug.
- Output summary: Company issue prefix is
CLI; status isactive. - Follow-up: Fix the context profile merge bug before continuing so later commands cannot fall back to
localhost:3100.
2026-05-24T11:11:00+02:00 - Fix and verify context profile merge
- Command: edited
cli/src/commands/client/context.ts,cli/src/client/context.ts, andcli/src/__tests__/context.test.ts;pnpm exec vitest run cli/src/__tests__/context.test.ts;pnpm --dir cli typecheck;pnpm paperclipai context set --api-base http://127.0.0.1:3197 --company-id 12e9db4b-f66c-459b-959e-d645002240fb --use --json;pnpm paperclipai context show --json - Purpose: Preserve existing context profile fields when setting a subset of fields.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb. - Expected result: Undefined patch fields do not erase existing profile values; context keeps both
apiBaseandcompanyId. - Actual result: Targeted Vitest context test passed; CLI typecheck passed; scratch context now contains both
apiBase: http://127.0.0.1:3197andcompanyId: 12e9db4b-f66c-459b-959e-d645002240fb. - Status: PASS.
- Output summary: Added regression coverage for undefined context patch fields.
- Follow-up: Continue parity testing.
2026-05-24T11:14:05+02:00 - Core domain CRUD and issue comments
- Command:
dashboard get;goal list/create/get/update;project list/create/get/update;agent list/create/get/update/configuration;issue list/create/get/update/comment/comments/comment:get/checkout;activity list - Purpose: Exercise core company-scoped CLI/API parity with JSON outputs and captured IDs.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; context profile with scratchapiBase; process adapter agent payload. - Expected result: Goal, agent, project, and issue CRUD succeeds; comments can be created and read; checkout succeeds for a todo issue.
- Actual result: Goal
5b2a9135-1044-48d6-a17d-6b91dd9fdc74, agent1dd601a1-031a-4225-b005-419427fd059f, projectd32032ce-d95e-4c4e-a942-dd98498025fb, issuef0250734-95f1-4c28-9e10-f1954649fffb, and comment231fd48a-9ed2-4e72-a3dc-3b762842f57dwere created/updated/read successfully. Explicit checkout of the first issue failed with 409 because assigning it at creation triggered automatic local process runs and checkout first. - Status: PASS with expected concurrency conflict.
- Output summary: The assigned
processadapter agent ran automatically and generated heartbeat runs. The issue later moved toblockedvia recovery handling because the smoke process printed output without a concrete Paperclip disposition. - Follow-up: Create a second unassigned issue for an uncontended checkout/release command test.
2026-05-24T11:15:41+02:00 - Issue checkout/release
- Command:
issue create --status todowithout assignee;issue checkout 1f7540d3-a3d3-48d2-b6c5-00d72c064e8f --agent-id 1dd601a1-031a-4225-b005-419427fd059f --expected-statuses todo --json;issue release 1f7540d3-a3d3-48d2-b6c5-00d72c064e8f --json - Purpose: Exercise atomic checkout and release semantics without automatic assignment races.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f; projectd32032ce-d95e-4c4e-a942-dd98498025fb; goal5b2a9135-1044-48d6-a17d-6b91dd9fdc74. - Expected result: Checkout moves issue to
in_progressand assigns the agent; release moves issue totodoand clears assignee. - Actual result: Checkout returned
status: in_progresswith the expected agent ID; release returnedstatus: todowithassigneeAgentId: null. - Status: PASS.
- Output summary: Issue
1f7540d3-a3d3-48d2-b6c5-00d72c064e8f. - Follow-up: Exercise token flows.
2026-05-24T11:16:43+02:00 - Board and agent token lifecycle
- Command:
token board create --company-id ... --name cli-parity-board --never-expires --json;token board list --json;whoami --api-key <board-token> --json;token agent create --company-id ... --agent ... --name cli-parity-agent --json;token agent list --company-id ... --agent ... --json;context set --profile cli-agent --persona agent ... --api-key-env-var-name PAPERCLIP_API_KEY --json;agent me --profile cli-agent --json;agent inbox --profile cli-agent --json;issue list --profile cli-agent --company-id ... --json;company list --profile cli-agent --json;token agent revoke ...;token board revoke ... - Purpose: Exercise board token creation/use/list/revoke; agent token creation/list/use/revoke; verify agent tokens cannot use board-only company list.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f. - Expected result: Board token works for
whoami; agent token works for agent persona commands and company-scoped issue list; board-only command fails with clear 403; both tokens are revoked. - Actual result: Board token
45d843a2-9334-4dda-b53a-cd6f7e62149awas listed andwhoamireportedsource: board_key. Agent tokend464c3fe-c760-4c1c-b6cd-f8f0cd6c1797was listed;agent me,agent inbox, and issue list succeeded;company listfailed withAPI error 403: Board access required; both tokens were revoked and later list output showedrevokedAt. - Status: PASS.
- Output summary: Plaintext token values were captured only in shell variables and were not written to repo files or this log.
- Follow-up: Exercise prompt/wake/run and safe ancillary surfaces.
2026-05-24T11:18:06+02:00 - Prompt, wake, runs, and ancillary safe surfaces
- Command:
board prompt --company-id ... --agent ... --title "CLI parity prompt issue" --no-wake ... --json;agent wake ... --reason "cli parity wake smoke" --payload '{"source":"cli-api-parity"}' --json;run list/get/events/log;dashboard get;activity list;cost summary;cost by-agent;finance summary;budget overview;secrets list/doctor/provider-configs;routine list;adapter list;plugin list;org get;agent-config list - Purpose: Exercise prompt handoff, wake/run inspection, and safe read-only activity/dashboard/cost/secrets/plugin/routine surfaces.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f. - Expected result: Prompt creates an issue without waking; wake creates/returns a run; run inspection endpoints work; safe list/read commands return JSON.
- Actual result: Prompt created issue
38b89e46-a775-43bc-a39a-c44ccd1f7f30; wake/run ID7b18a3ca-9875-4bfc-b910-db31deb2c0fa; run list returned 10 recent runs; activity returned 50 rows; secrets and routines were empty; adapter list returned 13 adapters; plugin list succeeded. - Status: PASS.
- Output summary: One transient UI/API background request for a just-created run log returned 404 and then succeeded on retry; direct CLI
run logfor the selected run succeeded. - Follow-up: Exercise import/export and destructive operations in scratch data.
2026-05-24T11:19:35+02:00 - Company export/import/delete and object deletes
- Command:
company export 12e9db4b-f66c-459b-959e-d645002240fb --out tmp/cli-api-parity/exports/company-package --include company,agents,projects,issues,skills --json;company import <export-dir> --target new --new-company-name "Imported Company" --yes --json;company get <imported-id> --json;company delete <imported-id> --yes --confirm <imported-id> --json; disposablegoal create/delete,project create/delete, andissue create/delete; final list checks. - Purpose: Exercise portability and destructive operations only in the isolated instance.
- Prerequisites/IDs used: original company
12e9db4b-f66c-459b-959e-d645002240fb. - Expected result: Export writes a package under scratch; import creates a new company; company delete removes the imported company; object delete commands remove disposable records.
- Actual result: Export wrote
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/exports/company-package; import created company0bdc6f69-733d-4b1c-b5c6-2246f9582598namedImported Company; company delete returnedok: true; final list checks confirmed the imported company and disposable goal/project/issue were absent. - Status: PASS.
- Output summary: Goal/project/issue delete commands return the deleted object rather than
{ ok: true }, so success was verified by final absence from list commands. - Follow-up: Run final lifecycle and verification checks.
2026-05-24T11:20:45+02:00 - Agent pause/resume and final checks
- Command:
agent pause 1dd601a1-031a-4225-b005-419427fd059f --json;agent resume 1dd601a1-031a-4225-b005-419427fd059f --json;agent get ... --json; finalcurl /api/health;token board list;token agent list;git status --short; targeted verification commands. - Purpose: Exercise agent pause/resume and confirm final service/token/code state.
- Prerequisites/IDs used: agent
1dd601a1-031a-4225-b005-419427fd059f. - Expected result: Agent pauses and resumes; health remains OK; tokens remain revoked; only expected repo files changed.
- Actual result: Pause returned
paused, resume returnedidle, final agent status isidle; health returnedstatus: ok; board and agent tokens showrevokedAt; git status shows only the context fix and this log. - Status: PASS.
- Output summary: Server remains running on
127.0.0.1:3197. - Follow-up: Hand off summary and restart instructions.
2026-05-24T11:26:43+02:00 - Resume verification before commit
- Command:
git status --short --branch;curl -sS http://127.0.0.1:3197/api/health;git diff --stat;pnpm exec vitest run cli/src/__tests__/context.test.ts;pnpm --dir cli typecheck - Purpose: Re-establish current worktree/server state before committing the fixed bug and continuing the broader CLI parity loop.
- Prerequisites/IDs used: isolated server on
127.0.0.1:3197; branchimprovement/cli-api-parity. - Expected result: Server remains healthy; worktree contains only the intended context fix and living log; focused test and CLI typecheck pass.
- Actual result: Health returned
status: ok; worktree showed modifications tocli/src/__tests__/context.test.ts,cli/src/client/context.ts,cli/src/commands/client/context.ts, and newdoc/bugs/; context Vitest file passed 5 tests;pnpm --dir cli typecheckpassed. - Status: PASS.
- Output summary: No additional files changed before commit.
- Follow-up: Stage and commit the context fix plus parity log, then continue with full CLI inventory and remaining command coverage.
2026-05-24T11:28:30+02:00 - Commit context fix
- Command:
git add cli/src/__tests__/context.test.ts cli/src/client/context.ts cli/src/commands/client/context.ts doc/bugs/2026-05-24-cli-api-parity-e2e-log.md;git commit -m "Fix CLI context profile patching" - Purpose: Persist the verified context isolation fix before continuing broader parity testing.
- Prerequisites/IDs used: focused context test and CLI typecheck from previous entry.
- Expected result: Commit contains only the context patching fix and living parity log.
- Actual result: Commit
1da21a91created with 4 files changed. - Status: PASS.
- Output summary: The working tree was clean immediately after this commit.
- Follow-up: Continue full CLI inventory and commit each subsequent fix after focused verification.
2026-05-24T11:30:29+02:00 - Approval and issue subresource partial pass
- Command:
approval create/list/get/comment/request-revision/resubmit/approve/reject;issue approvals/approval:link/approval:unlink;issue read/unread/archive/unarchive;issue child:create/get;issue document:put/get/lock/unlock/revisions/restore;issue work-product:create/list/update/delete - Purpose: Exercise approval lifecycle and issue subresource CLI/API parity with JSON outputs.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; issuef0250734-95f1-4c28-9e10-f1954649fffb; projectd32032ce-d95e-4c4e-a942-dd98498025fb; goal5b2a9135-1044-48d6-a17d-6b91dd9fdc74. - Expected result: Approval lifecycle commands mutate and read approvals; issue markers, child creation, documents, and work products succeed.
- Actual result: Approval lifecycle succeeded. Created/approved approval
c7f19d1c-fcb3-4e4d-87a7-e8a248a9eb09; created/rejected approvalbbcfb3ae-38f1-43b0-8f9f-0661e291f29c; linked and unlinked issue approvals successfully. Issue read/unread/archive/unarchive succeeded. Child issue6e78d443-c9f4-46ba-9137-f1fa2b7a75c5was created and fetched. Document create/get/lock/unlock/update/revisions/restore succeeded after supplying--base-revision-id; work product create/list/update/delete succeeded. - Status: PASS with docs/operator learning.
- Output summary: A first document update attempt without
--base-revision-idfailed withAPI error 409: Document update requires baseRevisionId; help/source confirmed the flag exists and is required for updates. - Follow-up: Continue interactions, tree holds, attachments, labels, feedback, and recovery checks.
2026-05-24T11:36:54+02:00 - Fix optional interaction accept keys
- Command:
issue interaction:create;issue interaction:accept <issue-id> <interaction-id>without--selected-client-keys; editedcli/src/commands/client/issue.tsandcli/src/__tests__/issue-subresources.test.ts;pnpm exec vitest run cli/src/__tests__/issue-subresources.test.ts;pnpm --dir cli typecheck - Purpose: Verify and fix request-confirmation acceptance without optional selected task keys.
- Prerequisites/IDs used: issue
f0250734-95f1-4c28-9e10-f1954649fffb. - Expected result: Omitting optional
--selected-client-keyssends noselectedClientKeysfield. - Actual result: Before the fix, the CLI sent
selectedClientKeys: []and local validation failed withArray must contain at least 1 element(s). After the fix, the focused issue subresource test passed 4 tests and CLI typecheck passed. - Status: PASS with fixed bug.
- Output summary: The command now preserves
undefinedfor omitted optional CSV input while still parsing provided CSV values. - Follow-up: Commit this fix before continuing, per user instruction.
2026-05-24T11:39:47+02:00 - Interaction lifecycle and tree hold retry
- Command:
issue interaction:create/accept/reject/respond/cancel;issue tree-state;issue tree-preview;issue tree-hold:create/list/get/release - Purpose: Exercise issue interaction lifecycle and tree control commands.
- Prerequisites/IDs used: issue
f0250734-95f1-4c28-9e10-f1954649fffb. - Expected result: Request confirmation accept/reject succeeds; question respond/cancel succeeds; tree hold create/list/get/release succeeds.
- Actual result: Request confirmation accept/reject succeeded. Ask-user-question respond succeeded.
interaction:cancelonly works forask_user_questions; trying it againstrequest_confirmationreturnedAPI error 422: Only ask_user_questions interactions can be cancelled. A corrected ask-user-question cancel succeeded. Tree hold create/list succeeded, but my script initially parsed the create response as.id; the API returns.hold.id, so the subsequent get used literalnulland the server returned 500. - Status: PASS with fixed server hardening and command UX mismatch.
- Output summary: Active tree hold
8f07dd71-092f-4746-9b6d-27bbb086b305was later fetched and released using the correct.hold.id/list-derived ID. - Follow-up: Harden tree hold routes so malformed hold IDs return 400 instead of database 500; log
interaction:cancelkind-specific UX mismatch.
2026-05-24T11:41:28+02:00 - Fix malformed tree hold ID 500
- Command: edited
server/src/routes/issue-tree-control.tsandserver/src/__tests__/issue-tree-control-routes.test.ts;pnpm exec vitest run server/src/__tests__/issue-tree-control-routes.test.ts;pnpm --dir server typecheck - Purpose: Prevent malformed tree hold IDs from reaching PostgreSQL UUID comparisons.
- Prerequisites/IDs used: reproduction path
/api/issues/<issue-id>/tree-holds/null. - Expected result: Invalid hold IDs return a client error and do not call the tree hold service.
- Actual result: Focused route test passed 9 tests; server typecheck passed.
- Status: PASS with fixed bug.
- Output summary: Both
GET /tree-holds/nullandPOST /tree-holds/null/releasenow validate UUID shape and return 400. - Follow-up: Commit this fix before continuing, per user instruction.
2026-05-24T11:43:22+02:00 - Attachments, labels, and feedback retry
- Command:
issue tree-hold:get/release;issue attachment:upload/list/download/delete;issue label:create/list/delete;issue feedback:vote/votes/list/export;token agent create/revoke - Purpose: Resume the subresource pass after fixing the tree hold script shape and route hardening.
- Prerequisites/IDs used: issue
f0250734-95f1-4c28-9e10-f1954649fffb; tree hold8f07dd71-092f-4746-9b6d-27bbb086b305; company12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f. - Expected result: Active hold is released; attachment upload/download round trip matches bytes; label lifecycle succeeds; feedback vote succeeds against a valid target.
- Actual result: Tree hold get/release succeeded. Attachment upload/list/download/delete succeeded and
cmpverified downloaded bytes. Label create/list/delete succeeded. Feedback vote against board-authored comment failed withAPI error 422: Feedback voting is only available on agent-authored issue comments. A retry that created an isolated temporary agent tokena67f4f69-7250-43d6-9988-96e7692da605still failed becauseissue comment --api-key <agent-token>did not produce an agent-authored feedback target. The temporary token was revoked immediately after the failure. - Status: PARTIAL.
- Output summary: No plaintext token values were written to this log. Token
a67f4f69-7250-43d6-9988-96e7692da605is revoked. - Follow-up: Inspect agent-authored comment command/auth semantics before retrying feedback voting.
2026-05-24T11:44:45+02:00 - Commit issue subresource fixes
- Command:
git add cli/src/__tests__/issue-subresources.test.ts cli/src/commands/client/issue.ts server/src/__tests__/issue-tree-control-routes.test.ts server/src/routes/issue-tree-control.ts doc/bugs/2026-05-24-cli-api-parity-e2e-log.md;git commit -m "Fix CLI issue subresource parity bugs" - Purpose: Persist verified fixes immediately after focused verification, per user instruction.
- Prerequisites/IDs used:
pnpm exec vitest run cli/src/__tests__/issue-subresources.test.ts;pnpm --dir cli typecheck;pnpm exec vitest run server/src/__tests__/issue-tree-control-routes.test.ts;pnpm --dir server typecheck. - Expected result: Commit contains only the optional interaction accept fix, malformed tree hold ID hardening, tests, and updated parity log.
- Actual result: Commit
73997628created with 5 files changed. - Status: PASS.
- Output summary: No plaintext tokens included in the commit.
- Follow-up: Continue parity testing and commit future fixes immediately after focused verification.
2026-05-24T11:46:46+02:00 - Feedback and recovery completion
- Command:
token agent create;issue comment --api-key <agent-token>;issue feedback:vote;issue feedback:votes;issue feedback:list;issue feedback:export;token agent revoke;issue recovery-actions;issue recovery:resolve - Purpose: Complete feedback voting/export and recovery resolution after the earlier invalid target and output-shape mistakes.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f; issuef0250734-95f1-4c28-9e10-f1954649fffb. - Expected result: Feedback vote is saved against an agent-authored target; feedback list/export work; temporary token is revoked; active recovery action resolves.
- Actual result: Correctly reading
token agent createoutput from.key.tokenproduced agent-authored commentd4e2adbe-d94c-4d87-8205-828f3ddfa033; feedback vote24843ebd-456d-4534-89ec-bdbc0bb02170was saved; feedback list/export completed. Temporary token40e683ec-758f-4964-bdef-544bee16ee5awas revoked. Recovery action1151475f-c97f-456b-9c6a-8e0f936abe05resolved after using--source-issue-status todo; the issue moved totodo. - Status: PASS with command output-shape learning and help mismatch.
- Output summary: A parser mistake against feedback output (
.vote.idinstead of top-level.id) stopped one script after the vote succeeded; the token was manually revoked and the remaining list/export commands were run separately. - Follow-up: Record recovery help mismatch and continue remaining CLI domains.
2026-05-24T11:50:09+02:00 - Restart isolated server after committed fixes
- Command:
kill <paperclip pid on 3197>;pnpm paperclipai onboard --yes --run --bind loopback;curl http://127.0.0.1:3197/api/health;issue tree-hold:get <issue-id> null --json - Purpose: Restart the disposable server so the committed server-side malformed hold ID fix is active in the running instance.
- Prerequisites/IDs used: scratch env from Isolation Contract; committed fix
73997628. - Expected result: Server restarts with the same scratch home/config/DB and returns 400 for malformed hold IDs.
- Actual result: Server restarted on
127.0.0.1:3197, using the same embedded DB path and pg port54330; health returnedstatus: ok; malformed hold ID now returnsAPI error 400: Invalid hold ID. - Status: PASS.
- Output summary: No real
~/.paperclip,~/.codex, or~/.claudepaths were used. The server session is currently running under the isolated environment. - Follow-up: Continue remaining CLI domains.
2026-05-24T11:52:20+02:00 - Advanced agent command pass
- Command: disposable
agent create/list/get/update/delete;agent permissions:update;agent configuration;agent config-revisions;agent config-revision:get;agent runtime-state;agent runtime-state:reset-session;agent task-sessions;agent skills;agent skills:sync;agent instructions-path:update;agent instructions-bundle;agent instructions-bundle:update;agent instructions-file:get/put/delete;agent local-cli --no-install-skills;agent approve/pause/resume/heartbeat:invoke/terminate;token agent revoke - Purpose: Exercise advanced agent lifecycle, runtime, instructions, skills, and local CLI token flows on a disposable agent.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; temp agentf9dfad96-6045-4b97-a548-bdc95fb22ec4. - Expected result: Commands succeed without mutating the main parity worker; any token created by
local-cliis revoked; temp agent is deleted. - Actual result: Advanced agent commands passed after adapting
instructions-path:updatefor process adapter constraints.agent local-cli --no-install-skillscreated keya9bf0b28-8217-4c60-829c-cb1962203a21, which was revoked.agent heartbeat:invokepassed. Temp agentf9dfad96-6045-4b97-a548-bdc95fb22ec4was terminated and deleted. A final key list for the main agent showed no unrevoked keys. - Status: PASS with command UX mismatch.
- Output summary: First
instructions-path:updateattempt withoutadapterConfigKeyfailed withNo default instructions path key for adapter type 'process'. Provide adapterConfigKey.A second relative-path attempt withadapterConfigKeyfailed because process adapters withoutcwdrequire an absolute path. The successful pass usedadapterConfigKey: instructionsFilePathand an absolute scratch path. - Follow-up: Record instructions-path UX mismatch and continue cost/finance/budget/access/admin domains.
2026-05-24T11:57:20+02:00 - Cost, finance, and budget command pass
- Command:
cost event:create;cost summary;cost by-agent;cost by-agent-model;cost by-provider;cost by-biller;cost by-project;cost window-spend;cost quota-windows;cost issue;finance event:create;finance events;finance summary;finance by-biller;finance by-kind;budget overview;budget policy:upsert;budget company:update;budget agent:update - Purpose: Exercise cost/finance event creation, rollups, issue cost lookup, and budget policy/update flows.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f; issuef0250734-95f1-4c28-9e10-f1954649fffb; projectd32032ce-d95e-4c4e-a942-dd98498025fb; goal5b2a9135-1044-48d6-a17d-6b91dd9fdc74. - Expected result: Cost and finance events are recorded; all rollup commands return JSON; budget updates work and are restored.
- Actual result: Cost event
63d757ae-a7f4-40e1-8ee8-e7d3174be1a4and finance eventbd38c196-7598-4591-8750-f992d4d9babfwere created. All listed cost/finance read commands succeeded. Budget policy upsert succeeded. Company budget was changed to23456then restored to12345; agent budget was changed to4321then restored to0. - Status: PASS.
- Output summary:
budget incident:resolvewas not run because no budget incident was created by this safe smoke path. - Follow-up: Continue access/profile/invite/admin/instance/sidebar/inbox/auth domains.
2026-05-24T12:02:45+02:00 - Access, profile, invite, admin, instance, sidebar, inbox, and auth challenge pass
- Command:
whoami;auth whoami;profile session/get/update/company-user;invite create/list/show/onboarding/onboarding:text/skills:index/skill/logo/revoke;join list/reject;member list/user-directory/update/permissions/role-and-grants/archive;admin user list/company-access/company-access:update;instance scheduler-heartbeats/settings:general/settings:general:update/settings:experimental/settings:experimental:update/database-backup;sidebar preferences/preferences:update/project-preferences/project-preferences:update/badges;inbox dismissals/dismiss;auth challenge create/get/cancel/approve;auth logout - Purpose: Exercise board access, current profile, disposable invite, member/admin, instance settings, sidebar, inbox, and auth challenge surfaces.
- Prerequisites/IDs used: company
12e9db4b-f66c-459b-959e-d645002240fb; member373f91e2-a433-46ee-8362-e61ab5e06593; userlocal-board; projectd32032ce-d95e-4c4e-a942-dd98498025fb; approvalc7f19d1c-fcb3-4e4d-87a7-e8a248a9eb09. - Expected result: Read commands return JSON; no-op updates preserve scratch user/company access; disposable invites/challenges are revoked/cancelled/approved; unsafe self-removal is rejected.
- Actual result: Identity/profile/session commands passed. Profile update preserved name
Board. Disposable inviteb3317c94-4e46-4ceb-9a5f-6df179c4f77ewas created, inspected through show/onboarding/onboarding text/skills index/skill, then revoked.invite logowas treated as optional because the company has no logo. Join list passed; two disposable pending join requests were rejected during cleanup. Member list/user-directory/update/permissions/role-and-grants passed; self archive returned expected403: You cannot remove yourself. Admin user list/company-access/company-access:update passed with the same company ID. Instance settings read/no-op update and database backup passed. Sidebar preferences/project preferences/badges and inbox dismissal passed. Auth challenge cancela52af778-39c1-41a4-8f87-46fd7b100d16and approve70b51e40-e6d4-4e01-ae5d-16734897375epassed.auth logoutcompleted safely against the isolated auth store. - Status: PASS with expected negative path and mismatches.
- Output summary:
invite test-resolutionfailed because the CLI does not provide the API-requiredurlquery.join approveon a disposable agent join request failed with409: Join request cannot be approved because this company has no active CEO; the request was rejected afterward. - Follow-up: Continue public catalog/LLM docs, adapter/environment/workspace/asset/skill/plugin/setup command domains.
2026-05-24T12:04:55+02:00 - Public catalog and LLM docs command check
- Command:
openapi;available-skill list;available-skill index;available-skill get cmux;llm agent-configuration;llm agent-icons;llm agent-configuration:adapter process - Purpose: Exercise OpenAPI, public skill catalog, and LLM prompt documentation CLI surfaces.
- Prerequisites/IDs used: isolated server on
127.0.0.1:3197. - Expected result: Commands return JSON or text for registered public routes.
- Actual result:
available-skill listandavailable-skill indexpassed.openapireturnedAPI error 404: API route not found.available-skill get cmuxreturnedAPI error 404: Skill not foundeven thoughcmuxwas returned byavailable-skill list.llm agent-configuration,llm agent-icons, andllm agent-configuration:adapter processreturnedAPI error 404: API route not found. - Status: PARTIAL with missing route/route mismatch issues.
- Output summary: These look like CLI/API parity gaps rather than test data problems; no code fix was applied yet.
- Follow-up: Record mismatches and continue remaining command domains.
2026-05-24T12:10:10+02:00 - Adapter, environment, project workspace, plugin coverage
- Command:
curl -sf http://127.0.0.1:3197/api/health;pnpm paperclipai health --json;pnpm paperclipai adapter list/get/config-schema/ui-parser/models/model-profiles/detect-model/test-environment ... --json;pnpm paperclipai environment list/capabilities/probe-config/create ... --json;pnpm paperclipai project-workspace create/list/update/delete ... --json;pnpm paperclipai workspace list --company-id ... --json;pnpm paperclipai plugin list/examples/ui-contributions/tools/init ... --json - Purpose: Cover remaining adapter, environment/workspace, and plugin command families with safe disposable state.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; projectd32032ce-d95e-4c4e-a942-dd98498025fb; isolated APIhttp://127.0.0.1:3197. - Expected result: API health passes; registered CLI commands map to supported routes; disposable project workspace can be created, updated, and deleted; plugin read-only routes and scaffold init work.
- Actual result: API health passed.
paperclipai healthis not registered. Adapter list/get/model commands passed forprocess;processconfig schema and UI parser returned expected unsupported 404s.adapter test-environment processreturned a structured failure because no process command was supplied. Environment list/capabilities/probe-config passed, but creating a second local environment returned a 500 due to the uniqueenvironments_company_driver_idxconstraint. Project workspace create/list passed; the first update/delete attempt failed because my shell ID extraction broke, then the workspace was recovered fromproject-workspace listand deleted successfully withproject-workspace delete d32032ce-d95e-4c4e-a942-dd98498025fb e271b6bc-368e-4a89-9824-d9e2b2bedb66 --json. Workspace list passed. Plugin list/examples/ui-contributions/tools passed;plugin initscaffolded a disposable plugin undertmp/cli-api-parity/artifacts/cli-parity-plugin. - Status: MIXED.
- Output summary: New mismatches/bugs recorded as
MISMATCH-008andBUG-004. No external plugin install was attempted; no built-in adapter delete/reinstall was attempted. - Follow-up: Fix the duplicate local environment 500 and restart the isolated server before rerunning the failing CLI command against live code.
2026-05-24T12:12:50+02:00 - Asset and company skill coverage
- Command:
pnpm paperclipai asset image:upload --company-id <company-id> --file doc/assets/avatars/zinc.png --namespace cli-parity --alt ... --title ... --json;pnpm paperclipai asset content <asset-id> --out tmp/cli-api-parity/artifacts/asset-download.png --json;pnpm paperclipai asset logo:upload --company-id <company-id> --file ui/public/favicon-32x32.png --json;pnpm paperclipai skill list/create/get/file/file:update/update-status/install-update/delete/scan-projects ... --json - Purpose: Cover asset upload/download/logo and company skill CRUD/file commands with disposable resources.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; image asset829fbd86-cd5c-4aaa-ad17-276faac7888b; logo asset1b3e7979-1359-4361-b3f5-c8a845e11659; temporary skill126ad416-864b-4136-8f48-f5adcf324f20. - Expected result: Image upload returns an asset ID; content download writes bytes; logo upload succeeds; local skill create/get/file/update/delete works; update check reports unsupported for local skills.
- Actual result: Image upload returned
assetIdand content download wrote27949bytes. Logo upload returnedassetId. Skill list/create/get/file/file:update/update-status/delete/scan-projects passed.skill install-updatereturned422: Only GitHub-managed skills support update checks, matching the precedingupdate-status supported: falseresult. - Status: PASS with expected negative check.
- Output summary: Temporary local skill was deleted. Uploaded image/logo assets remain in the disposable scratch storage as part of the test instance.
- Follow-up: None for asset/skill surface.
2026-05-24T12:13:24+02:00 - Fix duplicate local environment create error
- Command:
pnpm exec vitest run server/src/__tests__/environment-routes.test.ts;pnpm --dir server typecheck - Purpose: Verify the route-level fix for duplicate local environment creation before committing.
- Prerequisites/IDs used:
BUG-004reproduction from isolated E2E. - Expected result: Creating a second local environment returns a controlled conflict instead of leaking a database unique constraint as a 500.
- Actual result: Focused route suite passed with 31 tests; server typecheck passed.
- Status: PASS.
- Output summary: Added a pre-insert
localenvironment conflict check and regression coverage. - Follow-up: Commit immediately, then restart the isolated server and rerun the failing CLI command against the updated code.
2026-05-24T12:16:05+02:00 - Rerun duplicate local environment create on restarted server
- Command:
env -u DATABASE_URL -u DATABASE_MIGRATION_URL ... pnpm paperclipai environment create --company-id 12e9db4b-f66c-459b-959e-d645002240fb --payload-json '{"name":"CLI parity local env","description":"Disposable CLI parity environment","driver":"local","config":{"cwd":"/Users/aronprins/Documents/PaperclipAI/paperclip"}}' --json - Purpose: Verify
BUG-004against the restarted isolated source-tree server. - Prerequisites/IDs used: Same scratch env; server restarted with
pnpm paperclipai onboard --yes --run --bind loopback; company12e9db4b-f66c-459b-959e-d645002240fb. - Expected result: Controlled conflict instead of internal server error.
- Actual result: CLI returned
API error 409: A local environment already exists for this company. - Status: PASS.
- Output summary: Confirms the live CLI/API path now exercises the fixed route behavior.
- Follow-up: Continue remaining parity/fix pass.
2026-05-24T12:17:05+02:00 - Environment, plugin, and secrets lifecycle coverage
- Command:
pnpm paperclipai environment create/get/leases/probe/update/delete ... --json;pnpm paperclipai plugin install/list/inspect/health/config/jobs/local-folders/ui-contributions/disable/enable/uninstall ... --json;pnpm paperclipai secrets list/create/link/declarations/migrate-inline-env ... --json - Purpose: Add positive non-local environment coverage, plugin lifecycle coverage, and deeper secrets coverage.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; bundled plugin path/Users/aronprins/Documents/PaperclipAI/paperclip/packages/plugins/plugin-workspace-diff; temporary SSH environmentcc5ae311-13f5-42b8-8044-11065b4e1af0; temporary plugin installe8421ed5-c103-4950-afb7-1463a0fbb9c5; temporary secret20c74546-7bec-4766-80cd-0b6c57545f7d. - Expected result: SSH environment can be created, read, updated, and deleted; SSH probe can fail gracefully when local SSH is unavailable; bundled plugin can install and uninstall in the isolated instance; managed secret can be created and inspected through supported CLI flows.
- Actual result: SSH environment create/get/leases/update/delete passed; probe returned structured
ok: falsewith connection refused, as expected on this host. Plugin install/list/inspect/health/config/jobs/local-folders/ui-contributions/disable/enable/uninstall passed; final plugin list returned[]. Secret create/list/declarations/migrate-inline-env dry-run passed.secrets link --provider local_encrypted --external-ref ...returned400: local_encrypted does not support external reference secrets, which is expected provider behavior. The batch exposed missing CLI wrappers for secret update/rotate/usage/access-events/delete. - Status: MIXED.
- Output summary: New fixed parity gap recorded as
BUG-005. Plugin was uninstalled; SSH environment was deleted; one managed secret remained briefly for lifecycle verification. - Follow-up: Add missing secret lifecycle CLI commands, then update/rotate/inspect/delete the temporary secret through the new CLI paths.
2026-05-24T12:19:37+02:00 - Fix missing secret lifecycle CLI commands
- Command:
pnpm exec vitest run cli/src/__tests__/secrets.test.ts;pnpm --dir cli typecheck - Purpose: Verify the CLI wrappers for API-backed secret update, rotate, usage, access events, and delete.
- Prerequisites/IDs used:
BUG-005parity gap from OpenAPI reference and E2E. - Expected result: Commands map to
PATCH /api/secrets/:id,POST /api/secrets/:id/rotate,GET /api/secrets/:id/usage,GET /api/secrets/:id/access-events, andDELETE /api/secrets/:id. - Actual result: Focused CLI secrets test passed with 8 tests; CLI typecheck passed.
- Status: PASS.
- Output summary: Added destructive delete confirmation via
--yes --confirm <secret-id>. - Follow-up: Run new commands against temporary scratch secret.
2026-05-24T12:20:20+02:00 - Live-verify new secret lifecycle commands
- Command:
pnpm paperclipai secrets update 20c74546-7bec-4766-80cd-0b6c57545f7d --payload-json ... --json;pnpm paperclipai secrets rotate 20c74546-7bec-4766-80cd-0b6c57545f7d --value ... --json;pnpm paperclipai secrets usage 20c74546-7bec-4766-80cd-0b6c57545f7d --json;pnpm paperclipai secrets access-events 20c74546-7bec-4766-80cd-0b6c57545f7d --json;pnpm paperclipai secrets delete 20c74546-7bec-4766-80cd-0b6c57545f7d --yes --confirm 20c74546-7bec-4766-80cd-0b6c57545f7d --json;pnpm paperclipai secrets list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --json - Purpose: Verify fixed commands against the live disposable instance and clean up the temporary managed secret.
- Prerequisites/IDs used: Temporary secret
20c74546-7bec-4766-80cd-0b6c57545f7d. - Expected result: Update/rotate/usage/access-events/delete all succeed; final list is empty.
- Actual result: All new commands passed. Usage returned no bindings, access-events returned
[], delete returned{ "ok": true }, and final list returned[]. - Status: PASS.
- Output summary: No test secrets remain in the company after this verification.
- Follow-up: Commit the CLI fix and updated log.
2026-05-24T12:22:36+02:00 - Fix access, health, invite, join, and issue UX mismatches
- Command:
pnpm exec vitest run cli/src/__tests__/access-parity.test.ts cli/src/__tests__/issue-subresources.test.ts;pnpm --dir cli typecheck - Purpose: Verify CLI fixes for
MISMATCH-001,MISMATCH-002,MISMATCH-003,MISMATCH-005,MISMATCH-006, andMISMATCH-008. - Prerequisites/IDs used: Mismatches from earlier E2E batches.
- Expected result:
paperclipai healthexists;paperclipai access whoamiworks;invite test-resolutionhas a URL option;join list --status pendingmaps topending_approval; issue help text no longer overstates valid cancel/recovery inputs. - Actual result: Focused tests passed with 6 tests; CLI typecheck passed.
- Status: PASS.
- Output summary: Added a top-level health command, an
access whoamialias,invite test-resolution --url, pending status normalization, and more precise issue command descriptions. - Follow-up: Live-verify changed commands against scratch instance.
2026-05-24T12:23:25+02:00 - Live-verify access/health/invite/join fixes
- Command:
pnpm paperclipai health --json;pnpm paperclipai access whoami --json;pnpm paperclipai join list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --status pending --request-type agent --json;pnpm paperclipai invite create --company-id 12e9db4b-f66c-459b-959e-d645002240fb --payload-json '{}' --json;pnpm paperclipai invite test-resolution <token> --url https://example.com/invite/<token> --json;pnpm paperclipai invite revoke <invite-id> --json;pnpm paperclipai issue recovery:resolve --help;pnpm paperclipai issue interaction:cancel --help - Purpose: Verify fixed commands on the disposable instance and confirm help text updates.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; disposable invite57d7fb29-e29e-4327-9d11-7be325831da6revoked after test. A first test-resolution attempt againsthttp://127.0.0.1:3197/...intentionally hit the server's private-address guard and was replaced with a public HTTPS URL. - Expected result: Health and alias commands pass; pending alias is accepted; invite test-resolution sends the URL query and returns route data; help text mentions the narrower constraints.
- Actual result:
health,access whoami, andjoin list --status pendingpassed. Public invite resolution returnedstatus: reachable, methodHEAD, HTTP404fromexample.com, proving the command now supplies the URL. Invite was revoked. Help output includestodo, done, or in_review for restored outcomes; blocked is only valid for blocked outcomesandCancel an ask_user_questions issue thread interaction. - Status: PASS.
- Output summary: All fixed UX/parity paths are verified. No invite from this batch remains active.
- Follow-up: Commit this fix batch and continue unresolved docs/catalog parity gap investigation.
2026-05-24T12:28:46+02:00 - Fix LLM docs and available skill catalog isolation
- Command:
pnpm exec vitest run server/src/__tests__/llms-routes.test.ts cli/src/__tests__/access-parity.test.ts;pnpm --dir server typecheck;pnpm --dir cli typecheck - Purpose: Fix the docs/catalog subset of
MISMATCH-007that was straightforward and isolation-sensitive. - Prerequisites/IDs used: Isolated
CLAUDE_HOME=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/claude-home. - Expected result: CLI LLM commands reach mounted routes, and available skill discovery does not read the real
~/.claude/skillswhenCLAUDE_HOMEis set. - Actual result: Focused tests passed; server and CLI typechecks passed.
- Status: PASS.
- Output summary: Mounted
llmRoutesunder/apiin addition to the existing root mount. Updated available-skill discovery to readCLAUDE_HOME/skillswhen configured, include built-in Paperclip repo skills inavailable-skill list, and allowavailable-skill getfor safe listed/built-in skill names. - Follow-up: Restart isolated server and live-verify LLM docs plus available skill list/get behavior.
2026-05-24T12:30:05+02:00 - Live-verify LLM docs and available skill catalog isolation
- Command:
pnpm paperclipai llm agent-configuration --json;pnpm paperclipai llm agent-icons --json;pnpm paperclipai llm agent-configuration:adapter process --json;pnpm paperclipai available-skill list --json;pnpm paperclipai available-skill get paperclip --json;pnpm paperclipai available-skill get cmux --json;pnpm paperclipai openapi --json - Purpose: Verify docs/catalog fixes on the restarted disposable source-tree server.
- Prerequisites/IDs used: Same isolated env; server restarted after code changes.
- Expected result: LLM docs commands pass; built-in Paperclip skills are listed and fetchable; real-user
~/.claudeskills are not listed;openapistill documents the unresolved gap if no route exists. - Actual result: LLM docs commands passed.
available-skill listreturned Paperclip repo skills such asdiagnose-why-work-stopped;available-skill get paperclipreturned markdown.available-skill get cmuxnow returns 404 becausecmuxis no longer listed from the real Claude home.openapistill returns404: API route not found. - Status: MIXED.
- Output summary: Fixed the LLM route and available-skill isolation/list-get consistency parts of
MISMATCH-007;GET /api/openapi.jsonremains unresolved. - Follow-up: Commit scoped fixes and leave OpenAPI generation as the remaining docs/catalog parity gap.
2026-05-24T12:32:12+02:00 - Final cleanup and isolation verification
- Command: environment echo;
pnpm paperclipai health --json;pnpm paperclipai token board list --json;pnpm paperclipai token board revoke <redacted-board-token-id> --json;pnpm paperclipai token agent list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --agent 1dd601a1-031a-4225-b005-419427fd059f --json;pnpm paperclipai plugin list --json;pnpm paperclipai secrets list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --json;pnpm paperclipai environment list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --json;pnpm paperclipai project-workspace list d32032ce-d95e-4c4e-a942-dd98498025fb --json;pnpm paperclipai openapi --json - Purpose: Confirm the disposable instance remains isolated, clean up leftover tokens, and record final known gap.
- Prerequisites/IDs used: Isolated env from the Isolation Contract; board token
<redacted-board-token-id>; main agent1dd601a1-031a-4225-b005-419427fd059f. - Expected result: All env vars point under
tmp/cli-api-parity; database env vars remain unset; health passes; no active disposable tokens, plugins, secrets, project workspaces, or non-default environments remain; OpenAPI still fails as the documented unresolved gap. - Actual result: Env echoed the scratch paths and
DATABASE_URL/DATABASE_MIGRATION_URLas unset. Health passed. Board token list found one active key (<redacted-board-token-id>) from the earlier board-token test, which was revoked. Agent token list showed only revoked keys. Plugin list and secrets list returned empty arrays. Environment list contains the default local environment only. Project workspace list returned empty.openapistill returned404: API route not found. - Status: PASS with known OpenAPI gap.
- Output summary: No active API tokens created by this run remain. Scratch instance remains running on
http://127.0.0.1:3197. - Follow-up: Final report should call out
openapias unfixed and explain that implementing it needs a real OpenAPI generator/route rather than a small CLI wrapper correction.
2026-05-24T12:45:40+02:00 - Root setup and local maintenance command coverage
- Command:
pnpm paperclipai doctor --config <scratch-config>;pnpm paperclipai doctor --config <scratch-config> --repair --yes;pnpm paperclipai env --config <scratch-config>;pnpm paperclipai db:backup --config <scratch-config> --dir tmp/cli-api-parity/artifacts/root-setup/backups --retention-days 1 --filename-prefix cli-parity --json;pnpm paperclipai allowed-hostname cli-parity.test --config <scratch-config>;pnpm paperclipai auth bootstrap-ceo --config <scratch-config> --force --base-url http://127.0.0.1:3197;pnpm paperclipai auth whoami --json;pnpm paperclipai routines disable-all --config <scratch-config> --company-id 12e9db4b-f66c-459b-959e-d645002240fb --json;pnpm paperclipai env-lab doctor --instance cli-api-parity --json;pnpm paperclipai env-lab status --instance cli-api-parity --json - Purpose: Cover root/setup commands and local maintenance utilities against the disposable instance without touching real home state.
- Prerequisites/IDs used: Scratch config
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json; company12e9db4b-f66c-459b-959e-d645002240fb. - Expected result: Doctor and env introspection use scratch config; DB backup writes under scratch artifacts; allowed-hostname mutates only scratch config; bootstrap CEO is a no-op in
local_trusted; routines disable-all is harmless with no routines; env-lab reports host capability/status without starting services. - Actual result: All commands passed.
doctoranddoctor --repair --yescompleted.envprinted scratch deployment variables; the generated agent JWT secret is not copied here.db:backupcreated a one-off backup undertmp/cli-api-parity/artifacts/root-setup/backups.allowed-hostnameaddedcli-parity.testto the scratch config and noted a restart is required for it to take effect.auth bootstrap-ceocorrectly reported that bootstrap CEO invites are only required in authenticated mode.auth whoamireturned the local implicit board identity.routines disable-allreported zero routines.env-lab doctorreported SSH env-lab is disabled on macOS unless explicitly opted in, andenv-lab statusreported no running fixture. - Status: PASS.
- Output summary: This batch covered root setup/maintenance command surfaces that were previously only indirectly covered. Some artifact output files under
tmp/cli-api-parity/artifacts/root-setupcontain command output from the disposable instance. - Follow-up: Continue remaining untested command families, especially cloud/worktree surfaces and any server-backed command gaps discovered by targeted help/source review.
2026-05-24T12:47:54+02:00 - Worktree and cloud command gated coverage
- Command:
PAPERCLIP_WORKTREES_DIR=tmp/cli-api-parity/worktrees-home pnpm paperclipai worktree:list --json;pnpm paperclipai worktree env --config <scratch-config> --json;pnpm paperclipai worktree:merge-history --from current --to current --company CLI --dry;pnpm paperclipai cloud push --company 12e9db4b-f66c-459b-959e-d645002240fb --dry-run --json - Purpose: Start worktree/cloud parity coverage with read-only or dry-run commands before attempting any lifecycle command that creates branches, worktrees, or external cloud connections.
- Prerequisites/IDs used: Scratch config
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json; scratch worktree root/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/worktrees-home; company12e9db4b-f66c-459b-959e-d645002240fb. - Expected result: Worktree list and env introspection should use scratch config/environment; merge-history should reject identical source/target configs without mutating state; cloud push should fail safely if cloud sync is not enabled/configured.
- Actual result:
worktree:listpassed and showed the current repo branchimprovement/cli-api-paritywith no Paperclip worktree config.worktree env --config <scratch-config> --jsonpassed and printed the scratchPAPERCLIP_CONFIGplus generated env values; the generated JWT secret is intentionally not copied into this log.worktree:merge-history --from current --to current --company CLI --dryfailed as expected withSource and target Paperclip configs are the same. Choose different --from/--to worktrees.cloud push --dry-runfailed as expected withCloud sync is disabled. Enable the cloud sync experimental setting before running paperclipai cloud push. - Status: PASS for safe/gated coverage.
- Output summary: Worktree read-only/dry-run paths behaved safely. Cloud push was not attempted against a real upstream and remained blocked by scratch instance settings.
- Follow-up: Continue with a scratch-only worktree lifecycle test. Cloud requires an experimental setting plus a configured upstream; keep it gated unless a disposable fake upstream can be wired without touching the real install.
2026-05-24T12:55:45+02:00 - Scratch worktree lifecycle and fix verification
- Command:
HOME=tmp/cli-api-parity/shell-home PAPERCLIP_WORKTREES_DIR=tmp/cli-api-parity/worktree-instances pnpm paperclipai worktree:make cli-parity-wt --home <scratch-worktree-home> --from-config <scratch-config> --server-port 3198 --db-port 54331 --seed-mode minimal;pkillonly for the runaway scratch install attempt; editedcli/src/commands/worktree.tsandcli/src/__tests__/worktree.test.ts;pnpm exec vitest run cli/src/__tests__/worktree.test.ts;pnpm --dir cli typecheck;paperclipai worktree:cleanup cli-parity-wt --home <scratch-worktree-home> --force; reranpaperclipai worktree:make ...;paperclipai worktree:list --json;paperclipai worktree env --config <scratch-worktree-config> --json;paperclipai worktree:merge-history --from paperclip-cli-parity-wt --to current --company CLI --dry - Purpose: Exercise scratch-only worktree creation, initialization, dependency install, minimal DB seed, list/env introspection, dry-run merge history, and cleanup behavior without touching the real home or default instance.
- Prerequisites/IDs used: Scratch
HOME/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/shell-home; scratch worktree instance home/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/worktree-instances; source config/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json; worktree branch/pathpaperclip-cli-parity-wt. - Expected result:
worktree:makecreates/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/shell-home/paperclip-cli-parity-wt, installs dependencies once, writes repo-local.paperclip/config.jsonand.paperclip/.env, seeds a minimal isolated DB on ports3198/54331, and leaves normalworktree:list,worktree env, andworktree:merge-history --dryusable. - Actual result: The first live attempt exposed BUG-007: dependency installation recursively invoked the user pnpm shim when
HOMEwas overridden. After the fix, focused worktree tests and CLI typecheck passed.worktree:cleanup --forceremoved the partial scratch branch/worktree. The rerun completed successfully: dependencies installed, minimal DB seed succeeded, repo config/env were written under the scratch worktree, instance data was written under scratch worktree home,worktree:listshowed the new worktree withhasPaperclipConfig: true,worktree env --jsonprinted the scratch worktree env, andworktree:merge-history --drypreviewed zero inserts with existing company history already present. The generated worktree JWT secret is intentionally not copied here. - Status: PASS after BUG-007 fix.
- Output summary: One disposable worktree remains for manual continuation at
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/shell-home/paperclip-cli-parity-wt; its isolated config is/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/shell-home/paperclip-cli-parity-wt/.paperclip/config.json. - Follow-up: Commit BUG-007 fix, then continue remaining non-worktree command families. Cloud still requires a configured upstream or fake upstream harness for deeper coverage.
2026-05-24T13:06:21+02:00 - Agent prompt, heartbeat, feedback, board claim, OpenClaw, and configure coverage
- Command:
token agent create --company-id 12e9db4b-f66c-459b-959e-d645002240fb --agent 1dd601a1-031a-4225-b005-419427fd059f --name cli-agent-prompt-smoke --json;agent-prompt 1dd601a1-031a-4225-b005-419427fd059f <agent-token> "CLI parity agent-prompt smoke without wake" --title "CLI parity agent-prompt smoke" --no-wake --json;token agent revoke <key-id> --company-id ... --agent ... --json;heartbeat run --agent-id 1dd601a1-031a-4225-b005-419427fd059f --source on_demand --trigger manual --timeout-ms 5000 --json;feedback report/export/trace/bundle;company feedback:list;board-claim show invalid-claim-token --json;board-claim claim invalid-claim-token --payload-json '{}' --json;openclaw invite-prompt --company-id ... --payload-json '{"goal":"CLI parity OpenClaw invite prompt smoke"}' --json;configure --config <scratch-config> --section invalid-section - Purpose: Cover remaining safe operator/helper command surfaces that were not part of the earlier company/issue/agent/core batches.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f; feedback trace6193ff3a-55d3-4c01-bfbf-78e82ed55793; temporary agent token stored only under scratch artifacts and revoked after use. - Expected result:
agent-promptcreates or updates work through an agent token and no-wake path; heartbeat run returns a bounded on-demand invocation result; feedback report/export/trace/bundle can read the existing feedback trace; invalid board claim calls fail with controlled user-facing errors; OpenClaw invite prompt returns prompt data; invalid configure section should fail non-zero. - Actual result: First
agent-promptattempts failed with401because the test script passed the wrong token field (.keyobject / empty shell variable) instead of.key.token. Retrying with.key.tokenpassed and the token was revoked.heartbeat runcompleted within the timeout. Feedback report/export and trace/bundle passed using the existing trace.board-claim showreturned expected404: Board claim challenge not found;board-claim claimreturned expected400: Claim code is required. OpenClaw invite prompt passed.configure --section invalid-sectioninitially printed an error but exited0, exposing BUG-008; after the fix, it exits1. - Status: PASS after BUG-008 fix; board-claim paths covered only with invalid/gated tokens because no active board claim challenge exists in
local_trusted. - Output summary: Agent token artifacts are under
tmp/cli-api-parity/artifacts/agent-prompt-token*.json; the token was revoked. Feedback artifacts are undertmp/cli-api-parity/artifacts/feedback-*. No real home state was used. - Follow-up: Continue cloud/connect/run coverage decisions.
connectand positive board-claim flows are interactive/bootstrap-token dependent and may remain documented as gated if no disposable token source is available.
2026-05-24T13:11:19+02:00 - Cloud fake-upstream and remaining run/connect coverage
- Command: disposable Node fake upstream on
http://127.0.0.1:3199;instance settings:experimental:update --payload-json '{"enableCloudSync":true}' --json;cloud connect http://127.0.0.1:3199 --no-browser --json;cloud push --company 12e9db4b-f66c-459b-959e-d645002240fb --remote-url http://127.0.0.1:3199 --dry-run --json;run live --company-id ... --limit 5 --min-count 1 --json;run issues 9c686a91-c88a-47aa-9326-a889c4281d2b --json;run workspace-operations 9c686a91-c88a-47aa-9326-a889c4281d2b --json;run workspace-log 00000000-0000-4000-8000-000000000000 --json;run cancel 9c686a91-c88a-47aa-9326-a889c4281d2b --json;run watchdog-decision 9c686a91-c88a-47aa-9326-a889c4281d2b --decision continue --reason "CLI parity watchdog decision smoke" --json;connect --persona board --api-base http://127.0.0.1:3197 --profile cli-connect-smoke --context <scratch-context> --json - Purpose: Exercise cloud connect/push without a real external Paperclip Cloud stack, finish run subcommands that were not covered by earlier run list/get/events/log checks, and verify
connectbehavior in the non-interactive test runner. - Prerequisites/IDs used: Fake cloud server on loopback port
3199; company12e9db4b-f66c-459b-959e-d645002240fb; heartbeat run9c686a91-c88a-47aa-9326-a889c4281d2bcreated byheartbeat run; scratch context and config paths. - Expected result: Cloud sync can be enabled only in the scratch instance;
cloud connectstores a fake upstream connection under scratchPAPERCLIP_HOME;cloud push --dry-runexports local company data and posts a preview bundle to the fake upstream; run read/control commands return structured results or controlled 404 for a nonexistent workspace operation;connectrefuses non-interactive execution with guidance. - Actual result: Experimental
enableCloudSyncwas enabled in the scratch instance.cloud connect --no-browsercompleted against the fake upstream and stored a fake connection.cloud push --dry-runreturned a fake preview response with summary{create:0, update:0, adopt:0, skip:1, conflict:0, staleMapping:0}.run live,run issues, andrun workspace-operationspassed; workspace operations returned an empty list.run workspace-logon a sentinel ID returned expected404: Workspace operation not found.run cancelon the already completed run returned the run unchanged with statussucceeded.run watchdog-decisioncreated a watchdog decision record.connectreturned expected non-interactive error: use--api-base/--api-keyor context/token commands for scripts. - Status: PASS for fake-cloud dry-run and remaining safe run/connect coverage.
- Output summary: Fake cloud artifacts are under
tmp/cli-api-parity/artifacts/cloud-*. The fake cloud token is synthetic and stored only in scratch Paperclip home.connectremains intentionally interactive; scriptable equivalent coverage is viacontext set, token commands,whoami, and agent/board prompt flows already tested. - Follow-up: Stop the fake upstream server. Keep the real scratch Paperclip server running on
127.0.0.1:3197.
2026-05-24T13:15:09+02:00 - Routine lifecycle coverage
- Command:
routine create --company-id 12e9db4b-f66c-459b-959e-d645002240fb --payload-json '{"title":"CLI parity routine smoke",...}' --json;routine list;routine get 8254ead3-7edd-43fc-97ca-cb3f477cefc9;routine update;routine revisions;routine runs;routine trigger:create <routine-id>for API and webhook triggers;routine trigger:update <api-trigger-id>;routine trigger:rotate-secret <api-trigger-id>;routine trigger:rotate-secret <webhook-trigger-id>;routine trigger:fire <webhook-public-id>;routine run <routine-id>without and then withassigneeAgentId;routine trigger:deletefor both triggers; finalroutine update <routine-id> --payload-json '{"status":"archived"}' - Purpose: Exercise routine CRUD, revision/runs inspection, manual run, trigger create/update/delete, trigger secret rotation, public trigger fire validation, and cleanup by archiving the disposable routine.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f; routine8254ead3-7edd-43fc-97ca-cb3f477cefc9. - Expected result: Routine can be created, listed, read, updated, inspected, manually run when an assignee is supplied, and archived. API trigger secret rotation should fail because only webhook triggers have secrets. Disabled webhook fire should fail cleanly. Trigger delete should remove disposable triggers.
- Actual result: Routine create/list/get/update/revisions/runs passed. API trigger create/update/delete passed.
trigger:rotate-secreton the API trigger returned expected422: Only webhook triggers can rotate secrets; webhook trigger create and rotate passed.trigger:fireon the disabled webhook returned expected409: Routine trigger is not active.routine runwithout assignee returned expected422: Default agent required; rerun withassigneeAgentIdpassed and produced one routine run. Both triggers were deleted and the routine was archived. - Status: PASS with expected validation failures.
- Output summary: Routine artifacts are under
tmp/cli-api-parity/artifacts/routine. No active routine/trigger from this batch remains; the disposable routine is archived. - Follow-up: Final inventory and status check.
2026-05-24T13:19:42+02:00 - Final token-list fix verification
- Command:
token agent list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --agent 1dd601a1-031a-4225-b005-419427fd059f --json; editedcli/src/commands/client/token.tsandcli/src/__tests__/token.test.ts;pnpm exec vitest run cli/src/__tests__/token.test.ts;pnpm --dir cli typecheck; reran the same livetoken agent listcommand. - Purpose: Verify agent token list accepts the documented
--agent <agent-id>shape during final cleanup. - Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f. - Expected result: Agent token list resolves an agent ID directly and returns the key list.
- Actual result: Initial final cleanup attempt returned
404: Agent not foundfor the agent ID, whileagent listshowed the agent exists and using--agent "Parity Worker"worked. After BUG-009 fix, the same ID-based command passed and showed no active unrevoked agent keys. - Status: PASS after BUG-009 fix.
- Output summary: Verification artifact written to
tmp/cli-api-parity/artifacts/final-agent-tokens-by-id.json. - Follow-up: Commit BUG-009 fix, then run final clean status checks.
2026-05-24T13:20:43+02:00 - Final status sweep
- Command:
health --json;token board list --json;token agent list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --agent 1dd601a1-031a-4225-b005-419427fd059f --json;routine list --company-id ... --json;plugin list --json;openapi --json;git status --short --branch;lsof -nP -iTCP:3197 -sTCP:LISTEN;lsof -nP -iTCP:3199 -sTCP:LISTEN - Purpose: Confirm the disposable instance is still healthy, no temporary token/plugin/routine resources remain active, the fake cloud server is stopped, and git state is clean after all fixes.
- Prerequisites/IDs used: Same scratch env and company/agent IDs.
- Expected result: Paperclip remains running on
127.0.0.1:3197; fake cloud port3199is stopped; no active board or agent tokens from the test remain; plugin list is empty; disposable routine is archived;openapiremains the one documented unresolved API route gap. - Actual result: Health returned
status: ok; process11566is listening on127.0.0.1:3197; no process is listening on3199; final board token list has 2 revoked keys and no active keys; final agent token list has 4 revoked keys and no active keys; plugin list is empty; routine list contains the archived disposable routine and no active routines;openapi --jsonstill returns404: API route not found; git status was clean before this final log update. - Status: PASS with known unresolved OpenAPI gap.
- Output summary: Final artifacts are under
tmp/cli-api-parity/artifacts/final-*. - Follow-up: Final report should include restart commands and call out
openapi --jsonas not fixed because the OpenAPI branch/generator has not been integrated into this repo.
2026-05-24T13:25:20+02:00 - OpenAPI route fix verification
- Command: Generated
server/src/routes/openapi.tsfrom the route inventory indoc/plans/2026-05-23-cli-api-parity-openapi-reference.ts; mountedopenApiRoutes()under/api; addedserver/src/__tests__/openapi-routes.test.ts; ranpnpm exec vitest run server/src/__tests__/openapi-routes.test.ts;pnpm --dir server typecheck; restarted the isolated runbook server with the scratch environment;curl -fsS http://127.0.0.1:3197/api/openapi.json | jq '{openapi, pathCount:(.paths|keys|length)}';pnpm --silent paperclipai openapi --json > tmp/cli-api-parity/artifacts/openapi-live-after-fix.json. - Purpose: Close the remaining documented
openapiCLI/API parity gap without introducing a new generator dependency during the live parity run. - Prerequisites/IDs used: Same scratch env, API URL
http://127.0.0.1:3197, and local source-tree install. - Expected result:
/api/openapi.jsonandpaperclipai openapi --jsonreturn a valid OpenAPI 3.0 document with the reference route inventory, including representative CLI/API parity paths such as/api/companies/{companyId}/agentsand/api/agents/{id}/keys. - Actual result: Focused test and
servertypecheck passed. After restart, direct curl returned{"openapi":"3.0.0","pathCount":247}. The CLI command returnedopenapi: "3.0.0", titlePaperclip API,247paths,/api/openapi.jsonsummaryGet the generated OpenAPI document, and/api/agents/{id}/keysPOST summaryCreate an agent API key. - Status: PASS after MISMATCH-007 OpenAPI fix.
- Output summary: Live OpenAPI artifact is
tmp/cli-api-parity/artifacts/openapi-live-after-fix.json. The route exposes operation inventory, tags, summaries, and standard responses from the parity reference; it intentionally does not yet include full request/response schemas. - Follow-up: Commit the OpenAPI route fix, then rerun the final inventory/status sweep.
2026-05-24T13:31:50+02:00 - Instructions path help fix verification
- Command: Edited
cli/src/commands/client/agent.ts; ranpnpm exec vitest run cli/src/__tests__/agent-lifecycle.test.ts;pnpm --dir cli typecheck;pnpm --silent paperclipai agent instructions-path:update --help. - Purpose: Close the remaining logged UX mismatch where process-adapter instructions path requirements were only discoverable through failing API calls.
- Prerequisites/IDs used: Local source-tree CLI; no live server mutation required.
- Expected result: Help text explains that process adapters require
adapterConfigKey, relative paths requireadapterConfig.cwd, and the JSON payload option includes a concrete example. - Actual result: Focused agent lifecycle test and CLI typecheck passed. Help output now includes the process-adapter requirement, the relative path
adapterConfig.cwdrequirement, and example payload{"path":"/tmp/AGENTS.md","adapterConfigKey":"instructionsFilePath"}. - Status: PASS after MISMATCH-004 help fix.
- Output summary: This is a help-only CLI change; no scratch instance resources were created.
- Follow-up: Commit the help fix, then continue residual command coverage.
2026-05-24T13:33:50+02:00 - Residual company and skill command coverage
- Command:
company stats; disposablecompany create;company branding:update;company archive;company delete;company export:preview;company export:api;company import:preview;company import:apply; cleanupcompany delete;skill import; cleanupskill delete. - Purpose: Cover company subcommands and
skill importnot explicitly exercised in earlier batches. - Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; disposable archive company342c1b91-0f48-4a63-a9c5-fc7ffc758483; raw-import companydab6758c-dd30-4066-87f0-4df76bd21ea5; imported skillbe9538e4-9827-426f-b82a-4228c5d3f851. - Expected result: Company stats read succeeds; disposable company can be branded, archived, and deleted; raw API portability commands work with API-shaped payloads; skill import from a local repo skill path succeeds and the imported skill can be deleted.
- Actual result: Company stats passed. Disposable company branding/archive/delete passed. First raw export attempt using CLI wrapper-style
{"include":["company"]}returned expected API validationincludeobject error, so the test was adapted to raw API shape{"include":{"company":true}}; export preview and export API then passed. Full exported package import via a shell variable was abandoned because markdown code fences in the large JSON payload caused shell transport issues; a minimal inline company package was used instead, and raw import preview/apply/delete passed.skill importimported one local skill and cleanup delete passed. - Status: PASS after adapting raw API payload shape.
- Output summary: Artifacts are under
tmp/cli-api-parity/artifacts/residual-company-skill. No disposable company or imported skill from this batch remains active. - Follow-up: Continue advanced plugin surface coverage.
2026-05-24T13:37:45+02:00 - Advanced plugin command coverage and tool-dispatch failure
- Command: Installed bundled kitchen-sink plugin;
plugin list/inspect/health/logs/config/jobs/job:runs/job:trigger/webhook/dashboard/bridge:data/data/action/local-folders/upgrade/disable/enable/uninstall; initialplugin config:test/config:set/bridge:action/tool:execute/local-folder:*attempts; correctedconfig:test,config:set, andbridge:action; final uninstall. - Purpose: Exercise plugin command surfaces that require a plugin declaring jobs, webhooks, tools, bridge handlers, and UI contributions.
- Prerequisites/IDs used: Bundled plugin path
packages/plugins/examples/plugin-kitchen-sink-example; company12e9db4b-f66c-459b-959e-d645002240fb; projectd32032ce-d95e-4c4e-a942-dd98498025fb; agent1dd601a1-031a-4225-b005-419427fd059f; run9c686a91-c88a-47aa-9326-a889c4281d2b. - Expected result: Plugin installs, exposes its manifest surfaces, handles job/webhook/bridge/data/action calls, rejects unsupported stream/local-folder calls cleanly, and uninstalls. Tool execution should work for the listed kitchen-sink echo tool.
- Actual result: Install/list/inspect/health/logs/config/jobs/job:runs/job:trigger/webhook/dashboard/bridge:data/data/action/upgrade/disable/enable/uninstall passed. Config commands initially failed until payloads were corrected to
{"configJson":{...}}; bridge action initially failed until payload usedkeyinstead ofaction.bridge:streamreturned expectedPlugin stream bridge is not enabled. Local-folder calls returned expected validation because the kitchen-sink manifest declares no local folders.plugin toolslistedpaperclip-kitchen-sink-example:echo, butplugin tool:executereturned502: worker for plugin "paperclip-kitchen-sink-example" is not runningeven though bridge calls to the same plugin worker succeeded. - Status: PASS for safe plugin surfaces; FAIL for
plugin tool:execute, recorded as BUG-010. - Output summary: Artifacts are under
tmp/cli-api-parity/artifacts/residual-pluginandtmp/cli-api-parity/artifacts/residual-plugin-corrected. The kitchen-sink plugin was uninstalled after each batch. - Follow-up: Fix BUG-010 and rerun
plugin tool:executelive.
2026-05-24T13:41:40+02:00 - Plugin tool-dispatch fix verification
- Command: Edited
server/src/services/plugin-tool-dispatcher.ts,server/src/services/plugin-loader.ts, andserver/src/__tests__/plugin-database.test.ts; ranpnpm exec vitest run server/src/__tests__/plugin-database.test.ts;pnpm --dir server typecheck; restarted the isolated server; installed kitchen-sink plugin;plugin tools;plugin tool:execute --payload-json '{"tool":"paperclip-kitchen-sink-example:echo",...}'; cleanupplugin uninstall --force. - Purpose: Verify plugin tool execution uses the plugin database ID for worker lookup while preserving plugin-key namespaced tool names.
- Prerequisites/IDs used: Same scratch server and kitchen-sink plugin; tool
paperclip-kitchen-sink-example:echo. - Expected result: The listed echo tool dispatches to the running kitchen-sink worker and returns the echo result.
- Actual result: Focused test and server typecheck passed. After restart,
plugin toolslistedpaperclip-kitchen-sink-example:echo;plugin tool:executereturnedcontent: "CLI parity tool after fix"and the expected run context. The plugin was uninstalled andplugin listreturned[]. - Status: PASS after BUG-010 fix.
- Output summary: Live verification artifacts are under
tmp/cli-api-parity/artifacts/residual-plugin-after-fix. - Follow-up: Commit BUG-010 fix, then rerun final inventory/status sweep.
2026-05-24T13:47:02+02:00 - Routine webhook secret cleanup fix verification
- Command: Final inventory found active managed secret
156c6074-37b7-4f8e-8619-a62027c2147e; inspected routine trigger secret handling; editedserver/src/services/routines.tsandserver/src/__tests__/routines-service.test.ts; ranpnpm exec vitest run server/src/__tests__/routines-service.test.ts;pnpm --dir server typecheck; restarted isolated server; deleted the older leaked disposable secret; created temporary routine60ac06c9-f8c4-4cb1-b9fd-ae52163eb3e6; created webhook trigger02838bc3-5b48-4f1e-aad0-ca63a48b926b; deleted the trigger; verified secret140c2608-0d8e-4f1e-aad0-ca63a48b926bwas absent fromsecrets list; archived the temporary routine. - Purpose: Fix and verify cleanup for routine webhook trigger generated secrets.
- Prerequisites/IDs used: Company
12e9db4b-f66c-459b-959e-d645002240fb; scratch server restarted with the patched code. - Expected result: Deleting a webhook routine trigger removes the generated paperclip-managed secret and binding. No active secrets remain from parity cleanup.
- Actual result: Focused routine service test and server typecheck passed. Live trigger delete removed the generated secret; final
secrets listreturned0rows. The older leaked disposable secret was deleted through the CLI. - Status: PASS after BUG-011 fix.
- Output summary: Artifacts are under
tmp/cli-api-parity/artifacts/routine-secret-cleanup-fix. - Follow-up: Commit BUG-011 fix, then rerun final inventory/status sweep.
2026-05-24T13:48:40+02:00 - Final clean inventory sweep
- Command:
health --json;openapi --json;token board list --json;token agent list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --agent 1dd601a1-031a-4225-b005-419427fd059f --json;plugin list --json;routine list --company-id ... --json;secrets list --company-id ... --json;environment list --company-id ... --json;project-workspace list d32032ce-d95e-4c4e-a942-dd98498025fb --json;git status --short --branch;lsof -nP -iTCP:3197 -sTCP:LISTEN;lsof -nP -iTCP:3199 -sTCP:LISTEN; environment echo for required isolation variables and unset database variables. - Purpose: Confirm the disposable instance is healthy, isolated, cleaned up, and ready for manual continuation.
- Prerequisites/IDs used: Same scratch env and company/agent IDs.
- Expected result: Health and OpenAPI pass; all required env vars point under
tmp/cli-api-parity;DATABASE_URLandDATABASE_MIGRATION_URLare unset; no active board/agent tokens, plugins, secrets, non-default environments, project workspaces, or active routines remain; only the scratch server listens on127.0.0.1:3197; fake cloud port3199is stopped; git is clean before this final log update. - Actual result: Summary was
{health:"ok", openapi:"3.0.0", pathCount:247, activeBoardTokens:0, activeAgentTokens:0, plugins:0, routines:2, activeRoutines:0, secrets:0, environments:1, projectWorkspaces:0}.PAPERCLIP_HOME,PAPERCLIP_CONFIG,PAPERCLIP_CONTEXT,PAPERCLIP_AUTH_STORE,CODEX_HOME, andCLAUDE_HOMEall point under the scratch path.DATABASE_URLandDATABASE_MIGRATION_URLwereUNSET.nodePID70429is listening on127.0.0.1:3197; no process is listening on3199; git status was clean before this log update. - Status: PASS.
- Output summary: Final clean artifacts are under
tmp/cli-api-parity/artifacts/final-clean-sweep. - Follow-up: Leave the scratch instance running for manual testing.
2026-05-24T13:50:00+02:00 - Final user-facing handoff summary
- Command: Recorded the final assistant handoff summary in this living log after the clean inventory sweep.
- Purpose: Preserve the exact user-facing closeout in the reproducible CLI/API parity audit trail.
- Prerequisites/IDs used: Scratch server on
http://127.0.0.1:3197; company12e9db4b-f66c-459b-959e-d645002240fb; agent1dd601a1-031a-4225-b005-419427fd059f; final clean sweep artifacts undertmp/cli-api-parity/artifacts/final-clean-sweep. - Expected result: The log includes the final paths, command coverage, bug/fix summary, cleanup state, verification commands, and manual continuation instructions that were reported to the user.
- Actual result: Final handoff stated that the full isolated CLI/API parity pass completed and was committed, the scratch Paperclip server was still running on
http://127.0.0.1:3197, and goal usage was 2,625,855 tokens over about 2h 23m. - Status: PASS.
- Output summary:
{
"health": "ok",
"openapi": "3.0.0",
"pathCount": 247,
"activeBoardTokens": 0,
"activeAgentTokens": 0,
"plugins": 0,
"routines": 2,
"activeRoutines": 0,
"secrets": 0,
"environments": 1,
"projectWorkspaces": 0
}
- Final paths:
- Scratch home:
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home - Config:
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json - Context:
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/context.json - Auth store:
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/auth.json - Embedded DB:
/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/db, active on pg port54330 - API URL:
http://127.0.0.1:3197 - Log:
doc/bugs/2026-05-24-cli-api-parity-e2e-log.md
- Scratch home:
- Commands covered: health; context; auth/access/profile/session/invite/join/member/admin/sidebar/inbox/openclaw; company CRUD/export/import/raw portability/stats/branding/archive; goals; projects; agents; tokens; issues and subresources; approvals; feedback; dashboard/activity/cost/finance/budget; secrets lifecycle; adapters; environments; workspaces/project-workspaces; assets; skills/import; routines/triggers; prompt/wake/run/heartbeat; cloud fake upstream; worktree helpers; setup/doctor/env/db backup/env-lab; OpenAPI; advanced plugin lifecycle/tool/job/webhook/bridge/config surfaces.
- Latest continuation commits:
01579595Log final CLI parity sweepce16de70Clean up routine webhook secrets1de4174fFix plugin tool worker lookupec3cb727Clarify instructions path CLI helpc811bf07Add OpenAPI CLI route
- Remaining caveats:
- Positive interactive
connectwas initially not run because the CLI intentionally rejects non-TTY use; this was resolved in the follow-up with prompt-driven board and agent persona command tests plus the already covered scriptable auth/context/token flows. - Positive
board-claim claimwas initially not run because the live scratch server waslocal_trusted; this was resolved in the follow-up with an isolated authenticated-mode service test. - OpenAPI initially worked only at route/operation inventory level; this was resolved in the follow-up with a schema-backed generator.
- Positive interactive
- Tokens and cleanup: All created board and agent tokens were revoked. Plugins were uninstalled. Temporary secrets are gone. Temporary non-default environments and project workspaces are gone. Two routines remain archived in the disposable instance.
- Verification run:
pnpm exec vitest run server/src/__tests__/openapi-routes.test.tspnpm exec vitest run cli/src/__tests__/agent-lifecycle.test.tspnpm exec vitest run server/src/__tests__/plugin-database.test.tspnpm exec vitest run server/src/__tests__/routines-service.test.tspnpm --dir cli typecheckpnpm --dir server typecheck- live isolated CLI reruns for each fixed failure
- Manual continuation:
export PAPERCLIP_HOME=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home
export PAPERCLIP_INSTANCE_ID=cli-api-parity
export PAPERCLIP_CONFIG=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json
export PAPERCLIP_CONTEXT=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/context.json
export PAPERCLIP_AUTH_STORE=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/auth.json
export PAPERCLIP_API_URL=http://127.0.0.1:3197
export PAPERCLIP_SERVER_PORT=3197
export PORT=3197
export CODEX_HOME=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/codex-home
export CLAUDE_HOME=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/claude-home
unset DATABASE_URL DATABASE_MIGRATION_URL
pnpm paperclipai health --json
- Follow-up: Commit this log-only update so the final handoff is preserved in git history.
2026-05-24T14:07:24+02:00 - Caveat follow-up investigation
- Command:
rg -n "openapi|OpenAPI|board-claim|connect" server cli packages doc/plans/2026-05-23-cli-api-parity-openapi-reference.ts;sed -n ... server/src/routes/openapi.ts;sed -n ... doc/plans/2026-05-23-cli-api-parity-openapi-reference.ts;sed -n ... server/src/board-claim.ts;sed -n ... cli/src/commands/client/connect.ts;lsof -nP -iTCP:3197 -sTCP:LISTEN;git status --short --branch. - Purpose: Re-open the three final caveats and distinguish true implementation gaps from harness-gated coverage.
- Prerequisites/IDs used: Existing isolated scratch server on
127.0.0.1:3197, PID70429; same scratch env and repo branchimprovement/cli-api-parity. - Expected result: Determine whether OpenAPI requires more implementation, whether a positive board-claim claim can be tested, and whether interactive
connecthas untested behavior beyond the already verified scriptable equivalents. - Actual result: OpenAPI is a true implementation-depth gap:
server/src/routes/openapi.tscurrently serves a 247-path operation inventory with generic responses, whiledoc/plans/2026-05-23-cli-api-parity-openapi-reference.tsalready contains a realOpenAPIRegistry/OpenApiGeneratorV3implementation with request bodies from shared Zod schemas, auth/security fixups, and status overrides. Positive board-claim requires an authenticated-mode instance whose only instance admin islocal-board; the current disposable server islocal_trusted, where no challenge is generated. Interactiveconnectintentionally exits in non-TTY mode before any prompts; its network/token/context side effects are covered by scriptable command paths, but the prompt flow itself has not been PTY-tested. - Status: PASS with OpenAPI implementation gap confirmed and fixed in the next entry.
- Output summary: OpenAPI needed to be upgraded from inventory stub to generated schema-backed document. Board-claim positive coverage needs a separate isolated authenticated-mode harness or focused route/service test. Interactive
connectcan be checked with a PTY/script harness if a local board-login challenge can be approved non-interactively. - Follow-up: Implement full OpenAPI route from the reference file first, verify and commit, then evaluate scoped board-claim and connect harness options.
2026-05-24T14:12:30+02:00 - Full OpenAPI generator implementation
- Command:
pnpm add @asteasolutions/zod-to-openapi@7.3.4 --filter @paperclipai/server; replacedserver/src/routes/openapi.tsinventory stub with the schema-backed generator fromdoc/plans/2026-05-23-cli-api-parity-openapi-reference.ts; added route wrapper exports; tightenedserver/src/__tests__/openapi-routes.test.ts;pnpm exec vitest run server/src/__tests__/openapi-routes.test.ts;pnpm --dir server typecheck; restarted isolated server with the scratch env;pnpm paperclipai openapi --json. - Purpose: Resolve the final OpenAPI caveat by serving a proper generated OpenAPI document with shared Zod request schemas, auth/security metadata, and response status fixups.
- Prerequisites/IDs used: Isolated scratch server restarted on
127.0.0.1:3197;DATABASE_URLandDATABASE_MIGRATION_URLunset;PAPERCLIP_HOME,PAPERCLIP_CONFIG,PAPERCLIP_CONTEXT,PAPERCLIP_AUTH_STORE,CODEX_HOME, andCLAUDE_HOMEall undertmp/cli-api-parity. - Expected result:
/api/openapi.jsonandpaperclipai openapi --jsonreturn OpenAPI 3.0 with schema-backed request bodies, security schemes, public-operation security overrides, and create-operation201responses. - Actual result: Focused OpenAPI test passed and asserts
BoardSessionAuth,BoardApiKeyAuth,AgentBearerAuth, public/api/healthsecurity[],POST /api/companiesrequest body schema,POST /api/companies201response, andPOST /api/agents/{id}/keysrequest body schema. Server typecheck passed. Live CLI returned{openapi:"3.0.0", pathCount:259, security:["BoardSessionAuth","BoardApiKeyAuth","AgentBearerAuth"], companyCreateRequest:{type:"string",minLength:1}, companyCreateStatus:["201","400","401","403"], agentKeyRequest:{type:"string",minLength:1,default:"default"}}. - Status: PASS after OpenAPI caveat fix.
- Output summary: Live schema-backed OpenAPI artifact is
tmp/cli-api-parity/artifacts/caveat-followup/openapi-live-schema-backed.json. - Follow-up: Commit the OpenAPI fix, then continue positive board-claim and interactive connect follow-up testing.
2026-05-24T14:16:10+02:00 - Positive board-claim claim verification
- Command: Added
server/src/__tests__/board-claim.test.ts; ranpnpm exec vitest run server/src/__tests__/board-claim.test.ts; ranpnpm --dir server typecheck. - Purpose: Resolve the board-claim caveat with positive coverage for the authenticated-mode claim path without mutating the long-running
local_trustedscratch instance. - Prerequisites/IDs used: Fresh embedded-postgres test database; seeded one company, a real auth user, and
local-boardas the onlyinstance_admin; initialized board-claim challenge withdeploymentMode: "authenticated". - Expected result: A claim warning URL is generated;
inspectBoardClaimChallenge(token, code)returnsavailable; claiming as the signed-in user returnsclaimed;local-boardloses instance admin; the signed-in user gains instance admin and active owner membership for the existing company; subsequent inspect returnsclaimed. - Actual result: Initial test attempt exposed cleanup ordering only because the claim path creates
principal_permission_grants; cleanup was fixed to delete grants before companies. The rerun passed. Server typecheck passed. - Status: PASS.
- Output summary: Positive board-claim behavior is now covered by a focused authenticated-mode regression test. The live scratch instance remains
local_trusted, which is correct for the main parity harness. - Follow-up: Commit the board-claim positive coverage, then evaluate whether interactive
connectcan be PTY-tested or should remain classified as lower-risk because its side effects were exercised through scriptable paths.
2026-05-24T14:18:20+02:00 - Interactive connect flow verification
- Command: Added
cli/src/__tests__/connect.test.ts; ranpnpm exec vitest run cli/src/__tests__/connect.test.ts; ranpnpm --dir cli typecheck. - Purpose: Resolve the interactive
connectcaveat by exercising the actual TTY-gated command path with mocked prompts and mocked board-login approval, without opening a real browser or touching real auth state. - Prerequisites/IDs used: Temp context files under the OS temp directory; mocked
process.stdin.isTTYandprocess.stdout.isTTYto true; mockedloginBoardClito return a board credential; mocked API responses for health, company list, board API key create, agent list, and agent API key create. - Expected result: Board persona flow verifies health, completes board auth, lists companies, creates a board token, writes the selected board profile to context, and emits JSON output. Agent persona flow verifies health, completes board auth, lists companies and agents, creates an agent token, writes the selected agent profile to context, and emits JSON output.
- Actual result: Both prompt-driven
connecttests passed. CLI typecheck passed. The test intentionally does not launch a browser; browser approval itself is already covered by CLI auth challenge route tests and mocked here as the boundary before profile selection/token creation. - Status: PASS.
- Output summary: Interactive
connectno longer has an untested command-flow caveat. Remaining real-browser/device approval behavior is covered by lower-level CLI auth challenge route tests and scriptable auth commands, not by manually approving in this terminal. - Follow-up: Commit the connect flow coverage, then rerun final status and isolation checks.
2026-05-24T14:19:04+02:00 - Caveat follow-up final status
- Command:
pnpm paperclipai health --json;pnpm paperclipai openapi --json;lsof -nP -iTCP:3197 -sTCP:LISTEN;git status --short --branch, all with the scratchPAPERCLIP_*,CODEX_HOME, andCLAUDE_HOMEenvironment and withDATABASE_URL/DATABASE_MIGRATION_URLunset. - Purpose: Confirm the three caveats are no longer unresolved after the follow-up fixes and coverage.
- Prerequisites/IDs used: Isolated scratch server restarted from local source on
127.0.0.1:3197; PID84908; sametmp/cli-api-parityhome/config/context/auth paths. - Expected result: Scratch server is healthy; OpenAPI is schema-backed; git has no code changes before this final log entry; the only remaining difference is this log update.
- Actual result: Health returned
status:"ok", version0.3.1, deployment modelocal_trusted, exposureprivate, auth ready, bootstrap ready. OpenAPI returned{openapi:"3.0.0", pathCount:259, security:["BoardSessionAuth","BoardApiKeyAuth","AgentBearerAuth"], companyCreateStatus:["201","400","401","403"]}.nodePID84908is listening on127.0.0.1:3197. Git status was clean before this final log update. - Status: PASS.
- Output summary: OpenAPI caveat fixed in commit
1ab85cb5; positive board-claim caveat covered in commit678fd3a8; interactive connect caveat covered in commit40480f38. - Follow-up: Commit this final log-only status entry.
2026-05-24T14:22:00+02:00 - Detached scratch server continuation
- Command: Stopped the foreground scratch server process; started the same runbook command in detached screen session
paperclip-cli-parity; verifiedpnpm paperclipai health --json; checkedlsof -nP -iTCP:3197 -sTCP:LISTEN; checkedscreen -ls. - Purpose: Leave the disposable instance running without tying it to the active tool session.
- Prerequisites/IDs used: Same scratch env and unset database variables; detached screen session
91568.paperclip-cli-parity. - Expected result: Server continues running on non-default port
3197with the same isolated home/config/context/auth paths. - Actual result: Health returned
status:"ok"with deployment modelocal_trusted;nodePID91583is listening on127.0.0.1:3197;screen -lsshows detached session91568.paperclip-cli-parity. - Status: PASS.
- Output summary: Detached server log is
tmp/cli-api-parity/artifacts/caveat-followup/server-screen.log. - Follow-up: Manual continuation can use the same env block and
screen -r paperclip-cli-parityto inspect the server session.
2026-05-24T14:27:44+02:00 - Rename bug log directory to logs
- Command:
git mv doc/bugs doc/logs; appended this entry indoc/logs/2026-05-24-cli-api-parity-e2e-log.md;git status --short --branch;git diff --check. - Purpose: Rename the living test/bug log directory from
doc/bugstodoc/logswhile preserving the existing audit trail. - Prerequisites/IDs used: Existing clean branch
improvement/cli-api-parity; single log file2026-05-24-cli-api-parity-e2e-log.md. - Expected result: Git records the file as moved from
doc/bugs/todoc/logs/; historical command strings inside the log remain unchanged because they record what was run at the time. - Actual result: Directory rename is staged as a path move with this follow-up log entry.
- Status: PASS.
- Output summary: New log path is
doc/logs/2026-05-24-cli-api-parity-e2e-log.md. - Follow-up: Commit the directory rename.
Bugs And Mismatches
BUG-011 - Deleting a webhook routine trigger left its managed secret active
- Status: Fixed and live-verified.
- Severity: Medium resource lifecycle leak.
- Reproduction command:
routine trigger:create <routine-id> --payload-json '{"kind":"webhook","signingMode":"bearer"}' --json;routine trigger:delete <trigger-id> --json;secrets list --company-id <company-id> --json. - Expected result: The webhook trigger's generated paperclip-managed secret and binding are removed when the trigger is deleted.
- Actual result: The trigger was deleted, but the generated secret stayed active with
referenceCount: 1and descriptionWebhook auth for routine .... - Suspected cause:
deleteTrigger()deleted only theroutine_triggersrow and appended a revision; it did not removeexisting.secretId. - Files changed:
server/src/services/routines.ts,server/src/__tests__/routines-service.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: After successful trigger deletion, call
secretsSvc.remove(existing.secretId)for webhook triggers with managed secrets. Added assertions that deleting a webhook trigger removes bothcompany_secretsandcompany_secret_bindingsrows. - Verification command:
pnpm exec vitest run server/src/__tests__/routines-service.test.ts;pnpm --dir server typecheck; live isolated webhook trigger create/delete; livesecrets list --company-id <company-id> --json. - Remaining risk: Low. If secret removal failed after trigger deletion, the trigger would already be gone; current provider-backed removal path was verified for the local encrypted provider.
BUG-010 - Plugin tools were listed but could not execute against a running plugin worker
- Status: Fixed and live-verified.
- Severity: Medium plugin CLI/API parity bug.
- Reproduction command: Install
packages/plugins/examples/plugin-kitchen-sink-example, then runpnpm paperclipai plugin tool:execute --payload-json '{"tool":"paperclip-kitchen-sink-example:echo","parameters":{"message":"CLI parity tool"},"runContext":{"companyId":"<company-id>","projectId":"<project-id>","agentId":"<agent-id>","runId":"<run-id>"}}' --json. - Expected result: The listed tool dispatches to the running kitchen-sink worker and returns a
ToolResult. - Actual result:
plugin toolslistedpaperclip-kitchen-sink-example:echo, and bridge data/action calls to the same plugin worker succeeded, buttool:executereturned502: Cannot execute tool ... worker for plugin "paperclip-kitchen-sink-example" is not running. - Suspected cause:
plugin-loaderregistered tools with only the plugin key, soRegisteredTool.pluginDbIddefaulted to the plugin key.plugin-worker-managertracks running workers by database plugin UUID, so the dispatcher looked up the wrong worker ID. - Files changed:
server/src/services/plugin-tool-dispatcher.ts,server/src/services/plugin-loader.ts,server/src/__tests__/plugin-database.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Extended
registerPluginToolsto accept an optional database plugin ID, passed the database ID from the plugin loader, and added regression coverage that plugin activation registers manifest-key namespaced tools with the database ID for worker lookup. - Verification command:
pnpm exec vitest run server/src/__tests__/plugin-database.test.ts;pnpm --dir server typecheck; restarted isolated server; live kitchen-sinkplugin tools; liveplugin tool:execute; cleanupplugin uninstall --force. - Remaining risk: Low; lifecycle DB-backed registration already used the database ID, and this aligns initial loader registration with that path.
BUG-009 - token agent list --agent <agent-id> failed even when the agent exists
- Status: Fixed and live-verified.
- Severity: Low CLI argument parity bug.
- Reproduction command:
pnpm paperclipai token agent list --company-id 12e9db4b-f66c-459b-959e-d645002240fb --agent 1dd601a1-031a-4225-b005-419427fd059f --json. - Expected result:
--agentaccepts the documented agent ID, shortname, or unambiguous name. - Actual result: The command returned
404: Agent not foundfor the ID form; the name form worked. - Suspected cause: The token command always called the reference lookup route
/api/agents/:ref?companyId=...; the server route did not resolve the UUID ref in that lookup mode. - Files changed:
cli/src/commands/client/token.ts,cli/src/__tests__/token.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Detect UUID-form agent refs in the CLI, fetch
/api/agents/:iddirectly, and verify the returned agent belongs to the requested company before listing/creating/revoking keys. - Verification command:
pnpm exec vitest run cli/src/__tests__/token.test.ts;pnpm --dir cli typecheck; live isolatedtoken agent list --company-id <company-id> --agent <agent-id> --json. - Remaining risk: Low; non-ID references continue to use the existing company-scoped lookup path.
BUG-007 - worktree:make can recurse through pnpm shim when HOME is isolated
- Status: Fixed and live-verified.
- Severity: Medium local-dev/worktree reliability bug.
- Reproduction command:
HOME=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/shell-home pnpm paperclipai worktree:make cli-parity-wt --home /Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/worktree-instances --from-config /Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json --server-port 3198 --db-port 54331 --seed-mode minimal. - Expected result: The command creates the scratch git worktree and runs one dependency install inside it.
- Actual result: After creating the git worktree,
installDependenciesBestEffort()executed barepnpm install. WithHOMEredirected for isolation, the user's pnpm shim repeatedly spawnedpnpm add pnpm@9.15.4under the scratch home and the command did not reach worktree initialization until the runaway process tree was stopped. - Suspected cause: The CLI did not reuse the pnpm executable that launched the current Paperclip command, so dependency installation was subject to PATH/shim behavior under an overridden
HOME. - Files changed:
cli/src/commands/worktree.ts,cli/src/__tests__/worktree.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Added
resolvePnpmInstallInvocation()and changed worktree dependency installation to reusenpm_execpathwhen the CLI was launched through pnpm, falling back to barepnpmonly when no pnpm launcher is available. - Verification command:
pnpm exec vitest run cli/src/__tests__/worktree.test.ts;pnpm --dir cli typecheck; live isolatedworktree:cleanup --forcefor the partial worktree; live isolatedworktree:make ... --seed-mode minimal;worktree:list --json;worktree env --config <scratch-worktree-config> --json;worktree:merge-history --from paperclip-cli-parity-wt --to current --company CLI --dry. - Remaining risk: Low. If Paperclip is launched outside pnpm, dependency installation still falls back to PATH lookup as before.
BUG-008 - configure --section <invalid> printed an error but exited 0
- Status: Fixed and live-verified.
- Severity: Low command UX/scripting bug.
- Reproduction command:
pnpm paperclipai configure --config /Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/home/instances/cli-api-parity/config.json --section invalid-section. - Expected result: Invalid non-interactive configuration input should produce a failing process exit code so scripts can detect the error.
- Actual result: CLI printed
Unknown section: invalid-section...but exited with status0. - Suspected cause:
configure()logged and returned without settingprocess.exitCode. - Files changed:
cli/src/commands/configure.ts,cli/src/__tests__/configure.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Set
process.exitCode = 1for missing config and unknown section early returns; added regression coverage for both paths. - Verification command:
pnpm exec vitest run cli/src/__tests__/configure.test.ts;pnpm --dir cli typecheck; live isolatedconfigure --config <scratch-config> --section invalid-sectionreturned exit code1. - Remaining risk: Low; interactive configure paths were not changed.
BUG-001 - context set erased existing profile fields
- Status: Fixed.
- Severity: High for isolated CLI testing; a non-default
apiBasecan be silently removed and later commands may fall back tohttp://localhost:3100ifPAPERCLIP_API_URLis absent. - Reproduction command:
pnpm paperclipai context set --api-base http://127.0.0.1:3197 --use --json; thenpnpm paperclipai context set --company-id <company-id> --use --json; thenpnpm paperclipai context show --json. - Expected result: Profile preserves existing
apiBasewhile addingcompanyId. - Actual result: Profile only contained
companyId;apiBasewas removed. - Suspected cause:
context setpassed an object containing keys withundefinedvalues intoupsertProfile, and the merge spread those undefined values over existing properties. - Files changed:
cli/src/commands/client/context.ts;cli/src/client/context.ts;cli/src/__tests__/context.test.ts. - Fix summary: Build context command patches from provided fields only, and make
upsertProfileignore undefined values while still allowing empty strings to delete fields. - Verification command:
pnpm exec vitest run cli/src/__tests__/context.test.ts;pnpm --dir cli typecheck;pnpm paperclipai context show --json. - Remaining risk: Low; behavior is covered at the context store layer and typechecked.
MISMATCH-001 - Documented access whoami command is not registered
- Status: Fixed and live-verified.
- Severity: Low command UX/docs drift.
- Reproduction command:
pnpm paperclipai access whoami --json. - Expected result: Access identity command succeeds as documented in the runbook.
- Actual result: CLI exits with
unknown command 'access'. - Suspected cause:
registerAccessCommandsregisterswhoamias a top-level command, not under anaccessgroup. - Files changed:
cli/src/commands/client/access.ts,cli/src/__tests__/access-parity.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Added
paperclipai access whoamias an alias for the existing top-levelwhoamicommand. - Verification command:
pnpm exec vitest run cli/src/__tests__/access-parity.test.ts;pnpm --dir cli typecheck;pnpm paperclipai access whoami --json. - Remaining risk: Low.
BUG-002 - issue interaction:accept rejected omitted optional selected keys
- Status: Fixed.
- Severity: Medium CLI/API parity bug; the command help marks
--selected-client-keysoptional, but omitting it made the CLI fail before calling the API. - Reproduction command:
pnpm paperclipai issue interaction:accept <issue-id> <request-confirmation-interaction-id> --json. - Expected result: The CLI sends
{}and the API accepts the pending request confirmation. - Actual result: CLI validation failed with
selectedClientKeystoo small because omitted input was converted to[]. - Suspected cause:
parseCsv(undefined)returns[], andinteraction:acceptalways included that value in the payload. - Files changed:
cli/src/commands/client/issue.ts;cli/src/__tests__/issue-subresources.test.ts. - Fix summary: Preserve
undefinedwhen--selected-client-keysis omitted; keep CSV parsing for explicit values. - Verification command:
pnpm exec vitest run cli/src/__tests__/issue-subresources.test.ts;pnpm --dir cli typecheck. - Remaining risk: Low; focused CLI command wrapper coverage now includes omitted and explicit selected-key cases.
BUG-003 - Malformed tree hold ID returned server 500
- Status: Fixed.
- Severity: Medium API robustness bug; malformed user input reached a UUID database comparison and surfaced as a 500.
- Reproduction command:
pnpm paperclipai issue tree-hold:get <issue-id> null --jsonorpnpm paperclipai issue tree-hold:release <issue-id> null --json. - Expected result: Invalid hold IDs return a 400 client error without querying the tree hold service.
- Actual result: Server returned
API error 500: Internal server error; server log showedinvalid input syntax for type uuid: "null". - Suspected cause: Tree hold routes did not validate
holdIdbefore passing it to service/database code. - Files changed:
server/src/routes/issue-tree-control.ts;server/src/__tests__/issue-tree-control-routes.test.ts. - Fix summary: Validate
holdIdwithisUuidLikein get/release routes and return{ error: "Invalid hold ID" }with status 400. - Verification command:
pnpm exec vitest run server/src/__tests__/issue-tree-control-routes.test.ts;pnpm --dir server typecheck. - Remaining risk: Low; route-level regression covers both malformed get and release paths.
MISMATCH-002 - issue interaction:cancel command is generic but API only cancels questions
- Status: Fixed help text.
- Severity: Low command UX drift.
- Reproduction command:
pnpm paperclipai issue interaction:cancel <issue-id> <request-confirmation-interaction-id> --reason "..." --json. - Expected result: Either the command help states it only applies to
ask_user_questions, or request confirmations expose a cancel/supersede flow. - Actual result: API returns
422: Only ask_user_questions interactions can be cancelled. - Suspected cause: CLI command name/help is generic while server service method is
cancelQuestions. - Files changed:
cli/src/commands/client/issue.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Updated command description to say it cancels an
ask_user_questionsinteraction. - Verification command:
pnpm exec vitest run cli/src/__tests__/issue-subresources.test.ts;pnpm --dir cli typecheck;pnpm paperclipai issue interaction:cancel --help. - Remaining risk: Low; server still enforces the interaction kind.
MISMATCH-003 - issue recovery:resolve help overstates valid restored statuses
- Status: Fixed help text.
- Severity: Low command UX drift.
- Reproduction command:
pnpm paperclipai issue recovery:resolve <issue-id> --action-id <action-id> --outcome restored --source-issue-status blocked --json. - Expected result: Help text and validation agree on valid source statuses for
restoredoutcomes. - Actual result: Help says
--source-issue-statusacceptstodo, done, in_review, or blocked; validator rejectsblockedfor--outcome restoredwithRestored recovery actions must move the source issue to todo, done, or in_review. - Suspected cause: CLI option description lists the broad enum rather than outcome-specific constraints.
- Files changed:
cli/src/commands/client/issue.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Updated option description to state
blockedis only valid for blocked outcomes. - Verification command:
pnpm exec vitest run cli/src/__tests__/issue-subresources.test.ts;pnpm --dir cli typecheck;pnpm paperclipai issue recovery:resolve --help. - Remaining risk: Low; validation remains server-side/schema-driven.
MISMATCH-004 - agent instructions-path:update help does not expose process adapter requirements
- Status: Fixed and verified.
- Severity: Low command UX drift.
- Reproduction command:
pnpm paperclipai agent instructions-path:update <process-agent-id> --payload-json '{"path":"docs/cli-parity.md"}' --json. - Expected result: Help or validation guidance makes clear that process adapters need an explicit
adapterConfigKey, and relative paths needadapterConfig.cwd. - Actual result: First attempt failed with
No default instructions path key for adapter type 'process'. Provide adapterConfigKey.A second attempt with a relative path andadapterConfigKeyfailed withRelative instructions path requires adapterConfig.cwd to be set to an absolute path. - Suspected cause: CLI help only describes the JSON payload type; adapter-specific path requirements are enforced server-side.
- Files changed:
cli/src/commands/client/agent.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Updated the command description and
--payload-jsonhelp to call out process-adapteradapterConfigKey, relative pathadapterConfig.cwd, and an example payload. - Verification command:
pnpm exec vitest run cli/src/__tests__/agent-lifecycle.test.ts;pnpm --dir cli typecheck;pnpm paperclipai agent instructions-path:update --help. - Remaining risk: Low; this is help text only and server-side validation remains authoritative.
MISMATCH-005 - invite test-resolution omits required URL query
- Status: Fixed and live-verified.
- Severity: Low command/API parity bug.
- Reproduction command:
pnpm paperclipai invite test-resolution <invite-token> --json. - Expected result: Command either supplies a documented URL option or the API accepts token-only resolution testing.
- Actual result: API returns
400: url query parameter is required. - Suspected cause: CLI wrapper maps
invite test-resolution <token>directly to/api/invites/:token/test-resolutionwithout anyurlquery option. - Files changed:
cli/src/commands/client/access.ts,cli/src/__tests__/access-parity.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Added required
--url <url>option and forwards it as theurlquery parameter. - Verification command:
pnpm exec vitest run cli/src/__tests__/access-parity.test.ts;pnpm --dir cli typecheck;pnpm paperclipai invite test-resolution <token> --url https://example.com/invite/<token> --json. - Remaining risk: Low; local/private URLs are still rejected by the API guard as intended.
MISMATCH-006 - join list --status pending is rejected; API expects pending_approval
- Status: Fixed and live-verified.
- Severity: Low command UX drift.
- Reproduction command:
pnpm paperclipai join list --company-id <company-id> --status pending --request-type agent --json. - Expected result: Help or docs clarify valid join statuses, or common alias
pendingis accepted. - Actual result: API validation rejects
pending; valid values includepending_approval,approved, andrejected. - Suspected cause: CLI exposes a free-form status string with no enum guidance.
- Files changed:
cli/src/commands/client/access.ts,cli/src/__tests__/access-parity.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary:
join list --status pendingnow normalizes topending_approval; help lists canonical statuses. - Verification command:
pnpm exec vitest run cli/src/__tests__/access-parity.test.ts;pnpm --dir cli typecheck;pnpm paperclipai join list --company-id <company-id> --status pending --request-type agent --json. - Remaining risk: Low.
MISMATCH-007 - Public docs/catalog CLI routes missing or inconsistent
- Status: Fixed and live-verified.
- Severity: Medium CLI/API parity gap.
- Reproduction command:
pnpm paperclipai openapi --json;pnpm paperclipai available-skill get cmux --json;pnpm paperclipai llm agent-configuration --json;pnpm paperclipai llm agent-icons --json;pnpm paperclipai llm agent-configuration:adapter process --json. - Expected result: Registered CLI commands map to available API routes and return the OpenAPI document, skill markdown, and LLM prompt docs.
- Actual result: Initially,
openapiand all testedllmcommands returned404: API route not found.available-skill listreturnedcmuxfrom the real Claude home, butavailable-skill get cmuxreturned404: Skill not found. - Suspected cause: LLM routes were mounted at root while the CLI calls
/api/llms; available-skill discovery usedHOME/.claude/skillsinstead ofCLAUDE_HOME; OpenAPI generation was referenced by CLI/docs but no route was mounted. - Files changed:
server/src/app.ts,server/src/routes/access.ts,server/src/routes/openapi.ts,server/src/__tests__/openapi-routes.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Mounted LLM docs routes under
/api; made available-skill discovery honorCLAUDE_HOME, include built-in Paperclip repo skills, and fetch safe skill markdown consistently; added/api/openapi.json, then upgraded it from the initial path inventory to the schema-backedOpenAPIRegistry/OpenApiGeneratorV3implementation from the parity reference. - Verification command:
pnpm exec vitest run server/src/__tests__/llms-routes.test.ts cli/src/__tests__/access-parity.test.ts;pnpm --dir server typecheck;pnpm --dir cli typecheck; livellmandavailable-skillcommands after restart;pnpm exec vitest run server/src/__tests__/openapi-routes.test.ts; livecurl http://127.0.0.1:3197/api/openapi.json; livepnpm paperclipai openapi --json; follow-up live schema-backedpaperclipai openapi --json. - Remaining risk: Medium-low; the generator now includes shared Zod request schemas and security metadata, but response schemas remain intentionally generic for most endpoints until the API exports reusable response schemas.
BUG-006 - Available skill catalog ignored isolated CLAUDE_HOME
- Status: Fixed and live-verified.
- Severity: Medium isolation bug for local E2E runs.
- Reproduction command:
CLAUDE_HOME=/Users/aronprins/Documents/PaperclipAI/paperclip/tmp/cli-api-parity/claude-home pnpm paperclipai available-skill list --json. - Expected result: Skill discovery uses the isolated Claude home or built-in repo skills only.
- Actual result: Before the fix, the list included
cmuxfrom the real user Claude skills home, andavailable-skill get cmuxfailed because only a hardcoded Paperclip subset was fetchable. - Suspected cause: Server code read
HOME/.claude/skillsdirectly and did not add built-in Paperclip skills unless they were present in Claude's skills directory. - Files changed:
server/src/routes/access.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Use
CLAUDE_HOME/skillswhenCLAUDE_HOMEis set, include built-in Paperclip skills in catalog output, and resolve safe skill markdown from both Claude and Paperclip skills directories. - Verification command: live
available-skill list,available-skill get paperclip, andavailable-skill get cmuxafter restarting the isolated server. - Remaining risk: Low; this is runtime environment-sensitive and covered by live isolated verification.
MISMATCH-008 - paperclipai health is not registered
- Status: Fixed and live-verified.
- Severity: Low command/API parity gap.
- Reproduction command:
pnpm paperclipai health --json. - Expected result: The CLI has a documented health command, or docs consistently direct users to
curl <api-url>/api/health. - Actual result: Commander returned
unknown command 'health'. - Suspected cause: Health checking exists as an API endpoint and setup/doctor workflow, but not as a CLI client command.
- Files changed:
cli/src/commands/client/access.ts,cli/src/__tests__/access-parity.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Added a top-level
healthcommand that calls/api/health. - Verification command:
pnpm exec vitest run cli/src/__tests__/access-parity.test.ts;pnpm --dir cli typecheck;pnpm paperclipai health --json. - Remaining risk: Low.
BUG-004 - Creating a second local environment returned 500 instead of conflict
- Status: Fixed and live-verified.
- Severity: Medium API error handling bug.
- Reproduction command:
pnpm paperclipai environment create --company-id 12e9db4b-f66c-459b-959e-d645002240fb --payload-json '{"name":"CLI parity local env","description":"Disposable CLI parity environment","driver":"local","config":{"cwd":"/Users/aronprins/Documents/PaperclipAI/paperclip"}}' --json. - Expected result: Controlled
409or other user-facing validation error because a default local environment already exists for the company. - Actual result: API returned
500: Internal server error; server log showed duplicate key violation forenvironments_company_driver_idx. - Suspected cause: The route attempted the insert without checking the partial unique constraint on
(company_id, driver)fordriver = 'local'. - Files changed:
server/src/routes/environments.ts,server/src/__tests__/environment-routes.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Added a route-level pre-insert check that throws
409when a local environment already exists for the company; added regression coverage. - Verification command:
pnpm exec vitest run server/src/__tests__/environment-routes.test.ts;pnpm --dir server typecheck; restarted isolated server and reran the reproduction command, which now returns409. - Remaining risk: Low; create flow for non-local environment drivers still needs separate positive coverage.
BUG-005 - Secret lifecycle API endpoints lacked CLI wrappers
- Status: Fixed and live-verified.
- Severity: Medium CLI/API parity gap.
- Reproduction command:
pnpm paperclipai secrets --helpdid not expose commands forPATCH /api/secrets/:id,POST /api/secrets/:id/rotate,GET /api/secrets/:id/usage,GET /api/secrets/:id/access-events, orDELETE /api/secrets/:id. - Expected result: CLI can update, rotate, inspect usage/access events, and delete a secret, matching the OpenAPI parity reference.
- Actual result: CLI only supported list/create/link/provider/import/declaration/migration commands; a disposable managed secret could be created but not cleaned up through CLI.
- Suspected cause: Secret provider/import commands were added without completing the single-secret lifecycle wrapper set.
- Files changed:
cli/src/commands/client/secrets.ts,cli/src/__tests__/secrets.test.ts,doc/bugs/2026-05-24-cli-api-parity-e2e-log.md. - Fix summary: Added
secrets update,secrets rotate,secrets usage,secrets access-events, and guardedsecrets delete --yes --confirm <secret-id>commands. - Verification command:
pnpm exec vitest run cli/src/__tests__/secrets.test.ts;pnpm --dir cli typecheck; live scratch commands for update/rotate/usage/access-events/delete. - Remaining risk: Low;
secrets linkremains provider-dependent and correctly rejectslocal_encryptedexternal references.