Repository navigation
fix(adapters): reconcile quoted tasks-axi fields and record CP-08 acceptance - #15
Merged
Merged
Conversation
added 10 commits
October 6, 2026 19:50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Complete Factory CP-08 end to end after CP-07 merged at 9ba7ded, according to the original PROJECT.md, ARCHITECTURE.md, COMPLETION.md, BUILD_PLAN.md CP-08, docs/CONTRACTS.md, docs/INTEGRATIONS.md and docs/WORKFLOW.md without weakening frozen contracts. Prove one nontrivial localhost-only read-later application begun in a previously unused empty separate Git repository from the exact archived brief, with Pi-authored product truth, architecture, decisions, completion oracle and two-slice DAG frozen in first oracle commit 5fadae52 before implementation. Preserve the original brief and oracle digests. The app must provide separate DUMMY accounts, ownership derived from authenticated principals rather than client owner input, persistence across restart, list/search by URL/title/notes, own-item edit/delete, usable UI and reproducible setup; negative channels must conceal foreign items and preserve state. It must be delivered as at least two genuine Firstmate-owned vertical slices with guarded local-only landings, no public remote/deployment/real credentials, and exact release 5281646d81ebabaee2f93d14cec3da46b703838b.
Satisfy and honestly evidence every original V0 gate F-01 through F-09 and V1 P-01 through P-08, not merely unit/CI or closed tasks. Preserve independent completion behavior: failed, changed-contract and changed-release evidence cannot pass; when all tasks are closed a failed project check remains NOT COMPLETE and repair/retest is observed. Prove reviewed tasks-axi 0.2.5 dry-run/apply/idempotence, dependency holding and interrupted-publication recovery only in disposable fixtures or the authorized reviewed operation, with named-home hashes unchanged for read-only operations. Preserve CTX provenance and the initial strict 30k PARTIAL results versus later 45k STRICT_AGENT/HYBRID_SEMANTIC COMPLETE results; do not relabel CP-06 STANDARD ten-pack evidence as strict. Preserve CP-06 DUMMY/no-range/read-only security controls and CP-07 current-Pi command, reload and CLI parity without real credential attacks. Keep Linux Node verification, Windows Chrome loopback browser verification, and native Windows Node/macOS limitations explicit.
The real app passed RL-001 through RL-005 plus exact-PID kill/restart, clean-clone, account-isolation and browser proofs. The captain's genuine scoped human UI disposition was exactly “yes it looks okay , very simple ask claude to test it out”; record only that the UI looked okay and simple, not that the captain personally ran every workflow. The separately requested Claude Opus 5.5 exact-release test passed seven stable commands and functional/isolation/restart journeys with no accepted defect. Preserve its limits: native AXI confirm-dialog dismissal hung twice, so cancel/delete logic used an explicit window.confirm stub rather than native OK/Cancel clicks; terse errors are optional low-severity UX polish; possible search response ordering was code-reading only and not reproduced; no native Windows server, macOS, screen-reader, load or concurrency claim.
Implement only the smallest Factory fixes exposed by this greenfield exercise: tasks-axi quoted scalar reconciliation, replayable immutable-oracle validation, replayable closed-task/failed-project/stale-evidence status negatives, and a precise CP-08 evidence ledger/sanitized release receipt. Generated runtime evidence stays ignored; application source stays in its separate registered repository. Do not add a scheduler, model router, autonomous/background controller, worktree manager, shipping gate, deployment, global authentication change or tool update. Factory validates and packages; Pi reasons; Firstmate dispatches and alone merges. Preserve prior checkpoint commits/copies and all failed evidence as failures. Produce one normal no-mistakes PR with final-head review/tests/docs/lint and green exact-head CI; never merge it from this worker.
What Changed
src/adapters/tasks-axi.tsnow decodes every JSON-quoted scalar returned bytasks-axi show(title, state, kind, repo, blocked_by, held, as well as body). Before this, only the body was decoded, so a title with punctuation could stop a re-run of--applyfrom reconciling the task. If a quoted value fails to parse or is not a string, the adapter now raisesTASKS_AXI_OUTPUT_INVALID. A new installed-tasks-axi test intest/sync.test.tschecks that a title with commas is created once and stays unchanged on retry, with the backlog hash unchanged.npm run proof:cp08:oracleandnpm run proof:cp08:status, plus tests for each:NOT COMPLETEand stale results where expected, and checks that the backlog is unchanged. It refuses to write output outside ignored.factory/state, including when the state root does not exist yet.docs/probes/CP-08.md) and a sanitized release receipt (docs/probes/CP-08-release.json) for the greenfield read-later app (oracle5fadae52, release5281646d). It marks the CP-08 checklist complete inBUILD_PLAN.mdand updates the README status to point to the ledger and its platform limits; the README document-authority table is also re-aligned.Risk Assessment
✅ Low: The fix round fixes both findings the user chose to fix, and the changes are narrow. The new
canonicalPathfalls back to the canonicalized nearest existing ancestor only on ENOENT, so a missing.factory/statenow yields OUTPUT_OUTSIDE_STATE rather than INTERNAL_ERROR. A dangling symlink still cannot make a write escape state, because the later non-recursive mkdir fails. The stale pre-completion sentence was removed from the CP-08 ledger.Testing
I ran the CP-08 proof tests on their own on a clean tree, compared the old and new state guard on the same fixture, and showed the new tasks-axi quoted-title test fails before the fix and passes after it. I replayed the real oracle and status-negative proofs against the registered app at release 5281646 using only read-only checks, and confirmed the named home and the subject repo were unchanged. A clean clone of the app passed all seven of its checks. Transcripts and status JSON are saved in the evidence directory. Everything passed and no defects were found. There is no UI change in this Factory diff, so no screenshots were taken; the app's browser evidence comes from the recorded receipts.
Evidence: Status guard before/after fix with .factory/state absent
pre-fix: {"status":"fail","error":{"code":"INTERNAL_ERROR","message":"ENOENT ... realpath '.../.factory/state'"}} exit=1 fixed: {"status":"fail","error":{"code":"OUTPUT_OUTSIDE_STATE","message":"output must be a new path under .factory/state"}} exit=1Evidence: CP08 proof tests run alone on a clean tree
Evidence: tasks-axi 0.2.5 sync tests including quoted-title reconciliation
Evidence: Real oracle replay at release 5281646 (frozen digests, subject unchanged)
Evidence: Changed-release oracle negative (RELEASE_HEAD_MISMATCH)
Evidence: Real status negatives proof with named-home hashes
Evidence: Status negatives verdict summary
baseline product=COMPLETE | RL-001..RL-006 passed failed-project-check product=NOT COMPLETE | RL-002:failed, others passed repaired-retest product=COMPLETE | RL-001..RL-006 passed stale-release-head product=NOT COMPLETE | RL-001..RL-006 stale stale-contract product=NOT COMPLETE | RL-001..RL-006 stale/home/ansh/.treehouse/Factory-86709f/9/Factory/.factory/state/cp08/no-mistakes/n/evidence/01M4B78HQ1WBJ0DMXY6M7W97QB/status-negatives)Evidence: App clean-clone stable checks at release 5281646
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed ✅
scripts/cp08-status-proof.mjs:275- The round-1 fix the user chose is still not in the target commit.main()still callsrealpath(stateRoot)(<factoryRoot>/.factory/state) before the output-location guard. That directory is gitignored and is absent in this worktree, as in any fresh clone. When it is missing,realpaththrows ENOENT and the script exits withINTERNAL_ERROR, notOUTPUT_OUTSIDE_STATE. Sotest/cp08-status-proof.test.mjs"refuses output outside ignored Factory state" passes only when an earlier test file in the same run has already created.factory/state. It is order-dependent and fails when run alone on a clean clone. Fix: whenrealpath(stateRoot)throws ENOENT, fall back to the resolved non-realpath state root for the prefix comparison, so the guard no longer depends on the directory existing.docs/probes/CP-08.md:250- The round-1 fix the user chose is still not in the target commit. The Limits section still ends with "The final section must record exact release SHA, commands, exits, artifact hashes, dates, reviewers, intervention counts, task/merge refs, and residual risk before the remaining checkpoint checkboxes change." The same change ticks every CP-08 checkbox in BUILD_PLAN.md and adds the prevalidation and acceptance sections, so this pre-completion instruction now contradicts the ledger. Remove it or reword it as a historical note.🔧 Fix: Fix CP08 state guard for missing state root
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
npm ci && npm run build(test toolchain only; node_modules, dist and .factory/state removed afterwards)node --experimental-import-meta-resolve --test test/cp08-status-proof.test.mjs test/cp08-oracle-proof.test.mjsrun alone with.factory/stateabsent (clean-clone condition for review-1)Before/after comparison: pre-fixscripts/cp08-status-proof.mjsfrom 3dca129 vs fixed script on the same fixture with.factory/stateabsent (INTERNAL_ERROR ENOENT → OUTPUT_OUTSIDE_STATE)node --experimental-import-meta-resolve --test dist/test/sync.test.jsagainst installed tasks-axi 0.2.5 (16 tests, none skipped)Regression reproduction:--test-name-pattern="quoted scalar"with base 9ba7dedsrc/adapters/tasks-axi.ts(fails PARTIAL_SYNC), then restored the fixed adapternode scripts/cp08-oracle-proof.mjs --subject <registered FactoryReadLaterAcceptance> --oracle 5fadae52… --release 5281646d… --reviewer …(pass; subject HEAD/status/refs digest unchanged)Changed-release negative:cp08-oracle-proof.mjs --release 0fee6e2…against the real subject (RELEASE_HEAD_MISMATCH, exit 1)node scripts/cp08-status-proof.mjs --subject <registered app> --evidence-source <retained slice-2 worker copy> --home <named Firstmate home> --release 5281646d… --output .factory/state/nm-test-status --reviewer …(pass; independent backlog.md and data/ tree hashes unchanged)Parsed the generated status reports: baseline, failed-project-check, repaired-retest, stale-release-head and stale-contract product/condition/task statesClean temp clone of the registered app at 5281646:npm ciplusnpm run test-unit|test-integration|e2e-save-list-persist|e2e-account-isolation|e2e-search-edit-delete|e2e-interruption-recovery|release-setupChecked the ledger Limits section for review-2: the stale pre-completion sentence was removed in 786a7b6✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.