docs(instructions): point the logic brief at hotcrm's real layout, and put the agent briefs under a gate - #1520
Conversation
…d guard the briefs `.github/instructions/logic.md` named `packages/crm/src/` in two worked examples — a layout this repo does not have. Application source is single-package under `src/<kind>/`, so the hook example now points at `src/objects/opportunity.hook.ts` (where the 17 real `*.hook.ts` files live; `src/hooks/` is a barrel) and the action example at `src/actions/ai_briefing.actions.ts`. The six per-role briefs sat outside every gate in the repo, which is why this drifted unnoticed. `test/docs-src-tree-paths.test.ts` now covers them: the `src/<dir>/` names-implies-exists check the other docs get, plus a ban on `packages/…` paths keyed on that directory's absence. The ban is the load-bearing half. The existing extractor wants a directory and the defect names a file directly under `src/`, so it captured nothing from the unfixed brief and passed over it — adding the path without widening the pattern would have shipped a guard that cannot fail on its own defect. `architect.md` is recorded as a tracked pending entry naming #1518, under an equality assertion that fails in both directions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019hUuCQStzXGMFSX4dzww5t
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Maintainer ruling, 2026-09-03, given in chat to the director seat (session_01WXyGTWPbbreqXow7Z2pZCk) on decision batch 2, item 4 (this PR, option A: merge whole, gate included). Verbatim: 「同意」. Executing on that instruction from the maintainer's own account: marking ready and arming auto-merge (squash), since this repository's rule requires the merge queue; the queue re-validates against today's Generated by Claude Code |
Fixes #1233
Two halves. The second is the one worth reviewing.
Half 1 — the stale paths
.github/instructions/logic.mdnamedpackages/crm/src/in two worked examples, not one. The card names line 71; line 47 carries the same prefix. Re-derived onorigin/main@d3fb7ca, both fixed:// packages/crm/src/opportunity.hook.ts// src/objects/opportunity.hook.ts// packages/crm/src/ai_briefing.actions.ts// src/actions/ai_briefing.actions.tsThere is no
packages/directory in this repo; top-level entries areapps assets content docs e2e scripts src test.Each target was confirmed against the real tree rather than assumed:
src/hooks/. That directory holds onlyindex.ts, a re-export barrel; all seventeen*.hook.tsfiles live insrc/objects/, andsrc/objects/opportunity.hook.tsexists. So the hook example points at the file it is an example of.ai_briefing.actions.tssurvives the move.src/actions/is keyed by convention onENTITY.actions.ts, but nothing gates the basename, andglobal.actions.tsis the standing proof — its own header says it "is still namedglobal.actions.tsfor import stability; nothing here is a global action any more". A new AI-briefing action file belongs atsrc/actions/ai_briefing.actions.ts.Half 2 — the guard, and why the pattern had to widen
These six per-role briefs sat outside every gate in the repo. Nothing under
test/,scripts/orpackage.jsonreferenced the directory at all — re-measured, still 0 hits. That is why this drifted unnoticed.The guard moved. The card points at
TREE_DOCSintest/docs-drift.test.ts; #1196 split that file by family and the repo-tree path family now lives intest/docs-src-tree-paths.test.ts. The work lands there, and the SPLIT BY FAMILY pointer table indocs-drift.test.tsis updated to say so.Two rules, because the defect has two halves:
src/DIR/named implies it exists — the same check the maintainer and product docs already get, overlogic.md, with the vacuity assertionPRODUCT_TREE_DOCScarries.packages/...path at all, over every.mdin the directory, walked rather than listed — a brief added tomorrow is covered without anyone remembering to enrol it.Rule 2 is not decoration, and this is the measurement the grading asked for.
inlineSrcDirs()wants a directory (src/([a-z][a-z0-9_]*)/); the defect names a file directly undersrc/. Run the existing extractor over the unfixed brief and it returns[]— so the names-implies-exists assertion has nothing to find missing and is green. Appending the path toTREE_DOCS, which carries no vacuity guard, would have shipped a check that is green on the very defect it was added for.Rule 2 is keyed on the tree, not on a taste for
src/:packages/is banned because this repo has none, and the assertion saying so runs first. Give hotcrm a realpackages/directory and the block throws and demands a rewrite instead of going on banning prose that has become true.Observed failing before it was accepted
Ablation on the committed tree: the two paths were reverted to
packages/crm/src/..., the mutation was confirmed on disk (2 injected lines, 0 remaining fixed lines, on-disk hash4df75933differing from the HEAD blobb3ae1a39), and the file was run.The second failure is the fake-green, caught in the act: the substantive
missingassertion never ran, because there was nothing to check. Restored withgit checkout HEAD -- ABSOLUTE_PATH, hash back tob3ae1a39,git diff HEADempty, re-run 28 passed, exit 0. No build step is involved — the test reads the briefs as text, so there is nodist/for a stale artefact to hide in.The architect.md question, answered
The dispatch asked whether
architect.md'spackages/hr/src/...references are the same defect class. They are — the "worked teaching example" reading is only half the file.Exact count, since it matters: 9 lines of the form
packages/hr/src/NAME.KIND.ts(11-13, 17-18, 22-23, 27-28), pluspackages/[name]on line 46 — 10 distinctpackages/...strings.Lines 11-28 are indeed a hypothetical Recruiting System, and taken alone the illustrative reading holds. Lines 30-37 and 46 are not examples:
crm/products/financeas layered packages and forbidding imports "from a higher-layer package". None exist.### 📦 Package: packages/[name]. That is a path an agent is told to write, same kind as thelogic.mdcomment.src/foo.object.ts— the single-package layout. Strong evidence thepackages/content is residue, not teaching.It is not fixed here, and not suppressed either. The remedy is not a path rewrite: it needs a decision on whether this repo's architect plans in packages at all, and the same example routes files to
.mask.ts/.workflow.ts/.rls.tskinds that have no directory here (all three finds return nothing), so stripping the prefix would trade one absent path for another. Filed as #1518 with the measurement.The file is recorded in
PENDING_PACKAGES_REFSnaming #1518, under an equality assertion, so it fails in both directions: a new brief picking up the layout goes red, andarchitect.mdbeing cleaned up also goes red, demanding the entry be deleted. The exception can only shrink and cannot outlive its defect. The ablation output above shows it doing exactly that job —architect.mdsits in the expected set whilelogic.mdis reported as the new offender.Changeset
Empty-frontmatter, matching
agents-md-pure-metadata-principles.mdanddangling-tabs-citations.md: agent briefs and a test only, nothing released to HotCRM users, nosrc/metadata touched. Theskip-changesetlabel is the alternative sanctioned bychangeset-check.yml; the in-repo declaration was preferred because it leaves a durable record and needs no label write.Gates
pnpm verifyond7d54a9, the tip of this branch, exit 0 — all eight stages:Landing
Draft on purpose. Per the 2026-08-25 grading on #1233 this lands by human merge, not the merge queue —
.github/instructions/**is not in the literal governed-surface list, but these are per-role agent instruction files (logic.mdopens "You are the Backend Engineer for HotCRM") and are treated asAGENTS.md-class. The grading also asks foros-zhuangon review; that request is left to the dispatching seat, which owns the landing path.Whether
.github/instructions/**is formally governed is not decided here — it is a change to the governed-surface definition and belongs to the maintainer / skills seat.🤖 Generated with Claude Code
Generated by Claude Code
Generated by Claude Code