## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package already provides the production protocol and execution spine. > - Contributors still need stable SDK surfaces, deterministic test tools, and local inspection tools. > - Those surfaces share generated contracts and must change as one package boundary. > - This pull request adds the package-local SDK, labs, examples, and drift checks. > - The benefit is a reviewable developer platform that does not change application execution selection. ## Linked Issues or Issue Description **Subsystem affected** `packages/paperclip-runner` — runner SDK, conformance tools, and developer tooling. **Problem or motivation** The production runner spine is present, but package consumers cannot build deterministic integrations, inspect sessions, or verify provider-neutral behavior through supported surfaces. **Proposed solution** Add browser, React, standalone, live-session, scenario, conformance, and evaluation surfaces. Add generated contract inventories and package-local verification scripts. Keep production application routing unchanged. **Alternatives considered** We considered splitting each generated catalog, SDK surface, and demo into separate pull requests. Those changes share exports, fixtures, and drift gates. Splitting them would create intermediate package states that do not build. **Roadmap alignment** No overlapping item appears in `ROADMAP.md`. This work extends the runner package that is already on `master`. ## What Changed - Add browser, React, standalone, live-session, and issue-thread SDK surfaces. - Add deterministic mock control-plane, scenario, conformance, replay, and evaluation tools. - Add bounded Codex, OpenCode, and ACPX development transports and fixtures. - Keep deferred managed-provider execution fail-closed. Persisted compatibility data remains readable. - Add generated capability inventories with their source files and drift checks. - Add examples, package documentation, browser checks, and clean-consumer checks. - Preserve the reviewed protocol bounds, replay compatibility aliases, process environment isolation, and semantic redaction limits. - Update the ACPX package patch that the existing workspace patch registry already tracks. - Do not change `pnpm-lock.yaml`, repository workflows, server runtime selection, or the application UI. ## Verification GitHub Actions is the verification authority for this pull request. The repository CI, package TypeScript and Rust checks, package tests, generated-output drift checks, browser checks, security scans, and Greptile review must pass on the exact head. Local test suites were not run because this series uses parallel GitHub Actions for verification. ## Risks This is a large greenfield package change. The main risks are public export drift, generated-output drift, and optional React consumer compatibility. Package boundary checks, clean-consumer checks, and browser tests cover those risks. Production adapter selection and server execution are outside this pull request. ## Stack 1. **This PR:** runner SDK and developer tooling. 2. [Codex production server integration](https://github.com/paperclipai/paperclip/pull/12616). 3. [Provider-neutral task-thread UI](https://github.com/paperclipai/paperclip/pull/12617). ## Model Used OpenAI Codex, GPT-5, high-reasoning mode, with tool use and code execution. ## 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 searched GitHub for duplicate or related PRs and linked them above - [x] I have described the issue in-PR following the feature request template - [x] I have not referenced internal/instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge
9.4 KiB
Semantic Catalog Reconciliation
Document status: Canonical reconciliation ledger (TASK-17025 gate + TASK-17039 collapse)
Date: 2026-08-11
Source of truth: src/catalog/canonical-operations.ts (CAPABILITY_CANONICAL_OPERATIONS) — the single hand-authored 41-operation list. Both catalog modules derive their operation set, placement, required claims, and task-mode policy from it.
Drift authority: src/catalog/reconciliation.ts (machine-readable ledger), drift-checked by src/catalog/reconciliation.test.ts and src/catalog/catalog-docs.test.ts.
Parent plan: Runner foundation review plan (TASK-17016), deliverable D and execution step 1.
Purpose
The runner carried two independently hand-maintained semantic catalogs. TASK-17025
established one machine-readable authority over both and recorded every
divergence. TASK-17039 performed the physical collapse: the authoritative
operation list, placement, required claims, and task-mode policy now live once in
src/catalog/canonical-operations.ts, and both catalog modules derive from it —
neither declares an independent operation list or an independent claim/mode
policy any longer. Each catalog supplies only its per-surface presentation
(title, description, input/output schema, and the scenario-only mock mapping and
redaction rules), and a bidirectional parity check fails the build if either
catalog's presentation set drifts from the canonical surface.
The two catalogs
| Catalog | Module | Count | Descriptor | Consumers |
|---|---|---|---|---|
| Scenario / eval | src/tools/ |
37 (14 always + 23 optional) | Rich: placement (disposition), sideEffectClass, idempotency, redaction, mockCommandMapping |
src/scenarios/*, src/conformance/*; package-root default export |
| Live runtime | src/semantic-tools/ |
28 (13 always + 15 optional) | Live: exposure, allowedModes, disabledByDefault, provider input/output schemas; runtime dispatcher + policy + redaction |
src/live/* (live Codex), src/issue-thread/*, generated semantic-tool-contracts.json; package-root acceptedCapabilitySemanticTools |
Reconciled op-set relationship (pinned by the drift test):
- 24 shared operation ids.
- 13 scenario-only:
administer_company,export_company,inspect_operation_result,list_cases,list_company_skills,list_goals,list_projects,list_routines,list_secret_metadata,manage_routine,read_secret_value,sync_company_skills,upsert_case. - 4 live-only:
get_agent,get_approval,get_approval_context,schedule_wake. - Union = 41 operations.
Canonical authority decision
- Single source of truth:
src/catalog/canonical-operations.tshand-authors the 41-op union exactly once (CAPABILITY_CANONICAL_OPERATIONS), each entry naming surfaces, placement, optional group, claims, task modes, roles, side-effect class, idempotency, disabled-by-default, real-binding status, PRP evidence, and legacy aliases. Both catalog modules import it and project it:src/tools/renders the rich scenario descriptor andsrc/semantic-tools/renders the live provider descriptor. - Drift ledger:
src/catalog/reconciliation.tsenriches the canonical list with the scenario mock mapping and redaction flag (CAPABILITY_CANONICAL_CATALOG), andcapabilityCatalogReconciliation()recomputes the op-set summary and any remaining metadata divergence between the two catalogs' actual descriptors. - Neither
src/tools/norsrc/semantic-tools/is canonical; both are projections ofcanonical-operations.ts.
Real-binding status (before real Paperclip service binding)
No operation is bound to a real Paperclip service yet; the deterministic mock is the only backend (real-service binding is deliverable G). Each operation's current executability is classified as:
live_codex(27): executed by the live dispatcher against the mock and exposed to live Codex — the 24 shared ops (minus the test-only escape hatch) plus the 4 live-only ops.scenario_mock(13): defined only in the scenario/eval catalog and driven through the scenario runtime / mock extensions; no live dispatcher binding.test_only(1):generic_api_request— the escape hatch, which by rule cannot count as product capability coverage.
Divergence ledger (after the TASK-17039 collapse)
requiredClaims and task modes are single-sourced from
canonical-operations.ts, so the two catalogs cannot diverge on them; the drift
test asserts both divergence sets are now empty. The reconciliation ledger
recomputes divergences from the two catalogs' actual descriptors:
- Claims (0): unified.
generic_api_requestcarries a single claim,test:generic_api_request, on both surfaces. - Task modes (0): unified to one canonical policy — the live runtime
exposure policy unioned with
skill_test. Reads stay open in every mode; work-writes (report_progress,write_document,request_human_input,register_deliverable) allowstandard/planning/skill_test; lifecycle and state writes (finish_task,block_task,request_review,create_task,set_dependencies, request/decide/comment approvals,control_workspace_service) allowstandard/skill_test. Theskill_testmode makes every operation the eval harness must drive drivable, while the live runtime keeps its intended per-mode exposure. - Input-schema shape (reviewed intentional projection): one input contract is
projected two ways by design — the live provider descriptor threads
idempotencyKeyin-band with provider length/pattern bounds for the model, while the observable scenario runtime threads idempotency out-of-band. This is a single reviewed projection recorded in the ledger, not two independently authored schemas.
Effect on live provider schemas (QA gate)
- The generated live contract golden
generated/capability/semantic-tool-contracts.jsonis byte-identical after the collapse: it serializes name, description, input/output schema, exposure, and required claims — none of which changed on the live surface (allowedModesis not serialized). - The live runtime
allowedModesgainedskill_testfor the nine previouslystandard-only operations (finish_task,block_task,request_review,create_task,set_dependencies,request_approval,decide_approval,control_workspace_service,schedule_wake). This is a behavioral change to eval-harness exposure only; real live tasks never run inskill_testmode.
Legacy MCP aliases
Legacy MCP aliases are indexed in spec/capability/mcp-tool-map.yaml
(inventoryRole: legacy_alias_index, generated from packages/mcp-server). Each
alias row carries a foldedInto disposition linking it to the native eval/
operation that now covers its behavior; the reconciliation drift test asserts
every row has one. The authority additionally records the direct native
operation for the well-known aliases (for example paperclipListAgents →
list_agents, paperclipGetAgent → get_agent, paperclipListIssues →
search_tasks, paperclipCreateIssue → create_task).
Collapse decisions executed by TASK-17039
- One source of truth.
src/tools/andsrc/semantic-tools/no longer declare independent operation lists; both projectCAPABILITY_CANONICAL_OPERATIONS. Placement, optional group, required claims, task modes, allowed roles, side-effect class, idempotency, and disabled-by-default are single-sourced. Bidirectional parity checks fail the build on any drift between a catalog's presentation and the canonical surface. generic_api_requestclaim unified totest:generic_api_request(scenario callers/tests updated). It staystest_onlyand is excluded from product capability coverage.- One canonical task-mode policy (live runtime policy ∪
skill_test); the ledger's 15 task-mode divergences are resolved to zero. - Input schema unified as one contract, projected two ways — idempotency in-band with provider bounds for the model, out-of-band for the observable scenario runtime — recorded as the single reviewed intentional projection.
- Placement of scenario-only (13) and live-only (4) operations retained. The
13 scenario-only ops stay
scenario_mock(eval-only via mock extensions); the 4 live-only reads/continuation ops (get_agent,get_approval,get_approval_context,schedule_wake) staylive_codexwith no scenario projection. No operation crossed surfaces this increment; a future real-service binding (deliverable G) is where scenario-only ops would gain a live binding.
Consumed by the real-surface-ledger (deliverable B) and eval (deliverable F)
tasks: the live contract golden is unchanged; the only behavioral delta is the
allowedModes skill_test addition described above.
Verification
src/catalog/reconciliation.test.ts— pins the op-set relationship, asserts both catalogs derive their operation set from the canonical source, asserts claims/modes/placement are single-sourced (no divergence), and requires a reviewed disposition for the surviving input-schema projection.src/catalog/catalog-docs.test.ts— recomputes the catalog counts and membership indocs/capability-semantic-tools.mdfrom the catalog so a stale hand count fails.- Live golden byte-identity checked by
check:semantic-contracts; the scenario and live runtime behavior is covered by thetest:scenariossuites.