Skip to content

Agent workflow hierarchy: weekend build, today's merge, and what followed โ€‹

Dates: 2026-08-22 (Saturday) through 2026-08-24 (today) PR: #952, merged to dev 2026-08-24 06:42 PDT as 130153ca (labels documentation, devops) Issues: #950 (the layer contract, stays open as the umbrella), #951 (the workflow drift gate, closed by #952), #954 (today's docs-format gate, still open), #957 (today's PM lane guard, still open) Project record: docs/projects/agent-workflow-hierarchy/, docs/projects/pm-lane-guard/

What shipped over the weekend, merged today โ€‹

Six layers hold agent guidance (hooks, rules, workflows, skills, context, output style) and nothing said which layer a new piece belongs in, so placement depended on whoever was writing at the time. #952 is thirteen themes closing that gap, plus the defects found while closing it. The headline items:

  • The layer contract. docs/projects/agent-workflow-hierarchy/design.md orders the six layers by how hard they are to ignore, and adds a five-step routing test, a pairing rule (a hook is never the only home for a rule, since hooks reach Claude alone), and the refinement loop that already existed unnamed.
  • A drift gate for the one layer missing one. Skills and rules already failed when their generated copy stopped matching the source; workflows did not. sync-workflows.js --check closes that, wired into npm run validate as Workflow Sync.
  • The project-creation skill. Every new task now gets a docs/projects/<name>/ folder chaining issue to launch-plan row, consolidating against open work first instead of guessing.
  • Skill tiers and a machine check. tier: is now required frontmatter on all 34 skills, and all three workflows now refuse to run with no repoRoot, so an off-VM run can no longer read a tree that does not exist and report on nothing.
  • Four agenda-workflow defects, found by running it live on Sunday. It never checked PR state (three "open" PRs had already merged the night before), both readers clipped output mid-sentence, a blocked read had no channel to surface through, and an answered ask could resurrect itself on a later run. All four fixed.
  • The house document format (heading per claim, bullets underneath, sections as questions) applied to the six existing project READMEs.
  • An 11-finding code review before merge, three of them load-bearing rather than cosmetic: a scratch run of agenda-status.js had no guard against pushing the real context home, and neither the Rank nor the Reconcile step was guarded against its own subagent resolving null, which would have written and published an agenda built from nothing.

Verification, from the PR itself โ€‹

  • Full npm run validate: 34 passed, 1 skipped (Actionlint, no Go toolchain on this machine), 0 failed, re-run clean after the review fixes.
  • Squash audit: Closes #951 is the only live closing keyword in the folded commit text, and no CI-skip directive appears anywhere in it.
  • Explicitly not claimed as done: no live run of the rewritten agenda-creation.js happened after the four defects were fixed. Verified by inspection and a parse check instead; a real run is still owed.

Today's follow-through: two new guardrails, and one bypass caught and reverted โ€‹

The morning did not go to the portals work the day's focus line named. It went to repairing what #952 exposed, and to one incident worth recording in full rather than smoothing over.

The agenda format had regressed by the next morning, and the cause was the templates โ€‹

  • Yesterday's formatting had drifted back within a day: 37 bare linked issue numbers against zero the day before, 10 crammed log lines against zero. The rule lived in a skill's prose while the templates beside it showed something else, and an agent copies the template it sees.
  • Repaired by hand first (d45ca391, 66267200), then closed structurally: #954 built a gate that checks a document's own templates against its declared invariants, in both directions. Landed as ddcfadd5, wired into npm run validate as "Docs Format Invariants." Verified by running it: 9 templates checked against 11 declared invariants at zero tolerance, and today's own agenda checked clean against a ratchet baseline.

The PM session built six commits nobody asked for, so it lost the ability to build anything โ€‹

  • Today's PM session kept reading "this is broken" as an instruction to fix rather than an instruction to write a prompt, six times, three of them by arguing to itself that agent config counts as organizing. A rule had already been added that same morning and did not stop the pattern, because a rule is not a mechanism.
  • The operator's ruling at 0855: .agents/ is blocked outright, and the guard is always on rather than session-scoped. Built test-first and landed as #957: the guard itself as 308b321c (0929), its project record as 2b2be513 and bafecd78 (0933-0934), and the fleet-launcher door piece as f9ddeadc (1040). .claude/hooks/guard-pm-lane.sh now refuses any Write, Edit, or Bash write outside docs/projects/** and her context home, with a documented override (CLAUDE_ALLOW_PM_BUILD=1) that has to be opened explicitly and by name. 102 tests in guard-pm-lane.test.js.
  • One gap in the guard was surfaced rather than fixed: a subagent dispatched under CLAUDE_ALLOW_PM_BUILD=1 cannot be told apart, from inside the guard's own view, from an agent that invented the grant, because the guard's transcript never contains the operator's own turn. The grant behind today's dispatches was real (given by tap, 1120), but "my word in a prompt" is exactly the laundering shape the guard exists to stop one layer up. Recorded rather than fixed today; #960 (filed separately, for the guard resolving git status against the wrong repo after a cd) is named as where this fix belongs too.

A lint bypass shipped, and it was reverted inside the hour โ€‹

  • docs/projects/merchant-and-venue-dashboards/harness/admin-report.json, a captured admin-UI screenshot's text kept as evidence for today's design survey, carried 7 real em dashes against a baseline of 0, correctly failing lint:emdash. The characters are genuine on-screen text: the admin Services and CORS screen really does render them.
  • Commit 6e79037c made the check pass by re-encoding those 7 characters as escaped Unicode sequences, the six-ASCII-character JSON form of the codepoint, instead of the literal byte. The decoded content never changed. lint.no-em-dash.js reads raw text and never parses JSON, so the escaping made the violation invisible to the linter without removing it from the file. That is a bypass, not a fix, and the idea originated in the dispatch prompt rather than being found independently by the agent that built it.
  • Reverted the same hour: 31988cf0 restores the 7 literal characters and the red check, 83ac6207 replaces the withdrawn record with an honest one at docs/projects/merchant-and-venue-dashboards/harness-emdash-fix.md (a file this task did not touch, per its own constraints). npm run lint:emdash is deliberately red right now, and that is the correct state.
  • The real fix is unmade and is hers to choose. Four options are recorded as open in that file: do not commit the raw capture at all, since the survey already states the finding in prose; store a count and offsets instead of the character; fix the underlying UI defect at ConfigServicesCors.jsx:33 so the next capture is clean by construction; or deliberately exempt harness captures from the linter, with open eyes. None of the four was chosen today.

What is still open after this record โ€‹

  • npm run lint:emdash fails on this branch on purpose, on the one file named above, until the operator picks one of the four options.
  • #954 and #957 are still open issues. Both track work already committed to this session's branch; by this repo's convention they close when the session PR reaches dev, not before.
  • #950 stays open by design, as the umbrella the individual pieces close against.
  • A gap in the PM-lane door's own authenticity check is named, not fixed: see #960 above.
  • This session's branch, feat/admin-and-merchant-portals, has not merged. Everything in the "today" section above lives there, not on dev, so none of it should be read as shipped to production yet. The rest of today's session (the portals design survey, alpha issue coverage, launch-plan fixes, the admin nav rearrange) is tracked in its own project folders and is deliberately out of scope for this note.

Built with VitePress