feat(fabrika): land skill-doctor — byte-exact upstream vendor, fabrika-shaped (#8048) - #8063
Conversation
…a-shaped (#8048) Vendors Warp Skill Doctor (MIT, warpdotdev/common-skills @ b811c243) byte-exact (blob-SHA verified): scorers, references, collectors, renderer, assets, both unittest suites, LICENSE. Upstream's SKILL.md is deliberately not vendored — SKILL.md is authored fresh as the fabrika routing surface (conventions §1/§2) with contract.md carrying collector flags, the scoring contract, and report artifacts by section (ADR 0296). PROVENANCE.md carries the byte-exact/editable split and the re-copy re-sync rule. A new CI job runs both upstream suites (#8048 §8); .gitignore covers the skill's results dir and Python bytecode. Inert on arrival: opencode collector is #8049, corpus discovery #8051.
No preview deploy
|
…nformance (#8048) Proposed test adaptation awaiting maintainer acceptance. Target 1 runs both unchanged upstream suites in an isolated temp tree against upstream's own SKILL.md, downloaded from the pinned commit b811c243 and hash-gated before use — the shipped fabrika SKILL.md never enters that tree. Target 2 runs a new fabrika-authored conformance suite (13 doc-level tests, PROVENANCE-listed) over the shipped SKILL.md/contract.md: session scoping, scoring contract with label-to-score mappings and aggregation weights, failed-conversation threshold and edit gate, section addressability, documented limitations, §4 literal commands. Workflow gains shell: bash + set -euo pipefail; explicit guards for download failure, blob mismatch, and conformance-file isolation. Replacement verified locally; PR CI pending.
|
heal-ci: ROUTED — PR #8063 @ e715358 → author Scheduled stall sweep: this pull request classifies as Detection only — this run merged nothing, re-ran nothing and spawned nothing. What to do about the flag is a driver decision; Posted by the |
|
governance: FAIL @ e715358 content:6428e5975ce8 — shipped corpus no longer reads the same in any repository Governance verdict — FAILScope. Corpus half — one contradiction, hand-readNo decision record is in this diff, so there was no subject to rank and Questions this change decides:
Evidence, run live, not inferred. With this PR's
This contradicts the standing rule that fabrika's shipped corpus must read the same in any repository — the rule ADR 0381 (live, accepted) puts behind a pre-merge local gate explicitly covering shipped markdown, and the rule ADR 0394 (live, accepted) applies in its narrower The guard did not exist at this branch's base ( Note for the repair, not a second finding. Gate half — empty reach, recorded
Whether this diff needs a code-owner approval is a separate question CODEOWNERS answers. |
|
review-skill: FAIL @ e715358 content:6428e5975ce8 — shipped skill text reds portability-guard; deviations disclosure absent review-skill — FAIL (round 1)Scope: 16 skill-class files at Findings1.
The guard did not exist at this branch's base (2026-09-05; the head is 417 commits behind 2. The repair is two-sided, and the second side is in this diff. 3. What passed
Editorial (
|
|
review-code: FAIL @ e715358 content:6428e5975ce8 — deviations disclosure absent; head blocked at governance floor review-code — FAIL (round 1)Scope: 2 code-class files at Findings1. 2. Blocked at head by the governance namespace, not by the tests. Criterion 7 — the CI jobDischarged at this head, and well built.
One non-blocking note: target 1 reaches the network at every run, so a Criterion 9 —
|
…itory (#8048) Drop every ticket number, issue URL and repo name from the fabrika-authored SKILL.md, contract.md and PROVENANCE.md, and carry the byte-exact upstream files that cannot be edited as per-file exemption rows instead.
|
Repair round 1 at 53e142c. Each FAIL finding, and what it got:
One disclosed extra: merging current Local verdicts at this head: portability-guard clean, skill-lint clean (95 files), — at 53e142c |
|
governance: PASS @ 53e142c content:6a9963d8b269 — no contradiction, and the two loosenings are narrow, reasoned and disclosed Governance verdict — PASS (round 2)Scope. Corpus half — the round-1 contradiction is gone, hand-read againNo decision record is in this diff, so there was no subject to rank and Round 1 failed on one contradiction: fabrika's shipped corpus carried pointers that resolve only in this repository. Re-run live over the head tree, I re-verified the vendor myself rather than taking the repair's word: Gate half — one loosening, judged on its own
1. 2. The leak-guard exemption for
Does it need its own ruling? No. ADR 0398 (live, accepted) is the record that governs this key: it names One note, not a finding and not this PR's to fix: ADR 0286 (live, accepted) puts a repo-specific set in config rather than in CLI source, and this policy lives in both by design, kept honest by a golden test. That tension predates this diff. The empty answer, written downBeyond the two edits above, no gate invariant is in this diff's reach. The new workflow adds a gate rather than weakening one — no Whether this diff needs a code-owner approval is a separate question CODEOWNERS answers. |
|
review-skill: PASS @ 53e142c content:6a9963d8b269 — portability clean, vendor byte-exact, criteria discharged review-skill — PASS (round 2)Scope: 16 skill-class files at Round 1 finding 1 — portability: cleared, verified live
What I checked beyond the exit code, because an allow-list is a floor that only shrinks and "clean" can be bought:
Criterion 11 (appended round 1) is discharged, including its second clause. Round 1 finding 2 — the conformance test moved with the docs
The vendor survived the repairI re-ran Criteria at this head
Editorial (
|
|
review-code: PASS @ 53e142c content:6a9963d8b269 — CI green at head, deviations disclosed, guard edits narrow review-code — PASS (round 2)Scope: 5 code-class files at Round 1 finding — the deviations disclosure now exists, and it is honest
The section discloses the loosening a reviewer is most likely to miss, in the entry class that fits it, with the reason and the test that holds it honest. That is what the section is for. The three new code files
A note on Criterion 7 — the CI job, re-read at this headDischarged. The workflow is byte-identical to round 1 and I confirmed the run rather than the intent: The design still reads well: two targets in one job, the job fails if either fails, no The round-1 note stands unchanged and is still not a finding: target 1 reaches Criterion 9 —
|
|
ship: AWAITING-CP-APPROVAL — PR #8063 @ 53e142c → human Machine gates read satisfied at this head (review-code, review-skill, governance) and CI is green, but the PR touches a control-plane path ( Owed: one approving review from a @kamp-us/control-plane member (usirin, cansirin, rasitds, notusirin) at this exact head. Do not rebase or force-push once that approval lands — a moved head voids it. |
Fixes #8048
Landing child of #8035 (epic). Vendors the Warp Skill Doctor (MIT,
warpdotdev/common-skills@b811c243) byte-exact intoclaude-plugins/fabrika/skills/skill-doctor/, already shaped to skill-conventions. Status: tests/lint passed; leak scan ran and failed on path-policy matches — the scan refused two doc surfaces on agent home-dir path literals:contract.md(sanitized ine715358e) and the byte-exact upstreamreferences/supported-harnesses.md(held as vendored; its refusal stands until upstream changes the text). The test adaptation is a proposal awaiting maintainer acceptance (see "Proposed adaptation" below).Byte-exact vendor — git blob SHAs vs upstream tree @
b811c24365aeassets/pierre-diffs.js1ecc2c99…a25400538a97c2b21a2a172dassets/warp-pixel-icon.svg0ed8d084…7aeb0e46ec53references/skill-improvements.mdbbf1dace…f1661d4freferences/supported-harnesses.mde8f589b7…316e37ec50scorers/code-quality.md59179f8d…535c5afb6c5b14c37ascorers/efficiency.md28648134…019a8284bbe9a04scripts/collect_sessions.pyf24fb541…2aa335835053scripts/render_report.py972da3be…4c4ed5a2ab6fscripts/test_collect_sessions.pyf659ac6e…b4ce4244dscripts/test_render_report.py46658d0f…5153dcb6c3c30204scripts/warp_decoder.pyc54cebdd…269e0aac11c5498b1fLICENSE00bd0da9…4ba8565fc(upstream repo-root MIT)Upstream's own
SKILL.md(9fd7d77d…f598d) is deliberately not vendored — per conventions §1/§2 the landing authors a fabrika routing surface instead. Full SHAs inPROVENANCE.md.Fabrika-authored (editable per
PROVENANCE.md)SKILL.md— routing surface, user-invoked (containment-exempt: maintainer-by-hand), §4 plain-literal commands (the POSIXmktemprecipe does not survive), states the inert-on-arrival contract: zero sessions expected until opencode collector: skill-doctor reads phoenix's real session history #8049 (opencode collector),--skills-dirrequired until skill-doctor discovers fabrika's skills corpus with no flag #8051.contract.md— collector flags, scoring contract, report artifacts; each sectionwire doc-section-addressable (verified).PROVENANCE.md— the byte-exact/editable split and the re-copy re-sync rule.CI — replacement verified locally; PR CI pending
The workflow now runs two separate test targets; the job fails if either fails. No skips, no failure allowlists, no continue-on-error, no output parsing.
SKILL.md, downloaded from the pinned commitb811c24365ae505bfc9646458957b886e29110b5and hash-verified (9fd7d77d…) before use. The shipped fabrikaSKILL.mdnever enters that tree. Verified locally: 14/14 + 11/11 green, including the three SKILL.md-coupled packaging tests, against upstream's own artifact.scripts/test_fabrika_conformance.py(fabrika-authored, PROVENANCE-listed) runs 13 doc-level tests over the shippedSKILL.md/contract.md: session scoping, the scoring contract with label-to-score mappings and aggregation weights, the failed-conversation threshold and edit gate, section addressability, documented collector/discovery limitations, and §4 plain-literal commands. Verified locally: 13/13 green. Doc-level only — it proves the contracts exist where the skill reads them, not runtime behavior.Failure propagation demonstrated locally: a deliberately broken collector fails the step before the renderer runs (renderer verified passing standalone in the same broken tree); wrong pinned SHA, download 404, and a conformance file planted in the baseline tree each fail their guards.
guard skill-lint: verified by CIThe gate fails closed with zero-scope on the filer's Windows machine — the identical red reproduces on untouched
main, so it is a local walker limitation, not this diff. Manual gate-1/3/4 greps over the new directory are clean; frontmatter hand-verified. The authoritative run on ubuntu (this PR's CI, 2026-09-06) passed..gitignoreRows for the skill's
results/directory (transcripts + rendered report embed transcript-derived content and machine-local paths — never committed) and for__pycache__/(Python enters the repo with this child).Proposed adaptation — awaiting maintainer acceptance
The two-target design above is the proposed adaptation, landed in commit
70dad2a8for review: upstream's packaging assertions run against upstream's own artifact (baseline target), while fabrika-authored conformance tests check the replacement surface (target 2). Acceptance is the maintainer's call: if accepted, the baseline target supersedes running the three upstream packaging assertions against the replacedSKILL.mdin place; if rejected, the alternatives (upstream path-parameter patch, or vendoring upstream's startup/branding copy into the fabrika body) come back into scope.Repair round 1 — portability
The branch is now merged up to date with
main(it was 417 commits behind, so the guards that landed since never ran on it). The fabrika-authoredSKILL.md,contract.mdandPROVENANCE.mdno longer carry any ticket number, issue URL or declared repo name; the gaps they used to name by ticket are named by what is missing instead.scripts/test_fabrika_conformance.pymoved with them: the two assertions that pinned removed ticket numbers now pin that prose. Local verdicts at53e142c3:guard portability-guard checkclean (1449 files),guard skill-lint checkclean (95 files),build check --surface prose|code|workflowsgreen, conformance 13/13, upstream baseline 14/14 + 11/11 in an isolated tree, and all 11 vendored blob SHAs plusLICENSEre-verified againstwarpdotdev/common-skills@b811c243through the upstream tree API.Deviations
assets/pierre-diffs.jskeeps 138 matches and is carried as oneexemptrow inportability-guard.config.jsonnaming that exact file. Why: every match is a CSS hex colour on the minified line, and the file is byte-exact upstream under the re-copy-never-edit rule, so it cannot be edited here. Disposition: stated here, and the row states the same reason in itswhy.references/supported-harnesses.md, in both halves of that policy (DOC_SELF_EXEMPTinpackages/fabrika-cli/src/guard/leak.tsanddocLeakExemptin.fabrika.jsonc). Why: that file documents where each harness keeps its session history, so the home-dir literal is its subject matter; merging currentmainbrings the file into the leak gate's scope, and editing it is forbidden. Disposition: stated here;leak.golden.test.tsholds the two halves equal and passes.SKILL.mdin an isolated baseline tree, not against the fabrika-authoredSKILL.mdthat replaces it. Why: three of upstream's assertions read its own packaging copy, which conventions §1/§2 require this skill to replace; running them against the replacement would assert prose the skill deliberately does not carry. Disposition: stated here; the replacement contracts are covered by the fabrika conformance target instead.scripts/test_fabrika_conformance.pythat hard-pinned the removed ticket numbers. Why: the docs no longer carry those numbers, so the assertions would red target 2 of the workflow. Disposition: the assertions now pin the portable prose that replaced them; 13/13 green.