refactor(engine): premise-witness drift + single-resolution prompt cascade + per-unit worktrees + studio trim - #372
Conversation
|
Claude finished @jwaldrip's task in 5m 2s —— View job PR Review: refactor(drift): premise-witness modelTodo
Overall AssessmentThe design inversion is correct and well-argued. Witnessing premises (unit body + declared inputs) instead of deliverables (outputs) eliminates the class of permanent drift loops caused by normal output evolution, and the implementation is consistent about sign-time/check-time alignment. The Five inline issues filed, ranging from a real correctness concern to documentation cleanup. Issues (inline comments posted)Medium —
Medium —
Low — The sweep's explicit extension check for direct file inputs only covers Low — Stale comment in The newly added comment says approvals witness output paths "(legacy — to be dropped in Phase 6)" but Phase 6 is done — Nit —
Design Notes (non-blocking)
Test Coverage AssessmentThe existing test rewrites are solid — converting the old "output mutation fires drift" positive tests to negative regression guards is exactly right for the new model. The Noted gaps from the PR itself: Phase 9 input-drift tests (addition/deletion/dir-inventory mismatch, cosmetic-close re-stamp, material-close re-sign, migration backfill) are still TODO. The skip annotation on |
|
Claude finished @jwaldrip's task in 7m 39s —— View job PR Review: refactor(drift): premise-witness modelTodo
SummaryThe conceptual reframe here is correct and well-executed. The old model was witnessing outputs (things downstream of the decision), which caused the permanent drift loops you were seeing on The code is generally clean. A few specific issues found: Bug 1 (fragile): Input file hashing diverges at check-time —
|
|
Claude finished @jwaldrip's task in 4m 45s —— View job PR Re-Review: refactor(drift): premise-witness modelTodo
Status: Same 5 commits as prior review — no new code landedAll issues from the previous inline review remain open. Repeating them here for completeness, with updated notes from deeper analysis. Confirmed Open IssuesMedium — Sign-time and check-time are consistent with each other today (both use Medium — The skip-list is copy-pasted with a "must stay in sync" comment. The comment names the failure mode correctly (sign-time and check-time would disagree on inventory, causing spurious Low — Stale comment in // Reviews witness the unit body + input premises; approvals
// witness the declared output paths (legacy — to be dropped
// in Phase 6 of the drift cleanup).Phase 6 is done. Low —
details.units_migrated = outcome.units_migrated
details.drift_artifacts_deleted = outcome.drift_artifacts_deleted
// review_slots_backfilled and approval_slots_stripped disappear hereThe banner shown to users after migration gives no signal about how many witness blocks were backfilled or stripped — useful for auditing a production upgrade. Add the two fields to Low — Partial extension check at const currentSha =
ext === ".md" || ext === ".markdown" || ext === ".mdx"
? bodySha256(abs)
: outputSha256(abs)The explicit list covers only Nit —
New Observation (not in prior review)
The change in Design Notes
intent-scope approval asymmetry is intentional: unit approvals use Overall VerdictThe design inversion is correct and the implementation is internally consistent. The |
|
Claude finished @jwaldrip's task in 6m 13s —— View job PR Re-Review: refactor(drift): premise-witness modelTodo
Phase 8 Commits (new since last review) — cleanTwo new commits since the prior review pass:
Prior Issues: Not Yet AddressedNone of the issues raised in the two previous review passes were resolved in the new commits. Re-filing the unresolved ones: Bug (medium) — The review re-stamp in Medium —
Low — stale comment in Still references "legacy — to be dropped in Phase 6 of the drift cleanup." Phase 6 is done: Low — partial extension list in The manual Low —
Low — no dedicated v8→v9 migration unit test
Everything Else Remains Good
|
|
Claude finished @jwaldrip's task in 2m 26s —— View job PR Re-Review: refactor(drift): premise-witness modelTodo
New Commit:
|
Followup to the 21-stage verifier sweep. The prior commit added the
missing hats but inherited verbose "Hat X does Y..." per-unit baton
prose that duplicates each hat mandate's own Focus line. Compressed
16 STAGE.md files' Per-unit baton sections to artifact-handoff form
only: `hatA → hatB: artifact name`.
Rationale: STAGE.md body IS loaded into the elaborate-phase prompt
(packages/haiku/src/orchestrator/prompts/stage/elaborate/decompose/index.ts:249),
so the section isn't dead weight — but it should describe ONLY what
flows between hats, not what each hat does. The hat's own mandate
file is the source of truth for the hat's role.
Affected: compliance/assess, data-pipeline/{extraction,validation},
documentation/{draft,outline}, finance/analysis, hr/screening,
hwdev/firmware, incident-response/resolve, legal/intake,
libdev/security, marketing/strategy, migration/{assessment,mapping},
quality-assurance/certify, sales/negotiation.
Net change: -62 lines across 16 STAGE.md files (49 inserted, 111
removed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Continuing audit finding #18. Trimmed the RFC-2119 anti-pattern walls on 4 more heavy hats — each from 10-12 bullets down to 4-5, dropping items that: - duplicate engine contracts (placeholder bans, FM access rules enforced by the PreToolUse hook, naming conventions in the shared workflow-contracts-elaborate block) - restate process-section content positively rather than catching a non-obvious failure mode - repeat the same rule across two bullets Affected hats: - software/inception/hats/researcher.md — 12 → 5 - software/development/hats/reviewer.md — 10 → 4 - software/product/hats/specification.md — 10 → 5 - software/design/hats/design-reviewer.md — 11 → 5 Security-family hats (red-team, blue-team, threat-modeler, security-reviewer, security-engineer) left untouched — security work has real failure-mode density and benefits from explicit anti-patterns. Other heavy hats (hr/interview/evaluator, training/evaluate/analyst, qa/execute-tests/tester, etc.) deferred to the reflection loop when it eventually fires. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ft + merge-state hardening Session checkpoint on the drift-cleanup/witness-model branch. The headline is HTML-artifact rendering, plus a batch of engine and UX hardening fixes. Wireframe / HTML-artifact rendering (StageReview + haiku_view): - Inline adjacent stylesheets into HTML artifacts at parse + serve time so a wireframe authored as index.html + styles.css styles correctly in the srcDoc iframe (no base URL). New shared html-inline.ts backs both parser.ts (SPA wire payload) and the file-serve layer (serveArtifact in path-safety.ts), keeping the FB-21 octet-stream/attachment headers so HTML is never a renderable text/html under the tunnel origin. - haiku_view's ViewPage renders HTML via a fetched, sandboxed srcDoc (HtmlRenderer) instead of a raw octet-stream URL. - Resolve embedded relative refs (<img src>, srcset, CSS url()) to authed /stage-artifacts/<sid>/...?t=<jwt> tunnel URLs (resolveEmbeddedAssetUrls, DOM-based) so raster images load inside the srcDoc on both surfaces; inlined-CSS url() is re-based onto the HTML's dir server-side. .js/.css/ .svg/font sub-resources stay octet-stream-blocked. Fix-hat / hat relays: - reject_hat bounces to the prior hat (fresh iteration) carrying the rejection note, for both unit and feedback hats, so the next bolt doesn't pick a different implementation. - Relay breadcrumbs only re-dispatch the calling unit's chain; cross-unit completions fall through to run_next. - Software intent-scope fix_hats lead with an implementer (builder). Drift + merge state: - Skip input_mutation drift when the witnessed file is itself stage-produced (input==output baton exemption). - Suspend write guardrails (Claude + internal MCP tools) while a merge is in progress; internal tools keep schema validation. Quality gates / state tools: - Re-expose haiku_unit_get (single agent-authorable field read; refuses FSM-driven fields) so a gate-command fix is read -> modify-one -> write-back. - quality_gates + outputs stay writeable after a unit goes active (corrective exemption). Statusline: drive progress from granular cursor-action milestones (deriveProgressTrack); completed phases render filled, spec review is PRE-execute. Test infra: bump the e2e-* per-file budget in run-all.mjs from 180s to 300s — e2e-mode-coverage legitimately runs ~141s via npx tsx and was flaking right at the edge. Docs: sync CLAUDE.md / ARCHITECTURE.md for the above; skills renamed to the haiku- prefix; rebuilt SPA + MCP bundle. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…g the breadcrumb The per-unit-hat subagent's closure now has two parts: one concrete line on what it built/changed/verified (the only place it summarizes — what the parent surfaces so users see real progress instead of silent spawns), then the tool's plain-text return VERBATIM (pool snapshot + relay breadcrumb). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…tion, redundant with haiku_intent_list haiku_dashboard labeled a static "first declared stage" guess as "(cursor-derived)" and still read v3 stages/<stage>/state.json, which v4 dropped. haiku_intent_list already derives status + active_stage correctly via findCurrentStage, so the tool was both wrong and redundant. Removed the tool def + handler, the skill, the generated Gemini/OpenCode mirrors, and every sync-surface reference (cli-reference docs, paper operational-commands list, architecture-map tool surface). Repointed the haiku:status session-resume prompt to haiku_intent_list. Rebuilt the bundle. Skill-tools-smoke, prompts-registered, and skill-list suites green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ard removal The 'one-pr-per-stage' post had a section built around haiku_dashboard aggregating state across stage branches — doubly stale after bc52589 deleted the tool and v4 dropped the state.json it read. Rewrote it as 'How status crosses branches': the cross-branch-without-checkout point still holds (readFileFromBranch backs the repair + browse reads), minus the dead tool name and the state.json mechanism. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 6m 28s —— View job PR Re-Review: refactor(drift): premise-witness modelTodo
New Since Last ReviewSix commits landed since New Feature: Input==Output Baton Exemption (
|
The zap skill hand-taught 207 lines of hat-loop orchestration — studio/ stage resolution, the subagent prompt template, per-role instructions, PASS/FAIL verdict parsing, the retry cap, commit-only-on-PASS. All of it now computes from the real studio/stage/hat structures inside a new stateless haiku_zap tool and comes back as the returned instruction message. The skill collapses to a ~12-line redirect: call the tool, handle the pick-error, follow the message. Aligns zap with "skills are thin redirects; tools return dynamic instructions" and no-agent-mechanics-teaching. zap stays stateless — no .haiku/ writes, no tick. The tool resolves + reads + assembles; the agent still drives the sequential loop. Tests: zap-tool (5), skill-list (13), skill-tools-smoke (10), server-tools (69), state-tools-handlers (127) all green. Bundle (plugin/bin/haiku.mjs) intentionally NOT included — a concurrent in-tree refactor would contaminate a rebuild; it regenerates cleanly on the next full build once that work lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 7m 5s —— View job Pass 67 — No Issues · Ready to MergeTrigger: CI: 2 runs in progress (Claude Code Review + CI). New commits reviewed
Commit notes
Outstanding prior itemThe dead Overall: 67 passes, no open issues. The PR is clean and ready to merge. |
… no longer 404s
Two reported bugs on the StageReview Outputs detail view, both in paths I
under-verified earlier:
1. A unit-declared repo-root output (e.g. `web/apps/admin/.../WorkerDates.tsx`)
rendered as a blank box. The output IS the codebase file the unit edited —
it lives at the REPO ROOT, not under `.haiku/intents/<slug>/`. The parser
only resolved against the intent dir, so `buildArtifactEntry` couldn't
read it, returned a contentless "file" stub, and `ArtifactBody`'s tail
`<pre>{body}</pre>` rendered nothing.
- parser.ts: `parseUnitOutputs` now falls back to the REPO ROOT (the dir
containing `.haiku/`, located via the `/.haiku/` segment) when the
declared output isn't under the intent dir. Existing repo file → content
inlined + classified `code` + language; missing in both → "file" stub
surfaces for the SPA's "not on disk" note. Truly-unsafe paths (outside
intent AND outside repo) still skip.
- StageReview ArtifactBody now handles empty content gracefully (a clear
"not on disk" note + open link) instead of a blank `<pre>` — never an
empty box, even for missing outputs.
2. Clicking an item in a dynamic per-directory tab ("Proof", etc.) returned
route-level "Not Found." The `$kind/$name` route validated `kind` against
the fixed ReviewDetailKind union; dir tabs use the dir name. Widened
`isKind` to accept a safe slug (mirrors the `$tab.tsx` fix from 0e019fd).
Verified end-to-end:
- parse-output-artifacts 30/30 (+2 tests: repo-root resolves + inlines `tsx`
content; missing repo path surfaces as a "file" stub).
- haiku-ui 572/572 (+3 tests: code output renders highlighted in the
StageReview Outputs detail; empty output shows the "not on disk" note;
dir-tab detail renders, no 404).
- Booted the SPA in a real browser against the exact reported path: code
rendered (630 chars, 42 hljs token spans, 8 distinct colors), JSX preserved
as escaped text, source comments + imports visible, no "not on disk"
fallback shown — the empty box is gone.
- tsc + biome clean; bundle rebuilt (857KB gz, under budget).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 3m 3s —— View job Pass 68 — Review SPA output rendering + dir-tab 404 fixNew since Pass 67 ( What changedTwo targeted bug fixes in the Review SPA's detail view, neither touching the core drift/witness/migration machinery.
The The fix derives One detail worth noting: the mutation
The route's
Test coverage
Both suites pass. tsc and biome clean. Bundle 857 KB gz (147 KB under the 1 MB cap). Assessment: no blockers. PR is ready to merge. Prior passes found and fixed all substantive issues (drift-witness model, migration chain, deadlock detector, within-wave refill, optional-stage routing, non_actionable lifecycle guards, restamp audit timestamp preservation, |
…v9→v10 - Format elaborate_loop/index.ts + state-tools.ts (the only two files `npx biome check packages/haiku/src` flagged — CI's exact scope). - v9-to-v10 migrator: the `allow` set inside the `!hasStages` branch tested the exact condition we already know is false, so it was always null and the intersection never fired. Simplify to studioStages minus skip_stages and fix the misleading comment. Addresses PR review thread. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 4m 3s —— View job Claude Code Review — Pass 69Head: What this PR doesA large-scope refactor across the workflow engine, SPA review UI, and migration layer:
CorrectnessDrift model (
Hat sequence migration (
Session never-attached suppression ( Schema parity ( v9→v10 dead Parser repo-root fallback ( Dir-tab Deadlock detector Churn window — wait-for-human actions (user gate, etc.) no longer accumulate in the churn window, preventing the false "progress stalled" halt on the next real progress tick. SecurityNo new attack surfaces introduced. The repo-root fallback in PerformancePer-unit worktree isolation adds process overhead for worktree create/destroy but eliminates the serialization bottleneck from shared-worktree dirty-state collisions. Net win for multi-unit waves. The Design/ArchitectureThe premise-witness model is the right call. Witnessing outputs conflated "what did this unit declare it would produce" with "has anything changed in the codebase." The new model cleanly separates intent-plan stability (premises) from artifact mutation (not drift-relevant). The The The The schema parity guard ( CI (as of this review)
No regressions introduced in the last two commits ( VerdictApprove — merge when CI green. The premise-witness drift model is a foundational correctness fix. The supporting changes (worktree isolation, |
…and intent closeout
A unit could declare an output (e.g. `WorkerDates.test.ts`) that never
existed on disk — the real file shipped as `.test.tsx` — and the intent
reached closeout with no gate catching it. The SPA surfaced the phantom
("declared output isn't on disk") but nothing blocked. Two root causes:
1. The per-unit terminal-hat existence check validated outputs ONCE, at
completion. A later unit / fix-loop / merge that renamed or deleted a
file left a stale declaration no gate re-checked.
2. A whole family of intent-level validators (validateOutputLiveness,
validateCumulativeInputCoverage, validateStageOutputs, validateUnitInputs,
validateUnitNaming, validateDiscoveryArtifacts) has been DEAD since the
v4 refactor — defined, unit-tested, re-exported, even backed by error-
prompt builders + the haiku_coverage_acknowledge tool, but never wired
into the cursor.
Fix (no rewind, no repair tool, no breaking in-flight intents):
- `repairDeclaredOutput` (state-tools): intelligent near-miss repair — a
same-stem sibling differing only in the final extension is the corrected
path (`.test.ts` → `.test.tsx`, `.ts` → `.tsx`). Ambiguous or absent → null.
- Terminal-hat completion gate: attempt repair before blocking. An extension
typo self-corrects in the unit's `outputs:`; genuinely-absent outputs still
block (the agent claimed an artifact it never produced).
- Intent-closeout sweep (`validate-output-existence-gate`, wired pre-tick in
run-tick when findCurrentStage === null): re-validate every unit's declared
outputs, auto-repair near-misses in place, file a deduplicated `high` FB for
the rest so the fix loop corrects the path or produces the file. Gated on
closeout so it never flags an in-flight unit's not-yet-written output.
Existing intents self-heal on their next closeout tick — no migration script.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 8m 26s —— View job PR #372 Review — Pass 70PR: refactor(engine): premise-witness drift + single-resolution prompt cascade + per-unit worktrees + studio trim New commit since pass 69:
|
…y optional Reshapes the software studio's optionality around the MVP of a full feature. The mandatory core is now inception (research/framing) + product (spec) + development (build) — the minimum any feature needs. design, operations, and security are optional, dropped per intent when they don't apply. Removed the `release` stage entirely (it was ported from libdev in the earlier collapse). product loses `optional: true` (now mandatory); security gains it (now optional). Studio stage list is back to six: [inception, design, product, development, operations, security]. Tests + CLAUDE.md row + software workflow diagram updated to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Viewing a non-active stage with nothing pending puts the gate in
"disabled" mode. The old hint — "Type a comment above or click into
another stage" — is wrong in the docked-rail layout (composer={false}):
the composer isn't "above", it lives in the slide-out feedback panel
(reported on a previous-stage view). The new copy is composer-aware:
- composer present (desktop sidebar): "Type a comment above…"
- composer absent (docked rail): "Open the feedback panel…"
Both now state that only the ACTIVE stage can be approved, instead of the
vague "click into another stage" (a non-active stage can be earlier OR
upcoming — the old copy implied it was approvable).
gate-decision-hint.test.tsx renders the bar in disabled mode for both
composer values and asserts the exact copy.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 5m 55s —— View job PR #372 Review — Pass 70Two new commits since the last review pass (
|
Audited every studio for which stages are the mandatory core (the minimum any intent in that domain needs to produce its deliverable) vs optional (a meaningful subset of intents legitimately skips). Marked 47 stages optional: true across 22 studios. Marking a stage optional only ENABLES the keep-or-drop offer the cursor presents on first arrival — it never auto-drops, so this is additive and conservative (worst case: one extra prompt the user answers "keep"). Mandatory cores preserved per domain — verification-centric studios (QA, migration) keep deep cores with only the terminal stage optional; tight analytical arcs (executive-strategy, ideation) get a single optional. libdev (deprecated) untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…odel' into optstages-work2
|
Claude finished @jwaldrip's task in 5m 42s —— View job Claude Code Review — Pass 71Triggered by: New commits reviewed this pass
One open issue (carried from Pass 70, still unaddressed)
When the fix loop closes a missing-output FB as Inline comment filed with a one-line fix and a suggested test case. The test suite in Pass 71 findings per commit
Cumulative status (71 passes)All prior issues resolved except the Everything else across the premise-witness drift rewrite, per-unit worktree isolation, single prompt-resolution path, optional stages ( |
…later-complete) The detail view derives each stage's status independently from its own units, so an advanced stage whose unit FM lacks the full review/approval stamp set the browse heuristic expects reads as "active" — while a later, fully-stamped stage reads "complete". Result: the pipeline showed Operations active while Security (after it) was green (worker-new-badge), and the active-stage marker sat on a stage the engine had already moved past. Add normalizeStageProgression: a sequential pipeline can't have completed a later stage without finishing earlier ones, so completion propagates backward. All three providers normalize the per-stage status map before deriving the active stage and write the corrected status back onto each stage, so the dots are monotonic (complete* · active? · pending*). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dings; don't mutate gray-matter's cached parse Two issues caught by PR review on the output-existence gate: 1. non_actionable dedup leak (infinite loop): a missing-output FB closed as `non_actionable` (fix loop accepted the output as intentionally absent) sets `closed_at`, so the dedup `continue`d past it without recording the ref → next closeout tick re-filed → fix loop re-closes non_actionable → forever. Now `non_actionable` closures stay in `openRefs` (suppress re-file); only `closed` (fixed) and `rejected` (invalid) allow a re-file. 2. gray-matter shared-cache mutation: the gate (and the terminal-hat repair in state-tools) did `parsed.data.outputs = corrected` then re-stringified. gray-matter caches parse results by content and returns a SHARED object, so mutating it corrupts every byte-identical unit's next parse (two skeleton units would swap outputs). Both sites now build a fresh data object via spread. This surfaced as cross-test contamination; it's a real (if rare) production hazard. Tests: output-existence-repair.test.mjs gains the non_actionable-suppresses- re-file case + per-test unique slugs (the suite shares one process). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ate hint The GateDecisionBar hint-copy change (a5596fd) updated the source but not the inlined SPA blob the MCP serves. Regenerate via bundle-haiku-ui.mjs so the shipped micro-app shows the new disabled-mode copy (+38 bytes gzipped). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…odel' into refactor/drift-cleanup-witness-model
|
Claude finished @jwaldrip's task in 5m 38s —— View job Pass 71 — reviewing commits since New commits
Open issue from Pass 70: CLOSED
The same commit also fixes a second bug I hadn't caught: gray-matter shared-cache mutation in both
|
resolveUnitHats appended feedback-assessor as a terminal hat to any unit declaring `closes:`. But in v4 a unit's `closes:` is an informational breadcrumb only — it does NOT close the FB (closure is stamped on the FB by the fix loop's feedback-assessor via haiku_feedback_advance_hat). So the injection put a FIX hat inside the unit's plan-do-verify loop for zero closure benefit, and left feedback-assessor iterations on units that confused status derivation. A unit runs exactly its stage's `hats:` now. reconcileOrphanedHatSequences (already wired pre-cursor) strips any stale feedback-assessor iteration from existing units, since it's no longer in the resolved sequence. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trust-checkpoint regression against a real repo + bare remote: 1. Reconciling with intent work ahead of mainline leaves mainline (local + origin) byte-identical — the engine authors no merge onto it. 2. When the delivery PR is merged EXTERNALLY (a human merges haiku/<slug>/main into mainline), the engine recognizes it as merged (isBranchMerged → true, the close signal) and on the next reconciliation still adds nothing to mainline — the tip stays the human's merge commit, never an engine-authored one. Verified the test has teeth: injecting an engine-side merge+push to mainline makes assertion (1) fail. Delivery stays open-PR-and-wait; the user's merge is the only close signal. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 4m 26s —— View job Claude Code Review — Pass 72CI is running; reviewing the two commits pushed since Pass 71.
|
…s for their kind Generalize the per-tick reconciler so an iteration's `hat` is valid only when it's (1) the right KIND of hat for the entity AND (2) resolves to a hat file in the cascade: - UNIT iterations → the stage's `hats:` rotation - STAGE feedback → the stage's `fix_hats:` - INTENT feedback → the studio's `fix_hats:` "Hats are for units; fix hats are for feedback/fix loops." A unit can no longer carry a fix hat (feedback-assessor) and a feedback item can't carry a unit-rotation hat — invalid entries are trimmed pre-cursor every tick, so the state self-heals. The file-existence half also strips a hat named in settings whose mandate file was removed (e.g. by a studio reshape). Previously this only reconciled units, only against list membership (no file check), and never touched feedback. Full suite green (2064). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 4m 1s —— View job Claude Review — Pass 73One new commit since Pass 72: CI: in progress at time of review.
|
…er lost worker-new-badge (2026-05-28): two intent-completion reviewers each allocated FB-003 — `nextFeedbackNumber` is local-max+1, and their creates raced an intent-main that was behind origin (a CI auto-fix commit). The non-fast-forward rebase recovery then kept BOTH files (`003-cross-stage-….md` + `003-runtime-….md`); same numeric prefix, different slug → `readFeedbackFiles` yields two items with id FB-003 and `findFeedbackFile` resolves only one. The shadowed one was a delivery-branch net-delete BLOCKER — nearly lost, re-filed by hand. New pre-tick gate `healDuplicateFeedbackIds`: within each feedback scope (intent root + every stage), files sharing a numeric prefix are reduced to one keeper (earliest-created — it owns the id other state may reference) and the rest renumbered to fresh ids, carrying their sidecar attachment + rewriting the body attachment URL. Runs before the cursor collects feedback so dispatch sees distinct ids. Idempotent, best-effort, never blocks the tick. This is the root of the report's Bug 2 (the same push contention produced the divergent stage-branch frontmatter); the octopus-merge driver is a separate follow-up. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…the final check) Bug 4 (worker-new-badge 2026-05-28): the intent-completion track emitted the terminal `user` gate BEFORE `intent_quality_gates` — the cursor's comment even said "fires after every agent + user review approval." A human approved completion before the automated bar (20 gate commands) had run; a gate failing at that point would have routed back to a fix loop AFTER the signature. Reorder the intent-level walk so the intent-scope quality gates dispatch right after the adversarial reviewers and BEFORE the terminal user gate — the human is "the final check before reflection," approving over a green bar, never ahead of it. New order: spec → adversarial reviewers → intent quality gates → user → reflection → seal. e2e-mode-coverage continuous test now asserts `lastIndexOf(dispatch_quality_gates) < lastIndexOf(intent_review)` (the intent-scope QG precedes the terminal user gate). All five modes still seal. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… intent.md conflict to the agent) Bug 2 (worker-new-badge 2026-05-28): `workflowIntentComplete` fans unmerged stage branches into intent main via `mergeStageBranchForward`, which did a PLAIN `git merge --no-ff` — unlike the unit / fix-chain / downstream-sync merges, it never re-asserted engine-owned frontmatter. When intent main and a stage branch carried divergent `intent.md` FM (different approval timestamps, the fallout of the parallel-stamping + push contention fixed in the FB-id heal commit), the merge conflicted on `intent.md` and returned `mid_merge_blocking_tick` — handing a workflow-managed, engine-sole-write file to the agent to hand-resolve. Route `mergeStageBranchForward` through `engineProtectedMergeInCwd`: after the merge, intent-root engine state is re-asserted from the TARGET (HEAD = intent main, authoritative for cross-stage approvals) while stage-only files still merge forward; only genuine conflicts on agent (non-engine) content surface. Red test stage-forward-merge-engine-fm.test.mjs: pre-fix the divergent intent.md spec-timestamp conflicts (isConflict + conflictFiles:[intent.md]); post-fix the merge is clean, main's user approval + spec timestamp win (target-authoritative), and the stage's unit file still merges forward. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 4m 28s —— View job Claude Code Review — Pass 74Reviewed 3 new commits (
|
What this is
This branch opened as the drift-model rewrite from
DRIFT-CLEANUP.md. It grew — twice. It's now a broad engine-hardening + simplification pass plus a full rebuild of the review surface. 216 non-merge commits, ~1,560 files, +67.8k / −34.7k. The drift rewrite is still the flagship, but it ships alongside a single prompt-resolution path, per-unit worktree isolation, a studio-definition trim, a stack of engine reliability fixes, and — newest — the review SPA redesign + a native micro-app window.The net deletion is still part of the headline:
plugin/studios/drops a wall of hat anti-pattern prose, redundant batons, and inlined prompt bodies as they move into a shared, overridable resolution path.Workstreams
f52cc445d5477c7cc0b47a76b2ead1f4ffd3ba5aba011c80988457haiku_read_*tool family (haiku_read_hat,haiku_read_stage, discovery/output/phase) + build-time snapshot. Every subagent dispatch resolves studio assets through one shared reader instead of carrying inlined mandates.autotune→reflectionrename; prompt bodies move toplugin/prompts/with a project-override cascade.9ce122421720692d9f5196a77349921200cae4f8dbb23b35153f50c8ad8a65ebe2025b33880725a74a2de2b9e5627e5eeccf112cbfeb6e3f6bf5eb764ec72fbd0a5e01965b878a6948d8c47ae5954939a47d8da52d762c37f7cbdelivery-verifier(waits on delivery-PR CI, files findings, reads/resolves review threads). Pre-tick clean-tree gate blocks the tick on uncommitted agent work outside.haiku/.bf7a439bfMAX_CONCURRENT_SUBAGENTS. Fix-loop hats pool at the same cap;target_unitdedup dropped.42b7f5b33d6f13a1905ad0f9dab0d0c551d7eb12803486a56b37d1bb692f4302cb1d7beab8f69b0fa57f120ffbe00333f99b7d6e5bc8a2001a9358026375db0ecf3213fab25005c48ae6aaa31haiku_dashboarddeleted (broken active-stage derivation, redundant withhaiku_intent_list).haiku-zapprose replaced with a realhaiku_zaptool.bc52589a026aa7aba125821303e5dcc7402595483c9bbf6c05031378e747b58fix_hats; non-owning fix hats advance, not reject.BRIEF.mdwrites to the repo stage dir, not global~/.haiku.24e618369d01bd695fed4bdf910ea8412d8dd74e27e991e5a867459c8e40481723c9ec3dc293b6d70settings.ymlcollapsed to studio + providers only (plugin/schemas/drops ~1k lines).7bff30b19intent.stagesis the canonical materialized plan; the redundantskip_stagesdeny-list removed. A stage can beoptional: true— the cursor leads the first elaborate tick with a keep-or-drop offer + a "what you're severing" dependents summary;haiku_drop_stageremoves it from the plan (never auto-drops); cross-stage refs to a dropped stage auto-ignore (coverage gate skips a dir-less stage, prompts inject only.existsinputs, decompose plan-filters). Audited every studio for mandatory-core vs optional and marked 47 stages across 22 studios optional.softwarereshaped to its MVP core —inception/product/developmentmandatory,design/operations/securityoptional (the briefly-addedreleasestage removed).deprecated: truehides a studio from new-intent pickers but keeps it resolvable (libdev).v9→v10migration stripsskip_stages+ materializesstages. Fixed: user-gate next-stage routing follows the intent plan, not the studio superset.bc0dcdf528370b974d7920ccef47f0bd85f39521aa280e3cb639ae2ff39a80b85f26bfbc4ed2bbd5f51ca584cbThe drift rewrite (flagship)
The bug this fixes (observed in production): a unit's output gets edited legitimately — a re-run or a fix-loop — the witness on the producer's approval no longer matches, and drift fires forever on the same file (
terraform/environments/ops/fnox.tomlwas the prompting case). The agent eventually reaches forhaiku_debug({op: "reset_drift"}). Debug becomes the recovery path for routine workflow. That's the smell.Under the premise-witness model:
input_witness; material close invalidates the slot and re-dispatch re-signs with current SHAs.reset_driftgoes back to being a debug escape hatch, not a normal recovery path.Witnesses live in unit/intent frontmatter, per signed slot — no separate files:
Drift phases (all landed)
input_witnessesschema +resolveInputWitnesses/ extendedbuildReviewRecordinput_witnesses(new kinds: mutation / addition / deletion)buildApprovalRecordreturns{at}only; sweep stops readingapprovals.witnessesapprovals.<role>.witnesses, deletes dead sidecarsdrift-markers.ts+baseline-clear-marker.ts+haiku_baseline_init.tsdeleted (~2,450 LOC)drift_detectedprompt rewritten + new input-drift test fileDeleted by v8→v9 migration (on-disk)
drift-markers.json,stages/<stage>/baseline.json,baseline-content/,.baseline-ack,baseline-thrash.json, and theapprovals.<role>.witnessesfield on every unit (stripped, slot kept).Source files deleted (Phase 8)
src/orchestrator/workflow/drift-markers.ts,src/orchestrator/workflow/baseline-clear-marker.ts,src/tools/orchestrator/haiku_baseline_init.ts,test/haiku-baseline-init.test.mjs.drift-baseline.tsstays — still used byhaiku_human_write, baseline-content/upload routes,stamp-agent-write, and the drift-sweep kill switch (isDriftDetectionDisabled). It's no longer load-bearing for detection; further decoupling is its own refactor.Review surface + micro-app (new since this PR opened)
The review SPA used to drop the human into a feedback modal that blocked the page and an Approve button tangled into the feedback flow, opened in whatever Chrome profile they last touched. That's now rebuilt:
FEEDBACKrail toggles a slide-out overlay drawer. Closed, it occupies a dedicated gutter and overlays nothing; open, it floats over content with no layout shift. The comment composer lives inside the drawer; Approve / Request Changes is a standalone gate bar. The rail and drawer are bounded strictly between the header and the gate bar via measured CSS custom properties (--review-header-h/--review-gatebar-h), so they sit over neither.open-ing the URL into the user's default browser, the MCP launches a Chromium-family browser in--appmode against an isolated per-session profile — a standalone window with its own dock entry, no tabs, no extensions, no cross-talk. It carries a H·AI·K·U favicon, maximizes DPR-proof so it never trips the mobile breakpoint, and the whole Chromium process tree is reaped on close (the Apple-Silicon build-detection + process-group fix inb7d6e5bc8killed a ghost-browser leak).Test coverage
96+ test files touched. New + reworked drift suites:
drift-input-witnesses(input mutation/addition/deletion + cosmetic re-stamp + implicitintent.md),drift-no-false-positives(now includes a negative test — output mutation does not fire drift),drift-scenarios(output-drift case converted to a negative regression guard), plus the worktree-isolation and advance-hat-dispatch contract tests. The review SPA carries a 556-test vitest suite; the micro-app browser-discovery + process-tree reap has its own regression coverage (x64 + arm64 layouts). Migration chain intact through v9.Review threads
All review threads on this PR are resolved — see the resolution summary mapping each finding to its fix commit.