diff --git a/doc/plans/2026-10-02-opencode-skill-routing-link-qualification.md b/doc/plans/2026-10-02-opencode-skill-routing-link-qualification.md index 1573148ef48..79f0c4b5193 100644 --- a/doc/plans/2026-10-02-opencode-skill-routing-link-qualification.md +++ b/doc/plans/2026-10-02-opencode-skill-routing-link-qualification.md @@ -61,3 +61,15 @@ unchanged under permitted local execution: 906 assertions passed in the original 921-assertion attempt, and all 82 selected assertions passed in the permitted retry, including every originally failed assertion. No new model calls or old verdict changes are part of this follow-up. + +Fresh native-PR review caught a supported edge case in that later recipe: +`issue.identifier` may be null. The recipe now uses the current issue ID in the +unprefixed UI route when no identifier exists. Provider-free tests cover both +null and absent identifiers, preserving the returned document key. Source review +confirms that the board resolves the loaded issue's actual company and preserves +the document hash; no agent-side company fetch is needed. This route logic also +corrects wrong prefixes, so the frozen candidate's `PAP` href is noncanonical, +not a proven broken link. No authenticated click replay or further model run was +made. The previous 4/5 review and local setup/timing failures remain retained; +current focused document/source/manifest/admission checks pass 56 assertions and +E2E typecheck passes. This correction still has no live qualification. diff --git a/doc/plans/2026-10-02-stock-harness-paperclip-checklist.md b/doc/plans/2026-10-02-stock-harness-paperclip-checklist.md index b495865d745..eb5a2d819b2 100644 --- a/doc/plans/2026-10-02-stock-harness-paperclip-checklist.md +++ b/doc/plans/2026-10-02-stock-harness-paperclip-checklist.md @@ -250,9 +250,13 @@ Starting points: [onboarding assets](../../server/src/onboarding-assets/), [hiring skill and references](../../skills/paperclip-create-agent/), [teams catalog](../../packages/teams-catalog/catalog/). -Dotta approved hiring implementation; it is ongoing in a separate branch from -master. The hiring work owns its skill/references, CEO/CoS assets and team -catalog. This qualification branch does not change those files. +Dotta approved hiring implementation in separate draft +[PR #14985](https://github.com/paperclipai/paperclip/pull/14985), branch +`codex/tiny-hiring-templates`, published source +`5b05d9dcf99b7b1e84510735ab04e336d669ee44`. The hiring work owns its +skill/references, CEO/CoS assets and team catalog. This branch does not change +those files; PR CI/review and live qualification remain separate from its unit +checks. [Prompt diffs and preserved scope](https://github.com/paperclipai/paperclip/blob/5b05d9dcf99b7b1e84510735ab04e336d669ee44/doc/plans/2026-10-02-hiring-template-prompt-diff.md). The read-only audit found four onboarding CEO files (1,897 words), a 164-word CoS manual, four role examples (coder 652, QA 619, UX 1,325, security 1,724 words), @@ -268,7 +272,23 @@ review checklist would regenerate the removed operating policies. product-required behavior rather than assuming every rule is redundant. Custom and existing bundles and governance remain deliberate rollout boundaries. -Separate hiring PR/branch link and prompt diffs are pending. +Specialized Summarizer, Reflection Coach and Wiki Maintainer prompts remain +unchanged for separate product-contract review; optional Content Lead was already +tiny. The generic non-CEO fallback belongs to PR #14948. PR #14985 does not reduce +every shipped specialized agent. + +Its explicit `hiring-templates` suite selects native local Codex and ACPX Claude +`hire-coder-template-reuse` cells: a real default CEO, explicitly requested +production hiring skill/coder reference, independently scored saved JSON +artifacts and session reuse. Outcome and source/read coverage are separate; +missing or redacted receipts do not prove no regression. The existing first-task +suite covers actual wizard CoS snapshot selection. A matched union qualification +will hold the reduced manual/shared/operational skill and native completion +guidance constant while restoring only historical hiring sources in baseline. +Two cells per variant, five expected provider turns each: four cells / 20 turns, +15 minutes each, no automatic retries or broader selection. Exact-source +credential-free admission and frozen refs are required before dispatch; no +hiring providers have run yet. ## 4. Fix repository context while retaining Paperclip configuration @@ -448,7 +468,7 @@ will address them. Record intentional behavior explicitly rather than as a bug. - F19: Original prompt-removal cohorts loaded Paperclip; OpenCode skill truncation omitted the late API recipe. The early repair fixed Claude in one paired trial. In the repaired original OpenCode assignment, Paperclip was first loaded only during disposition recovery after a local-file write. Shared legacy operational-skill delivery/selection needs review before more recipe expansion. - F20: Explicit repaired OpenCode reads the early recipe/reference and saves a public document/revision, but hands off a code-formatted path rather than a clickable anchor. Baseline provides a clickable API URL, rejected by the UI-only oracle. Preserve both grades; clarify future clickable UI-link fixture and review the smallest link example separately. - F22: Legacy operational skill mounting is already mandatory, but its discovery description omitted ordinary task/heartbeat work and document delivery. The approved narrow fix expands stock metadata selection and adds a real Markdown link example in the existing reference. Original + clarified-explicit OpenCode pairs both pass in both variants, so improvement causality is not established. Candidate loads the operational skill/reference before public delivery; baseline original writes locally first, then saves publicly in the same assignment. Original candidate copies the example PAP prefix into its link while baseline supplies a bare slug path; neither is scored by the original link-free oracle. No full-body injection or native-tool leakage. ACP Claude names-only metadata, custom ACP unsupported delivery, OpenClaw wrappers and Pi HOME differences remain distinct follow-ups. -- F23: The new original OpenCode candidate copies `/PAP/issues/RUN-1#document-context-integrity-output` from the literal example despite actual prefix RUN. It passes durable-document grading but has an incorrect-prefix handoff. Baseline original also lacks a clickable canonical link. Approved reference-only correction now derives the link from `issue.identifier` and the saved receipt key. Independent provider-free calibration checks two other prefixes, redirected keys and rejects a wrong-company link; 25 focused document/source tests, canonical metadata checks and E2E typecheck pass. This later source correction is not live-qualified by the preserved runs; no further paid rerun. +- F23: The new original OpenCode candidate copies `/PAP/issues/RUN-1#document-context-integrity-output` from the literal example despite actual prefix RUN. It passes durable-document grading but has an incorrect-prefix handoff. Baseline original also lacks a clickable canonical link. Approved reference-only correction now derives the link from `issue.identifier` and the saved receipt key. Independent provider-free calibration checks two other prefixes, redirected keys and rejects a wrong-company link; 25 focused document/source tests, canonical metadata checks and E2E typecheck pass. The recipe now also handles null/absent identifiers through the supported issue-ID route; fresh review caught the initial nullable edge. 56 focused checks pass. Source review shows the UI corrects wrong prefixes, so the frozen PAP href is noncanonical rather than proven broken. These later corrections are not live-qualified by the preserved runs; no further paid rerun. - F21: Skill heading insertion shifted both generated capability inventories. General CI caught stale metadata after the frozen repair campaign’s narrower build admitted providers. Regenerate canonical derived files and require stale-manifest/inventory checks before future provider admission. For each completed item, add the chosen behavior, changed paths, verification diff --git a/packages/paperclip-runner/docs/capability-contract.md b/packages/paperclip-runner/docs/capability-contract.md index 5586c64065a..cf14bc59966 100644 --- a/packages/paperclip-runner/docs/capability-contract.md +++ b/packages/paperclip-runner/docs/capability-contract.md @@ -171,7 +171,7 @@ The skill/reference inventory and eval cases are the only normative behavior sou | skill:skills/paperclip/references/company-skills.md:notes:256 | optional_agent_tool | skills/paperclip/references/company-skills.md:256 | | skill:skills/paperclip/references/issue-documents.md:issue-documents-through-the-api:1 | always_agent_tool | skills/paperclip/references/issue-documents.md:1 | | skill:skills/paperclip/references/issue-documents.md:create-a-document:8 | always_agent_tool | skills/paperclip/references/issue-documents.md:8 | -| skill:skills/paperclip/references/issue-documents.md:update-or-resolve-an-unclear-write:47 | optional_agent_tool | skills/paperclip/references/issue-documents.md:47 | +| skill:skills/paperclip/references/issue-documents.md:update-or-resolve-an-unclear-write:49 | optional_agent_tool | skills/paperclip/references/issue-documents.md:49 | | skill:skills/paperclip/references/issue-workspaces.md:issue-workspace-runtime-controls:1 | optional_agent_tool | skills/paperclip/references/issue-workspaces.md:1 | | skill:skills/paperclip/references/issue-workspaces.md:discover-the-workspace:5 | optional_agent_tool | skills/paperclip/references/issue-workspaces.md:5 | | skill:skills/paperclip/references/issue-workspaces.md:control-services:23 | optional_agent_tool | skills/paperclip/references/issue-workspaces.md:23 | diff --git a/packages/paperclip-runner/generated/capability/capabilities.yaml b/packages/paperclip-runner/generated/capability/capabilities.yaml index 62ce0957f68..a2557fcd05c 100644 --- a/packages/paperclip-runner/generated/capability/capabilities.yaml +++ b/packages/paperclip-runner/generated/capability/capabilities.yaml @@ -1181,9 +1181,9 @@ "expectedMockState": "operation_result" }, { - "id": "skill:skills/paperclip/references/issue-documents.md:47", + "id": "skill:skills/paperclip/references/issue-documents.md:49", "kind": "skill_heading", - "sourceAnchor": "skills/paperclip/references/issue-documents.md#L47:update-or-resolve-an-unclear-write", + "sourceAnchor": "skills/paperclip/references/issue-documents.md#L49:update-or-resolve-an-unclear-write", "heading": "Update or resolve an unclear write", "primaryDisposition": "control_plane_owned", "semanticOperation": "runtime_reconciliation", diff --git a/packages/paperclip-runner/generated/capability/capability-contract.md b/packages/paperclip-runner/generated/capability/capability-contract.md index 828b28f88b0..4d124613015 100644 --- a/packages/paperclip-runner/generated/capability/capability-contract.md +++ b/packages/paperclip-runner/generated/capability/capability-contract.md @@ -5,6 +5,6 @@ Generated by `scripts/generate-capability-contract.mjs`; do not edit generated f - Skill/reference headings: 161 - Legacy MCP tools: 42 - Eval cases: 106 across 16 groups -- Deterministic content SHA-256: `62bb46560eae22b04c1a9fead8b5b5e6a372d3015b297325dc4f649924f945c8` +- Deterministic content SHA-256: `e577ca3ad6e6b045a7413ac11008013c8c12c2dc954f5a7876b86d96fbe017e8` Every row has exactly one primary disposition, a source anchor, a semantic operation, and a mock-state expectation. diff --git a/packages/paperclip-runner/spec/capability/capabilities.yaml b/packages/paperclip-runner/spec/capability/capabilities.yaml index d8d59892366..4170503c4bc 100644 --- a/packages/paperclip-runner/spec/capability/capabilities.yaml +++ b/packages/paperclip-runner/spec/capability/capabilities.yaml @@ -1965,9 +1965,9 @@ ] }, { - "id": "skill:skills/paperclip/references/issue-documents.md:update-or-resolve-an-unclear-write:47", + "id": "skill:skills/paperclip/references/issue-documents.md:update-or-resolve-an-unclear-write:49", "sourceKind": "skill_heading", - "sourceAnchor": "skills/paperclip/references/issue-documents.md:47", + "sourceAnchor": "skills/paperclip/references/issue-documents.md:49", "title": "Update or resolve an unclear write", "expectedSemantics": "Skill guidance headed “Update or resolve an unclear write”.", "primaryDisposition": "optional_agent_tool", @@ -1976,7 +1976,7 @@ "control_plane_invariant" ], "evidenceIds": [ - "skill:skills/paperclip/references/issue-documents.md:47" + "skill:skills/paperclip/references/issue-documents.md:49" ] }, { diff --git a/skills/paperclip/references/issue-documents.md b/skills/paperclip/references/issue-documents.md index f95755c7685..4033dcc9422 100644 --- a/skills/paperclip/references/issue-documents.md +++ b/skills/paperclip/references/issue-documents.md @@ -36,13 +36,15 @@ Construct a clickable Markdown link from the current issue and successful write receipt, then add it to the completion comment or response: ```javascript -const prefix = issue.identifier.split("-")[0]; -const documentUrl = `/${prefix}/issues/${issue.identifier}#document-${saved.key}`; +const issuePath = issue.identifier + ? `/${issue.identifier.split("-")[0]}/issues/${issue.identifier}` + : `/issues/${issue.id}`; +const documentUrl = `${issuePath}#document-${saved.key}`; const comment = `Saved [Task report](${documentUrl}).`; ``` Use the returned key: a locked document can redirect an agent's write to a new -document. +document. Unnumbered issues use their ID; the board resolves their company. ## Update or resolve an unclear write diff --git a/tests/runner-e2e/paperclip-document.test.ts b/tests/runner-e2e/paperclip-document.test.ts index 884ce61f570..4fd62239c0d 100644 --- a/tests/runner-e2e/paperclip-document.test.ts +++ b/tests/runner-e2e/paperclip-document.test.ts @@ -67,6 +67,20 @@ describe("explicit Paperclip document delivery", () => { }) as string; expect(gradeContextIntegrity({ ...scenario, checkpoints: [initial, final] }).every(row => row.passed)).toBe(true); }); + it.each([null, undefined])("the shipped recipe supports an unnumbered issue with identifier %s", identifier => { + const reference = readFileSync(new URL("../../skills/paperclip/references/issue-documents.md", import.meta.url), "utf8"); + const recipe = reference.match(/```javascript\n([\s\S]*?)```/)?.[1]; + expect(recipe).toBeDefined(); + const comment = runInNewContext(`${recipe}\ncomment`, { + issue: { id: "849c6474-ab4e-4428-981a-0b9a0207fa9b", identifier }, + saved: { key: "report-agent-redirected" }, + }) as string; + const target = comment.match(/\]\(([^)]+)\)/)?.[1]; + expect(target).toBeDefined(); + const url = new URL(target!, "https://paperclip.example"); + expect(url.pathname).toBe("/issues/849c6474-ab4e-4428-981a-0b9a0207fa9b"); + expect(url.hash).toBe("#document-report-agent-redirected"); + }); it("preserves the original ambiguous request and assigned output procedure", () => { expect(contextIntegrityScenario("assigned-skill-explicit-invocation", "probe").prompt).toBe( "Use the assigned Context integrity output skill for this task, then follow its instructions and finish the task. Do not create child tasks or unrelated deliverables.", diff --git a/tests/runner-e2e/stock-harness-checks.mjs b/tests/runner-e2e/stock-harness-checks.mjs index 444354a8933..8a1d4ddd965 100644 --- a/tests/runner-e2e/stock-harness-checks.mjs +++ b/tests/runner-e2e/stock-harness-checks.mjs @@ -43,7 +43,7 @@ export const stockHarnessGates = [ files: ["tests/runner-e2e/stock-harness-manifest.test.ts", "tests/runner-e2e/paperclip-document.test.ts", "tests/runner-e2e/stock-harness.test.ts", "tests/runner-e2e/stock-harness-checks.test.mjs", "tests/runner-e2e/stock-harness-admission.test.ts", "tests/runner-e2e/stock-harness-digest.test.ts", "tests/runner-e2e/select-rerun-artifacts.test.ts"], - required: ["requires generated capability manifests for the current skill sources", "the shipped recipe delivers the current", "rejects old SHA before providers", "allows toolchain paths and excludes every present or future credential", + required: ["requires generated capability manifests for the current skill sources", "the shipped recipe delivers the current", "the shipped recipe supports an unnumbered issue", "rejects old SHA before providers", "allows toolchain paths and excludes every present or future credential", "changes when the evaluated server/src/onboarding-assets/default/AGENTS.md changes", "changes when the evaluated packages/adapter-utils/src/server-utils.ts changes", "changes when the evaluated packages/shared/src/connection-intent-guidance.ts changes",