@erclx/canon 5.30.0 → 5.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/references/adopted.md +1 -1
- package/claude/skills/auto-ship/REQUIREMENT.md +4 -16
- package/claude/skills/auto-ship/SKILL.md +13 -58
- package/claude/skills/auto-ship/references/draft-mark.md +2 -2
- package/claude/skills/auto-ship/references/failure-recovery.md +1 -5
- package/claude/skills/auto-ship/references/tier-failures.md +1 -1
- package/claude/skills/auto-ship/references/ui-checklist.md +2 -2
- package/claude/skills/auto-ship/references/verb-absent.md +3 -27
- package/claude/skills/backlog-triage/SKILL.md +1 -1
- package/claude/skills/build-in-slices/REQUIREMENT.md +1 -1
- package/claude/skills/build-in-slices/references/adopted.md +1 -1
- package/claude/skills/canon-cli/REQUIREMENT.md +4 -6
- package/claude/skills/canon-cli/SKILL.md +2 -2
- package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
- package/claude/skills/canon-feedback/SKILL.md +10 -13
- package/claude/skills/canon-feedback-triage/REQUIREMENT.md +13 -14
- package/claude/skills/canon-feedback-triage/SKILL.md +50 -29
- package/claude/skills/canvas/REQUIREMENT.md +3 -4
- package/claude/skills/canvas/SKILL.md +5 -5
- package/{standards → claude/skills/canvas/references}/canvas.md +12 -1
- package/claude/skills/ci-workflow/REQUIREMENT.md +0 -1
- package/claude/skills/context-fold/REQUIREMENT.md +8 -20
- package/claude/skills/context-fold/SKILL.md +21 -45
- package/claude/skills/context-fold/references/classify.md +7 -8
- package/claude/skills/context-fold/references/completion-report.md +2 -6
- package/claude/skills/context-fold/references/context-refresh.md +5 -15
- package/claude/skills/context-fold/references/promoted-pages.md +3 -3
- package/claude/skills/context-fold/references/receipt-sweep.md +6 -17
- package/claude/skills/context-fold/references/unusable-baseline.md +4 -6
- package/claude/skills/create-rule/REQUIREMENT.md +0 -1
- package/claude/skills/create-skill/REQUIREMENT.md +6 -4
- package/claude/skills/create-skill/SKILL.md +9 -8
- package/{standards → claude/skills/create-skill/references}/skill-paths.md +1 -0
- package/claude/skills/decision-escalate/REQUIREMENT.md +1 -1
- package/claude/skills/decision-escalate/SKILL.md +1 -1
- package/claude/skills/design-taste/REQUIREMENT.md +0 -2
- package/claude/skills/design-taste/SKILL.md +2 -4
- package/claude/skills/design-taste/references/vocabulary.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +3 -3
- package/claude/skills/docs-sync/SKILL.md +1 -1
- package/claude/skills/document-health/REQUIREMENT.md +2 -2
- package/claude/skills/document-health/SKILL.md +4 -5
- package/claude/skills/document-health/references/axes.md +4 -6
- package/claude/skills/draft-and-pick/REQUIREMENT.md +16 -14
- package/claude/skills/draft-and-pick/SKILL.md +40 -32
- package/claude/skills/draft-and-pick/references/live-arms.md +9 -9
- package/claude/skills/draft-doc/REQUIREMENT.md +5 -5
- package/claude/skills/draft-doc/SKILL.md +10 -11
- package/claude/skills/draft-doc/references/requirements.md +61 -0
- package/claude/skills/draft-doc/references/wiki-kind.md +53 -0
- package/claude/skills/draft-doc/references/wiki.md +50 -30
- package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
- package/claude/skills/draft-figure/SKILL.md +5 -5
- package/claude/skills/draft-figure/references/architecture-set.md +4 -4
- package/claude/skills/draft-figure/references/hand-drawn.md +1 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +55 -0
- package/claude/skills/draft-figure/references/mermaid.md +43 -34
- package/claude/skills/draft-identity/REQUIREMENT.md +1 -1
- package/claude/skills/draft-identity/SKILL.md +9 -7
- package/claude/skills/draft-ready/REQUIREMENT.md +1 -1
- package/claude/skills/draft-ready/SKILL.md +6 -6
- package/claude/skills/draft-ready/references/assembly.md +1 -1
- package/{standards → claude/skills/draft-ready/references}/ready.md +13 -5
- package/claude/skills/git-issue/SKILL.md +1 -1
- package/claude/skills/git-issue/references/issue.md +3 -3
- package/claude/skills/git-pr/SKILL.md +1 -1
- package/claude/skills/git-ship/REQUIREMENT.md +0 -2
- package/claude/skills/git-ship/SKILL.md +16 -24
- package/claude/skills/git-stage/SKILL.md +1 -1
- package/claude/skills/markdown-craft/REQUIREMENT.md +23 -0
- package/claude/skills/markdown-craft/SKILL.md +17 -0
- package/{standards → claude/skills/markdown-craft/references}/markdown.md +14 -7
- package/claude/skills/plan-feature/REQUIREMENT.md +2 -1
- package/claude/skills/plan-feature/SKILL.md +14 -8
- package/{standards → claude/skills/plan-feature/references}/plan.md +33 -21
- package/claude/skills/plan-groundwork/SKILL.md +5 -6
- package/{standards → claude/skills/plan-groundwork/references}/groundwork.md +17 -4
- package/claude/skills/plan-intake/SKILL.md +2 -3
- package/{standards → claude/skills/plan-intake/references}/intake.md +17 -2
- package/claude/skills/plan-intake-answer/REQUIREMENT.md +1 -1
- package/claude/skills/plan-intake-answer/SKILL.md +1 -1
- package/claude/skills/review-address/SKILL.md +2 -2
- package/claude/skills/review-address/references/post-review-findings.md +1 -1
- package/claude/skills/review-craft/REQUIREMENT.md +3 -3
- package/claude/skills/review-craft/SKILL.md +2 -2
- package/claude/skills/review-craft/references/ui.md +4 -4
- package/claude/skills/review-pr/REQUIREMENT.md +1 -1
- package/claude/skills/review-pr/SKILL.md +5 -7
- package/claude/skills/review-pr/references/post.md +2 -2
- package/claude/skills/review-ui/REQUIREMENT.md +0 -1
- package/claude/skills/review-ui/SKILL.md +1 -1
- package/claude/skills/review-ui/references/post.md +1 -1
- package/claude/skills/role-orchestrator/REQUIREMENT.md +0 -3
- package/claude/skills/role-orchestrator/SKILL.md +8 -8
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +4 -3
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +7 -10
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +0 -3
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +1 -1
- package/claude/skills/role-planner/SKILL.md +2 -2
- package/claude/skills/role-reviewer/SKILL.md +1 -1
- package/claude/skills/role-worker/SKILL.md +2 -2
- package/claude/skills/session-compact/REQUIREMENT.md +1 -4
- package/claude/skills/session-compact/SKILL.md +3 -13
- package/claude/skills/session-compact/references/handoff-note.md +2 -2
- package/claude/skills/session-map/REQUIREMENT.md +1 -9
- package/claude/skills/session-map/SKILL.md +8 -16
- package/{standards → claude/skills/session-map/references}/session.md +17 -11
- package/claude/skills/session-relay/REQUIREMENT.md +1 -1
- package/claude/skills/session-resume/REQUIREMENT.md +4 -6
- package/claude/skills/session-resume/SKILL.md +3 -9
- package/claude/skills/session-worktree/SKILL.md +1 -1
- package/claude/skills/session-worktree/references/main-root-writes.md +2 -2
- package/claude/skills/systematic-debugging/REQUIREMENT.md +0 -1
- package/claude/skills/target-check/REQUIREMENT.md +3 -3
- package/claude/skills/target-check/SKILL.md +1 -1
- package/claude/skills/target-check/references/domains.md +1 -1
- package/claude/skills/target-setup/REQUIREMENT.md +4 -4
- package/claude/skills/target-setup/SKILL.md +3 -3
- package/claude/skills/target-setup/references/detect.md +1 -1
- package/claude/skills/target-setup/references/indexes.md +1 -1
- package/claude/skills/task-board/SKILL.md +4 -4
- package/claude/skills/task-board/references/archive.md +1 -1
- package/{standards → claude/skills/task-board/references}/board.md +9 -0
- package/claude/skills/task-board/references/decline.md +1 -1
- package/{standards → claude/skills/task-board/references}/tasks.md +13 -8
- package/claude/skills/teach-workspace/SKILL.md +1 -1
- package/claude/skills/teach-workspace/references/revisit.md +1 -1
- package/{standards → claude/skills/teach-workspace/references}/teach.md +17 -5
- package/claude/skills/test-first/REQUIREMENT.md +1 -1
- package/claude/skills/ux-audit/REQUIREMENT.md +2 -2
- package/claude/skills/ux-audit/SKILL.md +2 -3
- package/claude/skills/write-human/REQUIREMENT.md +0 -1
- package/claude/skills/write-human/SKILL.md +2 -2
- package/docs/agents/audits.md +1 -1
- package/docs/agents/canvas.md +1 -1
- package/docs/agents/commands.md +6 -10
- package/docs/agents/context-audit-checks.md +10 -24
- package/docs/agents/context-audit.md +7 -15
- package/docs/agents/context-classify.md +5 -5
- package/docs/agents/counts.md +5 -5
- package/docs/agents/drift-surfaces.md +2 -2
- package/docs/agents/index.md +3 -4
- package/docs/agents/install-and-sync.md +6 -6
- package/docs/agents/intake.md +1 -1
- package/docs/agents/markdown-audit.md +1 -1
- package/docs/agents/records-stale.md +5 -5
- package/docs/agents/records-validate.md +1 -1
- package/docs/agents/records.md +2 -2
- package/docs/agents/restated.md +1 -1
- package/docs/agents/routing.md +1 -1
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/skills-audit.md +2 -2
- package/docs/agents/state-scoped-risk.md +2 -2
- package/docs/agents/superseded.md +2 -2
- package/docs/agents/tasks-plans.md +2 -2
- package/docs/agents/tasks-validate.md +1 -1
- package/docs/agents/tasks.md +1 -1
- package/docs/agents/teach.md +1 -1
- package/docs/agents/test-order.md +1 -1
- package/docs/agents/upstream.md +94 -0
- package/docs/target/migrations.md +24 -0
- package/docs/target/projects.md +5 -7
- package/docs/target/scenarios.md +2 -2
- package/docs/target/sync.md +3 -3
- package/docs/workflow/ai-workflow.md +7 -38
- package/docs/workflow/index.md +1 -1
- package/docs/workflow/operating-model.md +8 -8
- package/docs/workflow/parallel-features.md +7 -7
- package/docs/workflow/skill-map-on-request.md +13 -16
- package/docs/workflow/skill-map.md +20 -32
- package/docs/workflow/visual-design-workflow.md +11 -14
- package/governance/renames.toml +0 -23
- package/governance/rules/canon/605-worktrees.md +1 -1
- package/governance/rules/{standards → canon}/plan.md +5 -5
- package/governance/rules/canon/tasks.md +18 -0
- package/governance/rules/writing/markdown.md +23 -0
- package/governance/stacks/base.toml +1 -1
- package/package.json +1 -1
- package/scripts/core/install-check.sh +2 -2
- package/scripts/core/regen-web-previews.ts +1 -1
- package/src/audits/catalog.ts +5 -97
- package/src/claude/cases/authoring.ts +5 -18
- package/src/claude/cases/misc.ts +0 -17
- package/src/claude/cases/setup.ts +3 -20
- package/src/claude/cases/workflow.ts +0 -33
- package/src/claude/seeds.ts +1 -7
- package/src/claude/skills-audit.ts +1 -1
- package/src/claude/skills-reach.ts +1 -1
- package/src/cli/help.ts +3 -4
- package/src/cli.ts +2 -4
- package/src/commands/claude.ts +9 -15
- package/src/commands/context.ts +18 -280
- package/src/commands/feedback.ts +22 -91
- package/src/commands/gov.ts +2 -2
- package/src/commands/records.ts +24 -6
- package/src/commands/sync.ts +5 -3
- package/src/commands/upstream.ts +430 -0
- package/src/context/audit.ts +6 -15
- package/src/context/classify/extract.ts +6 -13
- package/src/context/classify/patterns.ts +2 -41
- package/src/context/classify/prompts.ts +2 -6
- package/src/context/classify/run.ts +3 -3
- package/src/context/folders.ts +7 -12
- package/src/context/gate.ts +11 -91
- package/src/context/requirements.ts +13 -4
- package/src/counts/scan.ts +3 -3
- package/src/design/components.ts +2 -2
- package/src/feedback/body.ts +0 -12
- package/src/gate/measures.ts +6 -57
- package/src/gate/stages.ts +0 -1
- package/src/gov/citations.ts +9 -3
- package/src/gov/restated.ts +3 -3
- package/src/markdown/structure.ts +3 -3
- package/src/migrate/record-layout.ts +3 -3
- package/src/records/backup.ts +1 -0
- package/src/records/ordinal.ts +1 -1
- package/src/records/prune.ts +2 -1
- package/src/records/stale-canonical.ts +2 -2
- package/src/records/validate.ts +55 -0
- package/src/roots/record.ts +2 -1
- package/src/sandbox/scenario.ts +115 -11
- package/src/shipped/references.ts +3 -3
- package/src/standards/read.ts +52 -1
- package/src/sync/seeds-report.ts +1 -1
- package/src/tasks/answers.ts +14 -1
- package/src/tasks/reach.ts +2 -2
- package/src/tasks/stack.ts +176 -0
- package/src/tasks/validate.ts +1 -1
- package/src/teach/workspace.ts +1 -1
- package/src/upstream/catalog.ts +112 -0
- package/src/upstream/cursor.ts +120 -0
- package/src/upstream/digest.ts +75 -0
- package/src/upstream/due.ts +128 -0
- package/src/upstream/releases.ts +170 -0
- package/standards/context.md +3 -5
- package/standards/design.md +2 -3
- package/standards/index.md +0 -23
- package/standards/publish.md +1 -1
- package/standards/rule.md +1 -1
- package/standards/skill.md +1 -1
- package/tooling/base/reference.md +1 -1
- package/tooling/claude/reference.md +6 -20
- package/tooling/claude/seeds/.claude/hooks/index-reminder.sh +1 -1
- package/tooling/claude/seeds/.claude/hooks/records-index.sh +8 -20
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +3 -3
- package/tooling/claude/seeds/CLAUDE.md +1 -3
- package/tooling/claude/seeds/canon/REQUIREMENTS.md +2 -9
- package/tooling/web/configs/e2e/screenshot.ts +0 -1
- package/claude/skills/auto-ship/references/review-findings.md +0 -20
- package/claude/skills/bash-cli-script/REQUIREMENT.md +0 -43
- package/claude/skills/bash-cli-script/SKILL.md +0 -53
- package/claude/skills/bash-cli-script/references/template.md +0 -19
- package/claude/skills/canon-operator/REQUIREMENT.md +0 -62
- package/claude/skills/canon-operator/SKILL.md +0 -113
- package/claude/skills/canon-rollout/REQUIREMENT.md +0 -59
- package/claude/skills/canon-rollout/SKILL.md +0 -140
- package/claude/skills/canon-rollout/references/failure-recovery.md +0 -20
- package/claude/skills/context-fold/references/anchor-sweep.md +0 -58
- package/claude/skills/context-fold/references/wireframe-sweep.md +0 -45
- package/claude/skills/create-standard/REQUIREMENT.md +0 -33
- package/claude/skills/create-standard/SKILL.md +0 -31
- package/claude/skills/design-extract/REQUIREMENT.md +0 -42
- package/claude/skills/design-extract/SKILL.md +0 -108
- package/claude/skills/draft-and-pick/references/frame.html +0 -118
- package/claude/skills/draft-doc/references/wireframes.md +0 -48
- package/claude/skills/index-lookup/REQUIREMENT.md +0 -35
- package/claude/skills/index-lookup/SKILL.md +0 -44
- package/claude/skills/markdown-propose/REQUIREMENT.md +0 -47
- package/claude/skills/markdown-propose/SKILL.md +0 -122
- package/claude/skills/markdown-propose/references/format.md +0 -118
- package/claude/skills/memory-capture/REQUIREMENT.md +0 -50
- package/claude/skills/memory-capture/SKILL.md +0 -117
- package/claude/skills/memory-review/REQUIREMENT.md +0 -52
- package/claude/skills/memory-review/SKILL.md +0 -129
- package/claude/skills/memory-review/references/later-phases.md +0 -118
- package/claude/skills/memory-review/references/receipt-format.md +0 -64
- package/claude/skills/project-commands/REQUIREMENT.md +0 -42
- package/claude/skills/project-commands/SKILL.md +0 -87
- package/claude/skills/repo-metadata/REQUIREMENT.md +0 -37
- package/claude/skills/repo-metadata/SKILL.md +0 -54
- package/claude/skills/restate-plainly/REQUIREMENT.md +0 -41
- package/claude/skills/restate-plainly/SKILL.md +0 -41
- package/claude/skills/review-branch/REQUIREMENT.md +0 -40
- package/claude/skills/review-branch/SKILL.md +0 -137
- package/claude/skills/seed-sync/REQUIREMENT.md +0 -45
- package/claude/skills/seed-sync/SKILL.md +0 -158
- package/claude/skills/sketch-design/REQUIREMENT.md +0 -38
- package/claude/skills/sketch-design/SKILL.md +0 -94
- package/claude/skills/ux-walkthrough/REQUIREMENT.md +0 -56
- package/claude/skills/ux-walkthrough/SKILL.md +0 -53
- package/claude/skills/ux-walkthrough/references/builds.md +0 -15
- package/claude/skills/ux-walkthrough/references/candidate-pages.md +0 -11
- package/claude/skills/ux-walkthrough/references/measuring.md +0 -22
- package/claude/skills/ux-walkthrough/references/record.md +0 -36
- package/claude/skills/ux-walkthrough/references/relay.md +0 -25
- package/docs/agents/architecture-record.md +0 -36
- package/docs/agents/review-classification.md +0 -76
- package/governance/rules/canon/601-indexes.md +0 -9
- package/governance/rules/canon/603-memory.md +0 -11
- package/governance/rules/claude/565-behavior.md +0 -27
- package/governance/rules/claude/567-planning.md +0 -16
- package/governance/rules/claude/575-hooks.md +0 -16
- package/governance/rules/claude/576-settings.md +0 -13
- package/governance/rules/claude/592-claude-md.md +0 -19
- package/governance/rules/lang/120-bash.md +0 -18
- package/governance/rules/standards/architecture.md +0 -13
- package/governance/rules/standards/groundwork.md +0 -13
- package/governance/rules/standards/intake.md +0 -12
- package/governance/rules/standards/markdown.md +0 -16
- package/governance/rules/standards/memory.md +0 -12
- package/governance/rules/standards/ready.md +0 -13
- package/governance/rules/standards/requirements.md +0 -12
- package/governance/rules/standards/session.md +0 -13
- package/governance/rules/standards/tasks.md +0 -15
- package/governance/rules/standards/teach.md +0 -14
- package/governance/rules/standards/wiki.md +0 -13
- package/governance/rules/standards/wireframes.md +0 -13
- package/governance/rules/writing/800-prose.md +0 -15
- package/src/autoship/classify.ts +0 -75
- package/src/autoship/paths.ts +0 -50
- package/src/commands/autoship.ts +0 -129
- package/src/commands/repo.ts +0 -393
- package/src/context/architecture.ts +0 -654
- package/src/context/wireframe-states.ts +0 -238
- package/src/repo/metadata.ts +0 -206
- package/standards/architecture.md +0 -127
- package/standards/memory.md +0 -158
- package/standards/mermaid.md +0 -64
- package/standards/requirements.md +0 -79
- package/standards/wiki.md +0 -77
- package/standards/wireframes.md +0 -143
- package/tooling/claude/seeds/.claude/memory/index.md +0 -8
- package/tooling/claude/seeds/canon/ARCHITECTURE.md +0 -23
- package/tooling/claude/seeds/canon/wireframes/index.md +0 -8
- /package/{standards → claude/skills/create-skill/references}/skill-practice.md +0 -0
- /package/{standards → claude/skills/create-skill/references}/skill-requirement.md +0 -0
- /package/{standards → claude/skills/plan-feature/references}/plan-lifecycle.md +0 -0
- /package/{standards → claude/skills/plan-groundwork/references}/groundwork-spikes.md +0 -0
- /package/{standards → claude/skills/task-board/references}/tasks-decline.md +0 -0
- /package/{standards → claude/skills/teach-workspace/references}/glossary.md +0 -0
package/src/context/audit.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { isStubSeed } from '@/tooling/seed-marker'
|
|
|
18
18
|
* Every reason `canon context audit` refuses for.
|
|
19
19
|
*
|
|
20
20
|
* `no-folders` is the one ordinary absence: a project that never adopted
|
|
21
|
-
* `canon/context
|
|
21
|
+
* `canon/context/`, and holds no `.canon/diagrams/`
|
|
22
22
|
* folder an older install left, names no corpus this audit can measure, the
|
|
23
23
|
* same state `no-skills` reads for the skill corpora. The other four are a malformed invocation or a checkout git
|
|
24
24
|
* cannot read, which stay a break rather than an absence.
|
|
@@ -54,16 +54,13 @@ const CATALOG_NAMED_RATIO = 0.6
|
|
|
54
54
|
*
|
|
55
55
|
* These names do not generalize the way a length threshold does, which is why
|
|
56
56
|
* each list is keyed on the folder whose standard states it. `context.md`
|
|
57
|
-
* requires an overview and a layout.
|
|
58
|
-
* surface and answers each in a section, so those four are required and
|
|
59
|
-
* `## Behavior` is not, since a static surface has no interaction to state. A
|
|
57
|
+
* requires an overview and a layout. A
|
|
60
58
|
* diagram entry declares a heading per kind and its standard requires none.
|
|
61
59
|
*/
|
|
62
60
|
export const REQUIRED_SECTIONS_BY_FOLDER: Readonly<
|
|
63
61
|
Record<string, readonly string[]>
|
|
64
62
|
> = {
|
|
65
63
|
context: ['Overview', 'Layout'],
|
|
66
|
-
wireframes: ['Regions', 'States', 'Copy', 'Not on this surface'],
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
/**
|
|
@@ -158,15 +155,14 @@ const SENTENCE_END = /[.!?:;]\s(?=[^.!?:;]*$)/
|
|
|
158
155
|
* reading that field for a gain of one word.
|
|
159
156
|
*
|
|
160
157
|
* `standards/context.md` opens its scope by handing figures to the
|
|
161
|
-
* `draft-figure` skill
|
|
162
|
-
*
|
|
163
|
-
* standard routes elsewhere. The length and table
|
|
158
|
+
* `draft-figure` skill, so a marker reported in a diagrams entry would cite a
|
|
159
|
+
* rule that entry's own standard routes elsewhere. The length and table
|
|
164
160
|
* checkpoints are quoted from the same standard and keep reaching every audited
|
|
165
161
|
* folder, because a threshold on how far a reader travels generalizes across
|
|
166
162
|
* entry types while a rule about what an entry may say does not.
|
|
167
163
|
*
|
|
168
164
|
* What gates here is a rule only this standard states. Bullet weight does not,
|
|
169
|
-
* since `
|
|
165
|
+
* since `claude/skills/markdown-craft/references/markdown.md` owns that checkpoint across document types and
|
|
170
166
|
* its remedy sends the overflow to prose, which any entry type can act on.
|
|
171
167
|
* `standards/context.md` specializes that remedy for an entry carrying
|
|
172
168
|
* decisions, and specializing a rule narrows the advice rather than the measure.
|
|
@@ -495,7 +491,7 @@ function bareReferences(
|
|
|
495
491
|
* path prefix hardcodes what `--folder` exists to override and misses a domain
|
|
496
492
|
* split into `context/<sub-area>/`. Sibling names arrive the same way and for
|
|
497
493
|
* the same reason, since the folder an entry sits in is what holds them. The
|
|
498
|
-
* required sections arrive apart from jurisdiction, since a
|
|
494
|
+
* required sections arrive apart from jurisdiction, since a folder can owe
|
|
499
495
|
* sections under a standard that states no provenance rule.
|
|
500
496
|
*/
|
|
501
497
|
export function measureEntry(
|
|
@@ -652,11 +648,6 @@ export function matchesSiblings(folder: AuditedFolder): boolean {
|
|
|
652
648
|
* The standard sanctions omitting `## Layout` from a domain owning no paths,
|
|
653
649
|
* which no measure can tell from an entry that forgot it. An entry of that
|
|
654
650
|
* shape therefore reports, which is a reason this is printed and never gated on.
|
|
655
|
-
*
|
|
656
|
-
* A wireframe folder answers per file whether nested or not, since its
|
|
657
|
-
* standard keeps one surface per file. A subfolder of wireframes groups
|
|
658
|
-
* surfaces the way the named context folder groups domains, so a conforming
|
|
659
|
-
* sibling there says nothing about the surface beside it.
|
|
660
651
|
*/
|
|
661
652
|
export function missingSections(
|
|
662
653
|
root: string,
|
|
@@ -7,15 +7,13 @@ import { listChangedFiles, resolveBaseRef } from '@/git/files'
|
|
|
7
7
|
import { surfaceDir } from '@/roots/surface'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* The
|
|
10
|
+
* The three canonical doc types the classifier reaches, matching the file
|
|
11
11
|
* pattern the groundwork spike scoped its fixture to
|
|
12
12
|
* (`scripts/hunks.py`'s `DOC_PATH`) and the file-type catalog both system
|
|
13
13
|
* prompts state.
|
|
14
14
|
*/
|
|
15
15
|
export const CANONICAL_DOC_TYPES = [
|
|
16
16
|
'context',
|
|
17
|
-
'architecture',
|
|
18
|
-
'wireframes',
|
|
19
17
|
'design',
|
|
20
18
|
'requirements',
|
|
21
19
|
] as const
|
|
@@ -24,23 +22,19 @@ export type CanonicalDocType = (typeof CANONICAL_DOC_TYPES)[number]
|
|
|
24
22
|
|
|
25
23
|
const DOC_PATTERNS: Record<CanonicalDocType, RegExp> = {
|
|
26
24
|
context: /(^|\/)context\/.+\.md$/,
|
|
27
|
-
architecture: /(^|\/)ARCHITECTURE\.md$/,
|
|
28
|
-
wireframes: /(^|\/)wireframes\/.+\.md$/,
|
|
29
25
|
design: /(^|\/)DESIGN\.md$/,
|
|
30
26
|
requirements: /(^|\/)REQUIREMENTS\.md$/,
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
const INDEX_NAME = 'index.md'
|
|
34
30
|
|
|
35
|
-
/** The
|
|
31
|
+
/** The doc type `resolveFolders` discovers, paired with the folder name it takes. */
|
|
36
32
|
const MULTI_DOC_TYPES: readonly { type: CanonicalDocType; name: string }[] = [
|
|
37
33
|
{ type: 'context', name: 'context' },
|
|
38
|
-
{ type: 'wireframes', name: 'wireframes' },
|
|
39
34
|
]
|
|
40
35
|
|
|
41
|
-
/** The
|
|
36
|
+
/** The two doc types that resolve to one file each, paired with `surfaceDir`'s entry name. */
|
|
42
37
|
const SINGLE_DOC_TYPES: readonly { type: CanonicalDocType; entry: string }[] = [
|
|
43
|
-
{ type: 'architecture', entry: 'ARCHITECTURE.md' },
|
|
44
38
|
{ type: 'design', entry: 'DESIGN.md' },
|
|
45
39
|
{ type: 'requirements', entry: 'REQUIREMENTS.md' },
|
|
46
40
|
]
|
|
@@ -388,11 +382,10 @@ function readSections(
|
|
|
388
382
|
/**
|
|
389
383
|
* Every sweep-mode section across the requested canonical doc types.
|
|
390
384
|
*
|
|
391
|
-
* `context`
|
|
385
|
+
* `context` resolves through `resolveFolders`, the same
|
|
392
386
|
* folder discovery `canon context audit` uses, so a domain split into a
|
|
393
|
-
* folder of its own is swept the same way it is audited. The
|
|
394
|
-
* single-file types resolve through `surfaceDir
|
|
395
|
-
* `architectureRel`'s own resolution.
|
|
387
|
+
* folder of its own is swept the same way it is audited. The two
|
|
388
|
+
* single-file types resolve through `surfaceDir`.
|
|
396
389
|
*/
|
|
397
390
|
export async function extractSweepSections(
|
|
398
391
|
root: string,
|
|
@@ -37,44 +37,17 @@ export interface PatternVerdict<V extends string> {
|
|
|
37
37
|
const NARRATION =
|
|
38
38
|
/moved (again|twice|on)|has since|at this branch|on `feat|Measured in PR|did not survive|the operator picked|picked arm|\barm \d|closed on|was retired|no longer|used to|\bround\b|a review pass|this pass/i
|
|
39
39
|
|
|
40
|
-
/**
|
|
41
|
-
* A source-file path inside prose, the shape of implementation detail landing
|
|
42
|
-
* on a surface that should describe layout and intent instead. Ported
|
|
43
|
-
* verbatim from `heuristic.py`.
|
|
44
|
-
*/
|
|
45
|
-
const MECHANISM_IN_WIREFRAME = /`[\w./-]+\.(tsx?|py|css|spec\.ts)`/
|
|
46
|
-
|
|
47
40
|
function narrationQuote(text: string): string | undefined {
|
|
48
41
|
return text.match(NARRATION)?.[0]
|
|
49
42
|
}
|
|
50
43
|
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
* `file` decides whether the wireframe-only MOVE test applies. A file argument
|
|
55
|
-
* rather than a boolean matches `run.ts`'s other call sites, which hold the
|
|
56
|
-
* path and not a pre-computed flag.
|
|
57
|
-
*/
|
|
58
|
-
export function diffPatternVerdict(
|
|
59
|
-
file: string,
|
|
60
|
-
added: string,
|
|
61
|
-
): PatternVerdict<DiffVerdict> {
|
|
44
|
+
/** Classifies one diff-mode chunk from its added text alone. */
|
|
45
|
+
export function diffPatternVerdict(added: string): PatternVerdict<DiffVerdict> {
|
|
62
46
|
const quote = narrationQuote(added)
|
|
63
47
|
if (quote !== undefined) {
|
|
64
48
|
return { verdict: 'HISTORY', quote, reason: 'narrates how this got here' }
|
|
65
49
|
}
|
|
66
50
|
|
|
67
|
-
if (file.includes('wireframes/')) {
|
|
68
|
-
const match = added.match(MECHANISM_IN_WIREFRAME)
|
|
69
|
-
if (match) {
|
|
70
|
-
return {
|
|
71
|
-
verdict: 'MOVE',
|
|
72
|
-
quote: match[0],
|
|
73
|
-
reason: 'names a source file, which is implementation detail',
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
51
|
return { verdict: 'KEEP', reason: 'no narration or wrong-surface pattern' }
|
|
79
52
|
}
|
|
80
53
|
|
|
@@ -87,7 +60,6 @@ export function diffPatternVerdict(
|
|
|
87
60
|
* regex layer follows it.
|
|
88
61
|
*/
|
|
89
62
|
export function sweepPatternVerdict(
|
|
90
|
-
file: string,
|
|
91
63
|
body: string,
|
|
92
64
|
): PatternVerdict<SweepVerdict> {
|
|
93
65
|
const quote = narrationQuote(body)
|
|
@@ -99,16 +71,5 @@ export function sweepPatternVerdict(
|
|
|
99
71
|
}
|
|
100
72
|
}
|
|
101
73
|
|
|
102
|
-
if (file.includes('wireframes/')) {
|
|
103
|
-
const match = body.match(MECHANISM_IN_WIREFRAME)
|
|
104
|
-
if (match) {
|
|
105
|
-
return {
|
|
106
|
-
verdict: 'MOVE',
|
|
107
|
-
quote: match[0],
|
|
108
|
-
reason: 'names a source file, which is implementation detail',
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
74
|
return { verdict: 'KEEP', reason: 'no narration or wrong-surface pattern' }
|
|
114
75
|
}
|
|
@@ -13,15 +13,13 @@ export const DIFF_SYSTEM_PROMPT = `You review one hunk just added to a project's
|
|
|
13
13
|
|
|
14
14
|
File types and what they hold:
|
|
15
15
|
- context/<domain>.md: one domain's structure, decisions (choice + the alternative that lost), gotchas. No history of how the domain got here, no change numbers, branch names, or dates attached to a change.
|
|
16
|
-
- ARCHITECTURE.md: cross-domain decisions only, each a few sentences: what was chosen, over what, why. A measurement or mechanism specific to one domain belongs in that domain's context entry. Loaded every session, so weight matters.
|
|
17
|
-
- wireframes/<surface>.md: layout sketches, reachable states, exact on-screen copy, interaction intent. Would the line still be true if the surface were rebuilt in another framework? Component names, test files, pixel constants, and mechanism belong in context.
|
|
18
16
|
- DESIGN.md: tokens and visual rules, current state only.
|
|
19
17
|
|
|
20
18
|
Verdicts (pick exactly one):
|
|
21
19
|
- KEEP: states current design, a rule, copy, a decision with its rejected alternative, or a live gotcha, on the right surface.
|
|
22
20
|
- REPLACE: restates a fact or figure the existing section already carries ("moved again", "now", "the count moved", a newer number appended after an older one). The old statement should be rewritten in place, not appended to.
|
|
23
21
|
- HISTORY: narrates how things got here: which branch/PR changed what, "closed on", "did not survive", review-pass stories, pick-by-pick rounds. The current state is what belongs; the trail goes to the PR.
|
|
24
|
-
- MOVE: correct content on the wrong surface (
|
|
22
|
+
- MOVE: correct content on the wrong surface (a rule written into a context entry, or a measured result written into the requirements record).
|
|
25
23
|
|
|
26
24
|
Return only JSON: {"verdict": "...", "quote": "<the shortest added phrase that decided it>", "reason": "<one sentence>"}
|
|
27
25
|
|
|
@@ -35,15 +33,13 @@ export const SWEEP_SYSTEM_PROMPT = `You review one whole section of a project's
|
|
|
35
33
|
|
|
36
34
|
File types and what they hold:
|
|
37
35
|
- context/<domain>.md: one domain's structure, decisions (choice + the alternative that lost), gotchas. No history of how the domain got here, no change numbers, branch names, or dates attached to a change.
|
|
38
|
-
- ARCHITECTURE.md: cross-domain decisions only, each a few sentences: what was chosen, over what, why. A measurement or mechanism specific to one domain belongs in that domain's context entry.
|
|
39
|
-
- wireframes/<surface>.md: layout, reachable states, exact on-screen copy, interaction intent. Would the line still be true if the surface were rebuilt in another framework? Component names, test files, and pixel constants belong in context.
|
|
40
36
|
- DESIGN.md: tokens and visual rules, current state only.
|
|
41
37
|
- REQUIREMENTS.md: problem, goals, non-goals, scope, constraints. Never measured results.
|
|
42
38
|
|
|
43
39
|
Verdicts (pick exactly one):
|
|
44
40
|
- KEEP: the section states the current design, rules, copy, or decisions once, on the right surface. A single commit anchor on a figure is fine.
|
|
45
41
|
- REWRITE: the section carries its own history: a figure followed by a later corrected figure, "superseded", "now", "moved", "no longer", "reverses the earlier reading", branch or PR narration, pick-by-pick rounds, a heading that narrates an event. The subject belongs here, but it must be restated as the current state.
|
|
46
|
-
- MOVE: the section, or most of it, belongs on another surface (results in requirements
|
|
42
|
+
- MOVE: the section, or most of it, belongs on another surface (results in requirements).
|
|
47
43
|
|
|
48
44
|
Decision checks, in order:
|
|
49
45
|
1. Judge what the text says, not how long it is. A long section that states current design once is KEEP.
|
|
@@ -245,7 +245,7 @@ async function modelVerdictFor<V extends string>(opts: {
|
|
|
245
245
|
* A finding's `verdict` takes the model's reading when the model ran and
|
|
246
246
|
* parsed, and the regex reading otherwise, since the groundwork measurements
|
|
247
247
|
* show the model catching what the regex layer structurally cannot
|
|
248
|
-
* (REPLACE
|
|
248
|
+
* (REPLACE and MOVE). Both readings stay on the finding
|
|
249
249
|
* regardless of which one decided, so a caller can see where they disagreed.
|
|
250
250
|
*/
|
|
251
251
|
export async function classifyDiff(
|
|
@@ -263,7 +263,7 @@ export async function classifyDiff(
|
|
|
263
263
|
|
|
264
264
|
const findings: DiffFinding[] = []
|
|
265
265
|
for (const chunk of extraction.chunks) {
|
|
266
|
-
const regex = withQuote(diffPatternVerdict(chunk.
|
|
266
|
+
const regex = withQuote(diffPatternVerdict(chunk.added))
|
|
267
267
|
const model = await modelVerdictFor({
|
|
268
268
|
plan,
|
|
269
269
|
client,
|
|
@@ -312,7 +312,7 @@ export async function classifySweep(
|
|
|
312
312
|
|
|
313
313
|
const findings: SweepFinding[] = []
|
|
314
314
|
for (const section of extraction.sections) {
|
|
315
|
-
const regex = withQuote(sweepPatternVerdict(section.
|
|
315
|
+
const regex = withQuote(sweepPatternVerdict(section.body))
|
|
316
316
|
const model = await modelVerdictFor({
|
|
317
317
|
plan,
|
|
318
318
|
client,
|
package/src/context/folders.ts
CHANGED
|
@@ -17,19 +17,14 @@ import { SURFACE_ROOTS } from '@/roots/surface'
|
|
|
17
17
|
* these names. A folder left off the list is never resolved, so a path into one
|
|
18
18
|
* goes stale silently rather than failing a push.
|
|
19
19
|
*/
|
|
20
|
-
export const DEFAULT_FOLDERS: readonly string[] = [
|
|
21
|
-
'context',
|
|
22
|
-
'diagrams',
|
|
23
|
-
'wireframes',
|
|
24
|
-
]
|
|
20
|
+
export const DEFAULT_FOLDERS: readonly string[] = ['context', 'diagrams']
|
|
25
21
|
|
|
26
22
|
/**
|
|
27
23
|
* The bases every folder in the default list is looked for under.
|
|
28
24
|
*
|
|
29
25
|
* `diagrams` is a session record and resolves under `RECORD_ROOTS`, while
|
|
30
|
-
* `context`
|
|
31
|
-
*
|
|
32
|
-
* folders on this list read from two different root lists. The base array is
|
|
26
|
+
* `context` is tracked and resolves under `SURFACE_ROOTS`, so two folders on
|
|
27
|
+
* this list read from two different root lists. The base array is
|
|
33
28
|
* their union rather than a per-name map, since a name resolving at the wrong
|
|
34
29
|
* root costs one extra `existsSync` and nothing else, where a map states the
|
|
35
30
|
* split a second time next to the one each resolver module already carries.
|
|
@@ -90,10 +85,10 @@ export interface AuditedFolder {
|
|
|
90
85
|
* Names the requested record-root folders that actually exist, which is the
|
|
91
86
|
* citation check's scope.
|
|
92
87
|
*
|
|
93
|
-
* A skill or seed pointing into
|
|
88
|
+
* A skill or seed pointing into an optional folder is a live instruction for
|
|
94
89
|
* a project that carries the folder and says nothing about one that does not.
|
|
95
|
-
* Checking a path into an absent folder would fail
|
|
96
|
-
*
|
|
90
|
+
* Checking a path into an absent folder would fail shipped references here for
|
|
91
|
+
* the sole reason that this repository does not carry it.
|
|
97
92
|
*
|
|
98
93
|
* A folder resolved at the project root is measured and stays out of this. The
|
|
99
94
|
* pattern the citation check builds spells the `.claude/` prefix, so admitting
|
|
@@ -172,7 +167,7 @@ function locate(
|
|
|
172
167
|
* beside `node_modules` and a build output.
|
|
173
168
|
*
|
|
174
169
|
* The project root is reached only when the caller opts in, so a target holding
|
|
175
|
-
* a root
|
|
170
|
+
* a root folder of its own name is not audited against a standard it never adopted by
|
|
176
171
|
* the mere act of running the command. `.claude/` still wins a name carried by
|
|
177
172
|
* both, and the scope line prints the resolved path so a caller reads which
|
|
178
173
|
* base was taken rather than inferring it.
|
package/src/context/gate.ts
CHANGED
|
@@ -1,61 +1,19 @@
|
|
|
1
1
|
import type { SectionFinding } from '@/context/audit'
|
|
2
2
|
import type { FolderDrift } from '@/context/index-drift'
|
|
3
|
-
import type { WireframeStatesReport } from '@/context/wireframe-states'
|
|
4
3
|
|
|
5
4
|
export interface GateInput {
|
|
6
5
|
/** Cited paths that resolved to nothing, which gate under either mode. */
|
|
7
6
|
readonly unresolvedCitations: number
|
|
8
|
-
/**
|
|
9
|
-
* Whether the architecture record is longer than the ceiling it derives for
|
|
10
|
-
* itself, which gates under either mode for the reason a citation does.
|
|
11
|
-
*
|
|
12
|
-
* False when the project carries no record and false under
|
|
13
|
-
* `--citations-only`, which never measures it. That mode runs one check by
|
|
14
|
-
* construction, so widening it here would gate on a reading it never took.
|
|
15
|
-
*/
|
|
16
|
-
readonly recordOverLength: boolean
|
|
17
|
-
/**
|
|
18
|
-
* Whether the record holds more decisions than the cap it states, which
|
|
19
|
-
* gates under the same two modes and is false in the same two cases.
|
|
20
|
-
*/
|
|
21
|
-
readonly recordOverCount: boolean
|
|
22
|
-
/**
|
|
23
|
-
* Whether a decision lacks the revisit sentence the record requires of
|
|
24
|
-
* every decision, which gates under the same two modes and is false in the
|
|
25
|
-
* same two cases, plus a record stating no such clause.
|
|
26
|
-
*/
|
|
27
|
-
readonly recordMissingRevisit: boolean
|
|
28
|
-
/**
|
|
29
|
-
* Whether a decision holds more words than the cap the record states, which
|
|
30
|
-
* gates under the same two modes and is false in the same two cases, plus a
|
|
31
|
-
* record stating no word cap.
|
|
32
|
-
*/
|
|
33
|
-
readonly recordOverWords: boolean
|
|
34
|
-
/** The same reading for the Risks section's bullet cap. */
|
|
35
|
-
readonly recordOverRisks: boolean
|
|
36
7
|
/**
|
|
37
8
|
* Whether the requirements record holds more words than the cap it states,
|
|
38
|
-
* which gates for the reason
|
|
9
|
+
* which gates under either mode for the reason a citation does. False when
|
|
10
|
+
* the project carries no record and false under `--citations-only`, which
|
|
11
|
+
* never measures it. That mode runs one check by construction, so widening
|
|
12
|
+
* it here would gate on a reading it never took.
|
|
39
13
|
*/
|
|
40
14
|
readonly requirementsOverWords: boolean
|
|
41
15
|
readonly sections: readonly SectionFinding[]
|
|
42
16
|
readonly drift: readonly FolderDrift[]
|
|
43
|
-
/**
|
|
44
|
-
* Every wireframe entry's states report, empty for a project carrying no
|
|
45
|
-
* `canon/wireframes/` folder. A states/evidence mismatch is a fact read off
|
|
46
|
-
* the file, the same standing the missing-section and index-drift findings
|
|
47
|
-
* already have, so it gates alongside them under the widened mode.
|
|
48
|
-
*
|
|
49
|
-
* A sketch beside existing evidence stays out of the gate on both modes.
|
|
50
|
-
* `sketchWithEvidence` reads the whole entry against whether any of its
|
|
51
|
-
* states has evidence, not the sketched layout against the evidence for
|
|
52
|
-
* that same layout, since the standard's `## States` table names states
|
|
53
|
-
* rather than layouts and the report has no narrower unit to match on. An
|
|
54
|
-
* entry with a captured default layout and a sketch for a breakpoint layout
|
|
55
|
-
* that is not built yet is conforming and still trips this reading, so the
|
|
56
|
-
* finding stays a judgment for a reader rather than a fact a push fails on.
|
|
57
|
-
*/
|
|
58
|
-
readonly wireframes: readonly WireframeStatesReport[]
|
|
59
17
|
/**
|
|
60
18
|
* Whether the caller asked for the widened gate. False leaves a missing
|
|
61
19
|
* section and a drifted index advisory, which is what the project-root stage
|
|
@@ -71,65 +29,27 @@ export function hasDrift(drift: readonly FolderDrift[]): boolean {
|
|
|
71
29
|
)
|
|
72
30
|
}
|
|
73
31
|
|
|
74
|
-
/** Whether any wireframe's States table disagrees with its evidence folders. */
|
|
75
|
-
export function hasStatesMismatch(
|
|
76
|
-
wireframes: readonly WireframeStatesReport[],
|
|
77
|
-
): boolean {
|
|
78
|
-
return wireframes.some(
|
|
79
|
-
(entry) =>
|
|
80
|
-
entry.missingFolders.length > 0 || entry.unlistedFolders.length > 0,
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** Whether any wireframe carries a sketch beside evidence that already exists. */
|
|
85
|
-
export function hasSketchWithEvidence(
|
|
86
|
-
wireframes: readonly WireframeStatesReport[],
|
|
87
|
-
): boolean {
|
|
88
|
-
return wireframes.some((entry) => entry.sketchWithEvidence)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
32
|
/**
|
|
92
33
|
* Whether the audit found something that should fail the caller.
|
|
93
34
|
*
|
|
94
35
|
* An unresolved citation is a broken pointer and gates unconditionally, and so
|
|
95
|
-
* does a record past its own
|
|
96
|
-
*
|
|
97
|
-
* own word cap: each record states its rules for itself, which makes those the
|
|
98
|
-
* measures here that are facts
|
|
99
|
-
* rather than thresholds a reader weighs. The findings `--gate` adds are
|
|
36
|
+
* does a requirements record past its own word cap: the record states its rule
|
|
37
|
+
* for itself, which makes it a fact rather than a threshold a reader weighs. The findings `--gate` adds are
|
|
100
38
|
* the ones answerable from the file itself: a required section it does not
|
|
101
|
-
* declare, an index disagreeing with its folder
|
|
102
|
-
* table
|
|
103
|
-
*
|
|
104
|
-
* existing evidence are judgments, so they stay out under both modes. The
|
|
105
|
-
* `wireframes` field's own doc states why the sketch finding is a judgment
|
|
106
|
-
* rather than a fact.
|
|
39
|
+
* declare, and an index disagreeing with its folder. Entry length, depth, bullet,
|
|
40
|
+
* table, provenance, and the record's claim coverage are judgments, so they
|
|
41
|
+
* stay out under both modes.
|
|
107
42
|
*/
|
|
108
43
|
export function isGating({
|
|
109
44
|
unresolvedCitations,
|
|
110
|
-
recordOverLength,
|
|
111
|
-
recordOverCount,
|
|
112
|
-
recordMissingRevisit,
|
|
113
|
-
recordOverWords,
|
|
114
|
-
recordOverRisks,
|
|
115
45
|
requirementsOverWords,
|
|
116
46
|
sections,
|
|
117
47
|
drift,
|
|
118
|
-
wireframes,
|
|
119
48
|
widened,
|
|
120
49
|
}: GateInput): boolean {
|
|
121
50
|
if (unresolvedCitations > 0) return true
|
|
122
|
-
if (
|
|
123
|
-
recordOverLength ||
|
|
124
|
-
recordOverCount ||
|
|
125
|
-
recordMissingRevisit ||
|
|
126
|
-
recordOverWords ||
|
|
127
|
-
recordOverRisks ||
|
|
128
|
-
requirementsOverWords
|
|
129
|
-
) {
|
|
130
|
-
return true
|
|
131
|
-
}
|
|
51
|
+
if (requirementsOverWords) return true
|
|
132
52
|
if (!widened) return false
|
|
133
53
|
|
|
134
|
-
return sections.length > 0 || hasDrift(drift)
|
|
54
|
+
return sections.length > 0 || hasDrift(drift)
|
|
135
55
|
}
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import { join, relative } from 'node:path'
|
|
3
|
-
import { wordCount } from '@/context/architecture'
|
|
4
3
|
import { bodyLines } from '@/markdown/scan'
|
|
5
4
|
import { surfaceDir } from '@/roots/surface'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* The record this measures, relative to `root`, resolved at either surface
|
|
9
|
-
* root
|
|
8
|
+
* root, since a project that has moved holds it under either.
|
|
10
9
|
*/
|
|
11
10
|
export function requirementsRel(root: string): string {
|
|
12
11
|
return relative(root, surfaceDir(root, 'REQUIREMENTS.md'))
|
|
13
12
|
}
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Counts whitespace-delimited tokens, the unit the record's word cap is stated
|
|
16
|
+
* in. A code span counts as the tokens it holds, so a line citing a long path
|
|
17
|
+
* pays for it the way a reader does. A caller gating on the count hands in
|
|
18
|
+
* prose with fenced lines already dropped.
|
|
19
|
+
*/
|
|
20
|
+
export function wordCount(text: string): number {
|
|
21
|
+
return text.match(/\S+/g)?.length ?? 0
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
export interface RequirementsReport {
|
|
16
25
|
readonly rel: string
|
|
17
26
|
/** The whole record's word count, frontmatter left out. */
|
|
@@ -43,8 +52,8 @@ function isMissing(error: unknown): boolean {
|
|
|
43
52
|
/**
|
|
44
53
|
* Measures the record, or reports nothing when the project carries none.
|
|
45
54
|
*
|
|
46
|
-
* Absent rather than zeroed,
|
|
47
|
-
* record present and unreadable propagates
|
|
55
|
+
* Absent rather than zeroed, so a project with no record is never told it holds an
|
|
56
|
+
* empty one, and a record present and unreadable propagates.
|
|
48
57
|
*/
|
|
49
58
|
export async function measureRequirements(
|
|
50
59
|
root: string,
|
package/src/counts/scan.ts
CHANGED
|
@@ -35,8 +35,8 @@ export type CountsReport =
|
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* A calendar date, which reads a sentence as a historical record rather than
|
|
38
|
-
* a live claim about the tree.
|
|
39
|
-
*
|
|
38
|
+
* a live claim about the tree. The context entries
|
|
39
|
+
* carry a figure this way deliberately, and every one of them stays
|
|
40
40
|
* correct forever, so a sentence carrying one is read past rather than
|
|
41
41
|
* matched.
|
|
42
42
|
*/
|
|
@@ -142,7 +142,7 @@ const QUANTIFIERS = ['all']
|
|
|
142
142
|
* match at all. No syntactic rule tells a qualifier that narrows a catalog
|
|
143
143
|
* from one that only restates it, and the sentence was true when written, so
|
|
144
144
|
* the fix was not a narrower matcher: the clause was dated as a past state,
|
|
145
|
-
* the way
|
|
145
|
+
* the way a context entry dates its own figures, which is the class
|
|
146
146
|
* the date exclusion below already reads past.
|
|
147
147
|
*/
|
|
148
148
|
const ARTICLES = ['the', 'a', 'an']
|
package/src/design/components.ts
CHANGED
|
@@ -250,8 +250,8 @@ const TEACH_CHROME: Component = {
|
|
|
250
250
|
'navigation shared by every teach page. Recovered from two gitignored',
|
|
251
251
|
'course.css files that predate a regression that dropped this layer from the',
|
|
252
252
|
"generator, and rewritten onto this module's tokens rather than the",
|
|
253
|
-
'incompatible palette they carried. See canon/
|
|
254
|
-
'the shape.',
|
|
253
|
+
'incompatible palette they carried. See canon/context/features/teach/chrome.md',
|
|
254
|
+
'for the shape.',
|
|
255
255
|
].join('\n '),
|
|
256
256
|
reads: [
|
|
257
257
|
'--color-background',
|
package/src/feedback/body.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const SLUG_FALLBACK = 'general'
|
|
2
|
-
const SLUG_MAX_LENGTH = 40
|
|
3
1
|
const TITLE_MAX_LENGTH = 72
|
|
4
2
|
|
|
5
3
|
/**
|
|
@@ -79,16 +77,6 @@ function surfaceField(body: string): string | undefined {
|
|
|
79
77
|
return readField(body, 'Surface')?.split('\n')[0]?.trim()
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
export function deriveSlug(body: string): string {
|
|
83
|
-
const slug = (surfaceField(body) ?? '')
|
|
84
|
-
.toLowerCase()
|
|
85
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
86
|
-
.replace(/^-+|-+$/g, '')
|
|
87
|
-
.slice(0, SLUG_MAX_LENGTH)
|
|
88
|
-
.replace(/-+$/g, '')
|
|
89
|
-
return slug || SLUG_FALLBACK
|
|
90
|
-
}
|
|
91
|
-
|
|
92
80
|
/**
|
|
93
81
|
* Each label must exist on the toolkit repository, because `gh issue create`
|
|
94
82
|
* refuses the whole issue on an unknown label rather than dropping it.
|
package/src/gate/measures.ts
CHANGED
|
@@ -7,14 +7,6 @@ import {
|
|
|
7
7
|
type ClientCommand,
|
|
8
8
|
clientCommandCitationsIn,
|
|
9
9
|
} from '@/gate/client-commands'
|
|
10
|
-
import {
|
|
11
|
-
isOverCount,
|
|
12
|
-
isOverLength,
|
|
13
|
-
isOverRisks,
|
|
14
|
-
measureArchitecture,
|
|
15
|
-
missingRevisit,
|
|
16
|
-
overWords,
|
|
17
|
-
} from '@/context/architecture'
|
|
18
10
|
import { isOverWordCap, measureRequirements } from '@/context/requirements'
|
|
19
11
|
import {
|
|
20
12
|
auditSkills,
|
|
@@ -253,62 +245,19 @@ function citedPaths(record: { paths?: unknown } | undefined): string[] {
|
|
|
253
245
|
}
|
|
254
246
|
|
|
255
247
|
/**
|
|
256
|
-
* The
|
|
257
|
-
* architecture record carries five: the line ceiling its allowances derive,
|
|
258
|
-
* the entry cap, the revisit sentence closing each decision, the words a
|
|
259
|
-
* decision may hold, and the bullets its Risks section may hold. The
|
|
260
|
-
* requirements record carries one, its own word count.
|
|
248
|
+
* The requirements record against the word cap it states for itself.
|
|
261
249
|
*
|
|
262
250
|
* Read in-process rather than through `context audit`, whose one gating stage
|
|
263
|
-
* here runs `--citations-only` and never opens
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
* passes, since each rule belongs to the record rather than to the toolkit.
|
|
251
|
+
* here runs `--citations-only` and never opens the record. A project carrying
|
|
252
|
+
* no record, or a record stating no cap, passes, since the rule belongs to the
|
|
253
|
+
* record rather than to the toolkit.
|
|
267
254
|
*/
|
|
268
255
|
export const canonicalRecords: Measure = async (ctx) => {
|
|
269
|
-
const
|
|
270
|
-
measureArchitecture(ctx.root),
|
|
271
|
-
measureRequirements(ctx.root),
|
|
272
|
-
])
|
|
256
|
+
const requirements = await measureRequirements(ctx.root)
|
|
273
257
|
|
|
274
258
|
const failures: string[] = []
|
|
275
259
|
const emissions: Emission[] = []
|
|
276
260
|
|
|
277
|
-
if (report === undefined) {
|
|
278
|
-
emissions.push(info('No architecture record to measure'))
|
|
279
|
-
} else {
|
|
280
|
-
const decisions = report.decisions.length
|
|
281
|
-
const lackingRevisit = missingRevisit(report)
|
|
282
|
-
const longDecisions = overWords(report)
|
|
283
|
-
failures.push(
|
|
284
|
-
...[
|
|
285
|
-
isOverCount(report) &&
|
|
286
|
-
`${decisions} decisions against a cap of ${report.entryCap}. Merge two or retire one in ${report.rel}, never compress.`,
|
|
287
|
-
isOverLength(report) &&
|
|
288
|
-
`${report.lines} lines against a ceiling of ${report.ceiling} in ${report.rel}.`,
|
|
289
|
-
lackingRevisit.length > 0 &&
|
|
290
|
-
`No revisit sentence in ${lackingRevisit.map((heading) => `"${heading}"`).join(', ')}. Close each with one opening "Revisit when" in ${report.rel}.`,
|
|
291
|
-
longDecisions.length > 0 &&
|
|
292
|
-
`${longDecisions.map((entry) => `"${entry.heading}" (${entry.words})`).join(', ')} past ${report.wordCap} words a decision in ${report.rel}. Cut the reasoning to the trade, never split one decision across two headings.`,
|
|
293
|
-
isOverRisks(report) &&
|
|
294
|
-
`${report.risksBullets} risk bullets against a cap of ${report.riskCap} in ${report.rel}. Drop what is no longer open.`,
|
|
295
|
-
].filter((failure): failure is string => typeof failure === 'string'),
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
const cap =
|
|
299
|
-
report.entryCap === undefined
|
|
300
|
-
? 'no entry cap stated'
|
|
301
|
-
: `a cap of ${report.entryCap}`
|
|
302
|
-
emissions.push(info(`${decisions} decisions against ${cap}`))
|
|
303
|
-
if (report.riskCap !== undefined && report.risksBullets === undefined) {
|
|
304
|
-
emissions.push(
|
|
305
|
-
info(
|
|
306
|
-
`No Risks section to count against a cap of ${report.riskCap} in ${report.rel}`,
|
|
307
|
-
),
|
|
308
|
-
)
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
261
|
if (requirements === undefined) {
|
|
313
262
|
emissions.push(info('No requirements record to measure'))
|
|
314
263
|
} else if (isOverWordCap(requirements)) {
|
|
@@ -415,7 +364,7 @@ export const skillProvenance: Measure = async (ctx) => {
|
|
|
415
364
|
/**
|
|
416
365
|
* Every listed practice skill against the closing sections, and every skill on
|
|
417
366
|
* the wider ledger list against the ledger, both of which
|
|
418
|
-
* `
|
|
367
|
+
* `claude/skills/create-skill/references/skill-practice.md` requires.
|
|
419
368
|
*
|
|
420
369
|
* Read in-process for the reason `skillProvenance` is, so the verb keeps its
|
|
421
370
|
* missing-requirement-only exit. The list names shipped folders alone, so a
|
package/src/gate/stages.ts
CHANGED
|
@@ -110,7 +110,6 @@ export const TEST_CORPORA_PATTERNS = [
|
|
|
110
110
|
'^governance/rules/',
|
|
111
111
|
'^\\.claude/hooks/',
|
|
112
112
|
'^tooling/claude/seeds/\\.claude/hooks/',
|
|
113
|
-
'^standards/markdown\\.md$',
|
|
114
113
|
'^tooling/base/reference\\.md$',
|
|
115
114
|
'^tooling/web/configs/scripts/worktree-port\\.sh$',
|
|
116
115
|
]
|