@erclx/canon 5.32.0 → 5.34.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/REQUIREMENT.md +1 -2
- package/claude/skills/api-design/SKILL.md +2 -3
- package/claude/skills/api-design/references/adopted.md +1 -1
- package/claude/skills/auto-ship/SKILL.md +1 -1
- package/claude/skills/auto-ship/references/worktree-name.md +1 -1
- package/claude/skills/backlog-triage/REQUIREMENT.md +2 -2
- package/claude/skills/backlog-triage/SKILL.md +1 -1
- package/claude/skills/canon-cli/REQUIREMENT.md +16 -13
- package/claude/skills/canon-cli/SKILL.md +75 -32
- package/claude/skills/canon-feedback/REQUIREMENT.md +1 -0
- package/claude/skills/canon-feedback/SKILL.md +11 -29
- package/claude/skills/canon-feedback/references/template.md +53 -0
- package/claude/skills/{canvas → canvas-board}/REQUIREMENT.md +2 -2
- package/claude/skills/{canvas → canvas-board}/SKILL.md +6 -3
- package/claude/skills/{canvas → canvas-board}/references/canvas.md +26 -3
- package/{standards → claude/skills/canvas-board/references}/design.md +11 -2
- package/claude/skills/code-craft/REQUIREMENT.md +1 -1
- package/claude/skills/code-craft/SKILL.md +0 -1
- package/claude/skills/context-fold/REQUIREMENT.md +25 -33
- package/claude/skills/context-fold/SKILL.md +25 -70
- package/claude/skills/context-fold/references/classify.md +3 -3
- package/claude/skills/context-fold/references/completion-report.md +4 -4
- package/claude/skills/context-fold/references/context-refresh.md +5 -5
- package/{standards → claude/skills/context-fold/references}/context.md +16 -5
- package/claude/skills/context-fold/references/unusable-baseline.md +3 -5
- package/claude/skills/create-rule/SKILL.md +3 -3
- package/{standards → claude/skills/create-rule/references}/rule.md +15 -6
- package/claude/skills/create-skill/SKILL.md +2 -2
- package/{standards → claude/skills/create-skill/references}/skill.md +18 -15
- package/claude/skills/design-taste/REQUIREMENT.md +3 -3
- package/claude/skills/design-taste/SKILL.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
- package/claude/skills/docs-sync/SKILL.md +3 -3
- package/{standards → claude/skills/docs-sync/references}/docs.md +11 -0
- package/{standards → claude/skills/docs-sync/references}/readme.md +9 -2
- package/claude/skills/draft-and-pick/SKILL.md +5 -5
- package/claude/skills/draft-doc/SKILL.md +6 -6
- package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
- package/claude/skills/draft-figure/SKILL.md +2 -2
- package/claude/skills/draft-figure/references/hand-drawn.md +1 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +1 -1
- package/claude/skills/draft-identity/REQUIREMENT.md +2 -2
- package/claude/skills/draft-identity/SKILL.md +2 -2
- package/claude/skills/draft-ready/SKILL.md +1 -1
- package/claude/skills/git-branch/SKILL.md +1 -1
- package/{standards → claude/skills/git-branch/references}/branch.md +1 -1
- package/claude/skills/git-commit/SKILL.md +2 -2
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-issue/SKILL.md +1 -1
- package/claude/skills/git-issue/references/issue.md +4 -1
- package/claude/skills/git-pr/SKILL.md +13 -13
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +38 -14
- package/claude/skills/git-pr/references/labels.md +5 -1
- package/{standards → claude/skills/git-pr/references}/pr.md +19 -9
- package/{standards → claude/skills/git-pr/references}/publish.md +4 -2
- package/claude/skills/git-pr/references/task-number.md +1 -1
- package/claude/skills/git-ship/SKILL.md +15 -14
- package/claude/skills/git-split/SKILL.md +3 -3
- package/claude/skills/git-stage/SKILL.md +1 -1
- package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
- package/claude/skills/review-address/SKILL.md +1 -1
- package/claude/skills/review-address/references/post-review-findings.md +1 -1
- package/claude/skills/review-craft/references/ui.md +1 -1
- package/claude/skills/review-pr/REQUIREMENT.md +1 -1
- package/claude/skills/review-pr/SKILL.md +3 -3
- package/claude/skills/review-pr/references/body-variants.md +2 -2
- package/claude/skills/review-pr/references/key-changes.md +3 -3
- package/claude/skills/review-pr/references/post.md +4 -2
- package/claude/skills/review-ui/REQUIREMENT.md +1 -1
- package/claude/skills/review-ui/SKILL.md +8 -6
- package/claude/skills/review-ui/references/driving.md +8 -8
- package/claude/skills/review-ui/references/post.md +53 -17
- package/claude/skills/role-orchestrator/REQUIREMENT.md +3 -0
- package/claude/skills/role-orchestrator/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +8 -5
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +32 -1
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +3 -0
- package/claude/skills/role-planner/REQUIREMENT.md +2 -1
- package/claude/skills/role-planner/SKILL.md +13 -2
- package/claude/skills/role-reviewer/SKILL.md +1 -1
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +9 -1
- package/claude/skills/session-map/SKILL.md +1 -1
- package/claude/skills/session-resume/REQUIREMENT.md +2 -2
- package/claude/skills/session-worktree/SKILL.md +5 -5
- package/claude/skills/target-setup/SKILL.md +10 -4
- package/claude/skills/target-setup/references/detect.md +20 -3
- package/claude/skills/task-board/REQUIREMENT.md +7 -12
- package/claude/skills/task-board/SKILL.md +5 -17
- package/claude/skills/task-board/references/tasks.md +2 -2
- package/claude/skills/task-complete/REQUIREMENT.md +47 -0
- package/claude/skills/task-complete/SKILL.md +86 -0
- package/claude/skills/{task-board → task-complete}/references/archive.md +4 -4
- package/claude/skills/{context-fold → task-complete}/references/receipt-sweep.md +5 -5
- package/claude/skills/task-complete/references/unusable-baseline.md +19 -0
- package/claude/skills/teach-workspace/REQUIREMENT.md +6 -2
- package/claude/skills/teach-workspace/SKILL.md +8 -4
- package/claude/skills/teach-workspace/references/lesson-craft.md +1 -1
- package/claude/skills/{context-fold/references/promoted-pages.md → teach-workspace/references/promotion-fold.md} +3 -3
- package/claude/skills/teach-workspace/references/promotion.md +3 -3
- package/claude/skills/test-craft/REQUIREMENT.md +2 -3
- package/claude/skills/test-craft/SKILL.md +15 -3
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/ux-audit/SKILL.md +1 -1
- package/claude/skills/ux-measure/SKILL.md +1 -1
- package/docs/agents/canvas.md +6 -2
- package/docs/agents/commands.md +4 -3
- package/docs/agents/context-audit-checks.md +4 -4
- package/docs/agents/gov-detect.md +47 -0
- package/docs/agents/index.md +7 -4
- package/docs/agents/indexes.md +1 -1
- package/docs/agents/install-and-sync.md +10 -11
- package/docs/agents/key-changes.md +5 -5
- package/docs/agents/label-coverage.md +11 -0
- package/docs/agents/migrate.md +1 -1
- package/docs/agents/pr-evidence-layout.md +70 -0
- package/docs/agents/pr-evidence.md +8 -9
- package/docs/agents/pr-frames.md +7 -2
- package/docs/agents/pr-lift.md +132 -0
- package/docs/agents/records-push.md +2 -2
- package/docs/agents/records-stale.md +12 -47
- package/docs/agents/records-validate.md +3 -7
- package/docs/agents/records.md +5 -27
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/sandbox.md +4 -4
- package/docs/agents/scripting.md +2 -1
- package/docs/agents/skills-audit.md +1 -1
- package/docs/agents/tasks-plans.md +2 -2
- package/docs/agents/tasks.md +2 -2
- package/docs/target/migrations.md +10 -2
- package/docs/target/projects.md +4 -4
- package/docs/target/sync.md +1 -1
- package/docs/workflow/operating-model.md +2 -2
- package/docs/workflow/parallel-features.md +7 -7
- package/docs/workflow/skill-map-on-request.md +9 -9
- package/docs/workflow/skill-map.md +12 -11
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/detect.toml +201 -0
- package/governance/renames.toml +0 -11
- package/governance/rules/canon/context.md +13 -0
- package/governance/rules/claude/skill.md +17 -0
- package/governance/rules/code/000-code.md +1 -13
- package/governance/rules/code/010-testing.md +2 -30
- package/governance/rules/ui/400-ui.md +1 -1
- package/governance/rules/ui/480-canvas.md +13 -0
- package/governance/stacks/base.toml +2 -4
- package/package.json +4 -4
- package/scripts/core/install-check.sh +3 -3
- package/scripts/core/regen-hero.ts +0 -6
- package/scripts/lib/ui.sh +0 -168
- package/src/audits/catalog.ts +0 -1
- package/src/canvas/arrange.ts +66 -0
- package/src/canvas/capture.ts +20 -6
- package/src/canvas/content.ts +39 -0
- package/src/canvas/fit.ts +238 -0
- package/src/canvas/tokens.ts +28 -10
- package/src/capture/frame-values.ts +2 -32
- package/src/claude/cases/misc.ts +1 -1
- package/src/claude/cases/setup.ts +4 -0
- package/src/claude/cases/workflow.ts +6 -1
- package/src/claude/seeds.ts +1 -1
- package/src/claude/skills-audit.ts +2 -2
- package/src/cli/help.ts +3 -1
- package/src/cli/ui.ts +2 -3
- package/src/commands/canvas.ts +179 -1
- package/src/commands/claude.ts +1 -1
- package/src/commands/gov.ts +146 -16
- package/src/commands/labels.ts +326 -7
- package/src/commands/migrate.ts +6 -1
- package/src/commands/pr.ts +377 -2
- package/src/commands/records.ts +13 -399
- package/src/commands/sandbox.ts +3 -6
- package/src/commands/tasks.ts +3 -3
- package/src/context/audit.ts +5 -5
- package/src/context/folders.ts +1 -1
- package/src/design/budget.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/regen.ts +1 -1
- package/src/design/render.ts +1 -1
- package/src/feedback/body.ts +26 -5
- package/src/gate/measures.ts +59 -45
- package/src/gate/sequencer.ts +56 -1
- package/src/gate/stages.ts +4 -11
- package/src/gov/detect.ts +301 -0
- package/src/gov/install.ts +2 -3
- package/src/gov/list.ts +23 -2
- package/src/gov/stacks.ts +10 -1
- package/src/hooks/post-merge.ts +1 -1
- package/src/labels/apply.ts +39 -0
- package/src/labels/format.ts +3 -3
- package/src/labels/phase.ts +3 -3
- package/src/labels/sections.ts +43 -0
- package/src/migrate/skill-names.ts +20 -1
- package/src/pr/evidence.ts +218 -45
- package/src/pr/frames.ts +23 -3
- package/src/pr/lift.ts +418 -0
- package/src/pr/paths.ts +4 -4
- package/src/pr/rest.ts +3 -0
- package/src/pr/review-scope.ts +76 -0
- package/src/records/backup.ts +16 -6
- package/src/records/stale-canonical.ts +31 -1
- package/src/records/validate.ts +2 -188
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/coverage.ts +2 -6
- package/src/sandbox/equivalence.ts +19 -51
- package/src/sandbox/expect.ts +4 -4
- package/src/sandbox/provision.ts +13 -36
- package/src/sandbox/scenario.ts +26 -48
- package/src/sandbox/tree.ts +2 -6
- package/src/standards/read.ts +14 -1
- package/src/sync/git.ts +1 -1
- package/src/tasks/archive.ts +5 -5
- package/src/tasks/branch.ts +3 -3
- package/src/tasks/label.ts +1 -1
- package/src/tasks/record.ts +2 -2
- package/src/tasks/validate.ts +1 -1
- package/standards/index.md +0 -13
- package/standards/standard.md +1 -7
- package/tooling/base/reference.md +1 -1
- package/tooling/base/seeds/.github/pull_request_template.md +2 -2
- package/tooling/claude/reference.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +9 -1
- package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +171 -0
- package/tooling/claude/seeds/.claude/settings.json +9 -0
- package/governance/rules/standards/context.md +0 -14
- package/governance/rules/standards/design.md +0 -12
- package/governance/rules/standards/readme.md +0 -12
- package/governance/rules/standards/rule.md +0 -13
- package/governance/rules/standards/skill.md +0 -21
- package/governance/rules/standards/standard.md +0 -13
- package/scripts/config.sh +0 -11
- package/scripts/lib/gov.sh +0 -14
- package/scripts/lib/sandbox-fixtures.sh +0 -191
- package/scripts/lib/sandbox-git.sh +0 -125
- package/scripts/lib/sandbox-path.sh +0 -50
- package/scripts/sandbox-hook.sh +0 -99
- package/src/gov/standard-rules.ts +0 -179
- package/src/records/migrate.ts +0 -78
- package/src/records/stale.ts +0 -243
- package/src/sandbox/hooks.ts +0 -128
- /package/{standards → claude/skills/draft-figure/references}/figures.md +0 -0
- /package/{standards → claude/skills/git-branch/references}/slug.md +0 -0
- /package/{standards → claude/skills/git-commit/references}/commit.md +0 -0
- /package/{standards → claude/skills/git-commit/references}/versioning.md +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Rule detection
|
|
3
|
+
description: Proposing opt-in governance rules from a target's dependencies and paths, the evidence file the verb reads, the record it emits, and its exit codes
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rule detection
|
|
7
|
+
|
|
8
|
+
`canon gov detect` proposes the opt-in governance rules a target's evidence points at, and writes nothing. A rule no stack names reaches a project only through this verb, which `canon:target-setup` calls before it previews an install.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
canon gov detect
|
|
12
|
+
canon gov detect ../my-app --stack node --json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
| Option | Behavior |
|
|
16
|
+
| ----------------- | ------------------------------------------------ |
|
|
17
|
+
| `--stack <stack>` | Leave out every rule this stack already resolves |
|
|
18
|
+
| `--json` | Emit the record on stdout instead of the frame |
|
|
19
|
+
|
|
20
|
+
## Evidence
|
|
21
|
+
|
|
22
|
+
Each opt-in rule keeps a table in the toolkit's `governance/detect.toml`, keyed by rule basename. Its `deps` are package names, read from `package.json` (`dependencies` and `devDependencies`), `pyproject.toml`, `go.mod`, and `composer.json`. Its `files` are globs matched against the target's git-listed paths and against each folder on those paths, so `.github/workflows` matches a folder holding a workflow. A glob with no wildcard is also tested on disk, which is how `.canon/canvas` matches in a target that gitignores `.canon/`.
|
|
23
|
+
|
|
24
|
+
Both reads stop at depth two, which reaches a service folder and a workspace package under `packages/<name>/`. Outside git the verb walks the directory to the same depth and skips `.git`, `node_modules`, `vendor`, and `.venv`. A manifest that does not parse contributes nothing.
|
|
25
|
+
|
|
26
|
+
## Record
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"target": "/abs/path/my-app",
|
|
31
|
+
"stack": "node",
|
|
32
|
+
"proposals": [
|
|
33
|
+
{
|
|
34
|
+
"rule": "200-react",
|
|
35
|
+
"evidence": [{ "kind": "dep", "match": "react", "path": "package.json" }]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`kind` is `dep` for a dependency, with `path` naming the manifest that declares it, or `file` for a glob, with `path` naming what it matched. `stack` is null when no `--stack` was passed.
|
|
42
|
+
|
|
43
|
+
## Exit codes
|
|
44
|
+
|
|
45
|
+
The verb exits 0 on every readable target, including one with no evidence, which returns an empty `proposals` array. A target that does not exist and a `--stack` that does not resolve each exit 1 with the reason on stderr.
|
|
46
|
+
|
|
47
|
+
Install what the operator kept with `canon gov install --add <rules> <target>`, which needs no stack.
|
package/docs/agents/index.md
CHANGED
|
@@ -9,7 +9,7 @@ category: Agent surface
|
|
|
9
9
|
CLI catalog and invocation rules for agents, split by command domain. Start with overview.
|
|
10
10
|
|
|
11
11
|
- [Audits](audits.md): Running every health check as one set, what the single verdict means, the exit code each outcome takes, the retained baseline and the delta it reports, and which corpora are kept out of the record
|
|
12
|
-
- [Canvas](canvas.md): The canvas server, its content format, and the verbs that list, arrange, select, edit, mark, and capture frames
|
|
12
|
+
- [Canvas](canvas.md): The canvas server, its content format, and the verbs that list, arrange, fit, select, edit, mark, and capture frames
|
|
13
13
|
- [Capture](capture.md): Rendering HTML sources to PNG, what the command asserts about fonts, and why the selector has no default
|
|
14
14
|
- [Census](census.md): Tracked-plus-untracked file count, a breakdown by extension, and a line total that skips whatever reads as binary
|
|
15
15
|
- [Command catalog](commands.md): Every top-level command with its purpose, each domain's subcommands and the page describing them, the browser commands, and the version skew report
|
|
@@ -23,27 +23,30 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
23
23
|
- [Drift surfaces](drift-surfaces.md): The seven sections canon sync --check reports beside the per-domain scan, being seeds, superseded artifacts, unmigrated domains, surfaces at the old root, new rules and skills, and the reverse walk, with the managed-target gate and what counts toward the exit code
|
|
24
24
|
- [Driver](driver.md): Walking a page through named interactions, the probe catalog and the false finding each one carries, why viewport heights are never defaulted, and what each refusal reports
|
|
25
25
|
- [Merge gate](gate.md): Running the gate this repository verifies a branch with, what the stage table holds and what stays a script, how the changed set scopes three stages, and why a stage that cannot read its input reports rather than passing
|
|
26
|
+
- [Rule detection](gov-detect.md): Proposing opt-in governance rules from a target's dependencies and paths, the evidence file the verb reads, the record it emits, and its exit codes
|
|
26
27
|
- [Hooks](hooks.md): Running the post-merge steps through one verb, the order and the child call behind each, the root and working directory each step reads, the skip switches, and the line each record maps to
|
|
27
28
|
- [Indexes](indexes.md): Flags, exit codes, and JSON shape for canon indexes regen and canon indexes list, plus when regen auto-stages what it rewrote
|
|
28
29
|
- [Install and sync](install-and-sync.md): What each install and sync verb writes, refuses, or leaves alone, and how drift is attributed in a target project
|
|
29
30
|
- [Intake](intake.md): Reading intake folder counts and items, the three read states an item can be in, landing a batch of selections in one cluster, the refusal reasons, and why a call is scoped to one file
|
|
30
|
-
- [Key
|
|
31
|
+
- [Key changes bijection](key-changes.md): Comparing the files a pull request body's Key changes names against its own diff, the two directions and the split inside each that decides what is worth raising, the span rules the extractor was measured into, and the three refusals that separate a clean pass from a read that produced nothing
|
|
31
32
|
- [Label coverage](label-coverage.md): Reading a changed set against the pull request label map, the two tables it matches, how a gap is separated from a decision, and why an absent map is an answer
|
|
32
33
|
- [Markdown audit weight](markdown-audit-weight.md): The structural half of the markdown audit, being bullet and paragraph weight, run depth, the two cadence numbers, and the length ceiling, with the samples behind each checkpoint and why none of them gates
|
|
33
34
|
- [Markdown audit](markdown-audit.md): Running the audit over any markdown path, where its bans and checkpoints are read from, what each check reports, and why the ban half gates while the structural half reports
|
|
34
35
|
- [Migrate](migrate.md): What each canon migrate verb moves and rewrites, what it refuses, the markers that keep an old spelling, and the idempotence check a second run gives
|
|
35
36
|
- [Output shape](output-shape.md): Two framed shapes every command renders into, how JSON and --names modes keep stdout clean, and the exit discipline that lets piped output drain
|
|
36
37
|
- [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
|
|
38
|
+
- [The pull request evidence layout](pr-evidence-layout.md): How canon pr evidence groups screenshots into one block per view with a row per width and a column per theme, when a base column appears, where a name outside the form lands, how the commit line links, and when the blocks open
|
|
37
39
|
- [The pull request evidence comparison](pr-evidence.md): What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, what the --check read reports as owed, and why the comparison anchors at the merge base rather than the previous push
|
|
38
40
|
- [The pull request frame store](pr-frames.md): How canon pr frames pushes a UI review frame to a never-merged branch through the GitHub API and returns a branch-path link, which ref it writes, the pass segment that keeps an earlier image fixed, the refusal reasons it names, and how --drop and --prune rewrite the branch so a dropped frame leaves history
|
|
41
|
+
- [The pull request draft lift](pr-lift.md): How canon pr lift removes the draft mark once the reviews, evidence, standing, and CI all read clear at the head, the gate order and what each reads, the wait on a pending run, the re-read before the write, the refusal reasons it names, and what --check reports
|
|
39
42
|
- [The pull request local preview](pr-local.md): How canon pr local finds the server a worktree is running, why a server in another worktree is never reported, the refusal reasons it names, and how a close workflow drops the address line with --remove
|
|
40
43
|
- [The pull request preview deploy](pr-preview.md): How canon pr preview finds a fenced Cloudflare Pages deploy, refuses a branch its push filter does not serve, dispatches it on a pull request's branch, reads the alias the run prints, the refusal reasons it names, and why an unfenced deploy is refused before anything runs
|
|
41
44
|
- [Head-sensitive pull request reads](pr-reads.md): Resolving a branch tip from the remote rather than from the pull request object, reading what a review pass covered off its own marker rather than off GitHub's submission stamps, why an empty run list is not a pass, the refusal reasons each verb names, and what the remote read costs
|
|
42
45
|
- [The pull request checklist tick](pr-tick.md): How canon pr tick marks the checklist boxes a UI pass drove, the stamp that names the commit each passed at, why a render at a newer head clears a tick, the refusal reasons it names, and why a taste box is never ticked
|
|
43
46
|
- [Records push](records-push.md): Backing the record folders to a private remote and restoring them, which folders the payload carries, the one-time setup, the refusal reasons, and the hook that runs the push
|
|
44
|
-
- [Records stale](records-stale.md):
|
|
47
|
+
- [Records stale](records-stale.md): Counting the releases since the requirements record was last reviewed, where the review date is read from, and the exit codes and refusals
|
|
45
48
|
- [Records validate](records-validate.md): Validating the session records and the standards corpus, the per-kind checks, which root each kind defaults to, the exit codes, and the refusal reasons
|
|
46
|
-
- [Records](records.md): The two roots a record folder resolves at,
|
|
49
|
+
- [Records](records.md): The two roots a record folder resolves at, claiming the ordinal intake and groundwork share, reading each folder's size and growth, pruning stale scratch, and where validation, the canonical review count, and the private-remote backup are described
|
|
47
50
|
- [Restated instructions](restated.md): Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
|
|
48
51
|
- [Routing report](routing.md): Reading per CLAUDE.md section how many bullets name a path, what counts as naming one, when a rule counts as covering it, the two refusals, and why the verb reports rather than gates
|
|
49
52
|
- [Rule citations](rule-citations.md): Resolving every path a governance rule cites and every frontmatter glob the internal corpus declares, the three forms a citation is written in, the shapes that look like citations and are not, the two classes where an absent path is correct, why the glob half reads one corpus, and why this one gates
|
package/docs/agents/indexes.md
CHANGED
|
@@ -5,7 +5,7 @@ description: Flags, exit codes, and JSON shape for canon indexes regen and canon
|
|
|
5
5
|
|
|
6
6
|
# Indexes
|
|
7
7
|
|
|
8
|
-
`canon indexes regen` rewrites `index.md` files from sibling frontmatter. With no positional paths, it walks the current directory. With paths, each resolves by walking up to the nearest indexed ancestor, bounded by `--root`.
|
|
8
|
+
`canon indexes regen` rewrites `index.md` files from sibling frontmatter, so a hand edit to a generated index is lost on the next run. With no positional paths, it walks the current directory. With paths, each resolves by walking up to the nearest indexed ancestor, bounded by `--root`.
|
|
9
9
|
|
|
10
10
|
Duplicates dedupe. The whole-repo walk prunes `.git`, `node_modules`, and anything `.gitignore` covers via `git check-ignore`.
|
|
11
11
|
|
|
@@ -28,11 +28,11 @@ applies, and the target's git diff is the record afterwards. `canon sync
|
|
|
28
28
|
--check` lists the same file as `retired` or `renamed` before any sync runs.
|
|
29
29
|
|
|
30
30
|
A rule that only routed a path to a standard ships under that standard's name,
|
|
31
|
-
but the tasks and
|
|
32
|
-
`
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
but the tasks, plan, context, and skill rules are hand-written at `canon/` and
|
|
32
|
+
`claude/skill.md`. A held copy of each syncs in place, and the groundwork,
|
|
33
|
+
intake, session, design, readme, and rule copies are deleted as retired. The
|
|
34
|
+
markdown rule is hand-written at `writing/markdown.md`, and a target holding
|
|
35
|
+
`standards/markdown.md` keeps it there as `800-prose` retires.
|
|
36
36
|
|
|
37
37
|
A project's own rules belong under `.claude/rules/project/`, where
|
|
38
38
|
`canon standards rule` reserves `900-999` for them, and a rule placed under
|
|
@@ -112,6 +112,10 @@ Every documented agent path already passes the argument, including
|
|
|
112
112
|
`canon init`. The confirm-then-apply prompt after it still resolves to `Yes`
|
|
113
113
|
headlessly, so a call that names its stack is unchanged.
|
|
114
114
|
|
|
115
|
+
`--add` with no stack installs the named rules into the one positional, or the
|
|
116
|
+
current directory, and keeps the recorded chain. Pass `./node` to force a target
|
|
117
|
+
named like a stack. [Rule detection](gov-detect.md) proposes the names.
|
|
118
|
+
|
|
115
119
|
`canon gov install` also refuses the toolkit root as a target. It resolves the
|
|
116
120
|
target before anything else, so a path that does not exist fails rather than
|
|
117
121
|
being scaffolded.
|
|
@@ -146,12 +150,7 @@ runs the verb again for that name.
|
|
|
146
150
|
|
|
147
151
|
`canon gov regen` is the one governance verb that runs against the toolkit root,
|
|
148
152
|
because the `.claude/rules/` it writes there is produced output rather than an
|
|
149
|
-
operator's working copy. It
|
|
150
|
-
per standard under `standards/` whose frontmatter carries `paths:`, clearing the
|
|
151
|
-
folder so a standard that drops the field loses its rule. A standard named like
|
|
152
|
-
a band folder or an authored rule, or a `paths:` or `rule:` that is not a list
|
|
153
|
-
of strings, refuses the whole run before anything is written. It then reads the
|
|
154
|
-
stack recorded in `internal/governance.toml`
|
|
153
|
+
operator's working copy. It reads the stack recorded in `internal/governance.toml`
|
|
155
154
|
into `.claude/rules/canon/`, installs anything under `internal/rules/` into a
|
|
156
155
|
separate `.claude/rules/internal/`, and clears both destinations first so a
|
|
157
156
|
rule the record stopped naming disappears. `internal/` is what this repository
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Key
|
|
3
|
-
description: Comparing the files a pull request body's Key
|
|
2
|
+
title: Key changes bijection
|
|
3
|
+
description: Comparing the files a pull request body's Key changes names against its own diff, the two directions and the split inside each that decides what is worth raising, the span rules the extractor was measured into, and the three refusals that separate a clean pass from a read that produced nothing
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Key
|
|
6
|
+
# Key changes bijection
|
|
7
7
|
|
|
8
|
-
`canon pr key-changes` reads the `## Key
|
|
8
|
+
`canon pr key-changes` reads the `## Key changes` section of a pull request body, lifts the paths its bullets claim, and compares that set against the files the pull request actually changed. This repository squash-merges, so the body becomes the commit message and the record on the trunk once the branch is gone.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
canon pr key-changes
|
|
@@ -45,7 +45,7 @@ A generated asset and a regenerated index belong in the incidental class and are
|
|
|
45
45
|
|
|
46
46
|
## What counts as a claim
|
|
47
47
|
|
|
48
|
-
Only `## Key
|
|
48
|
+
Only `## Key changes` is read. `## Technical context` legitimately names files a branch never touched, such as an install stamp inside a target, so widening the read manufactures a finding out of every argument an author made for the change.
|
|
49
49
|
|
|
50
50
|
Inside the section, every backticked span in a bullet is read, and the bullet's first comma outside a span divides the ones that can accuse from the ones that can only credit. That one lever was chosen by measurement. Over the 23 merged pull requests in this repository carrying the section, reading whole bullets reported 16 paths as claimed-but-untouched and every one was a file the body named for context. Cutting at the comma left 110 claims of the original 149 and took the false reports to 2. A list of sixteen clause-opening words tried beside it removed nothing the comma had not already removed, because this corpus punctuates every one of them.
|
|
51
51
|
|
|
@@ -70,6 +70,17 @@ It reports and never gates. Whether an uncovered surface deserves a label is a j
|
|
|
70
70
|
|
|
71
71
|
A project declaring no map refuses with `no-map`, which is an answer rather than a fault. Such a project is labelled silently by design, and treating the absence as a break would make the map mandatory for every target. `canon audits run` reads that one reason as an expected absence and every other refusal as a measure that did not run.
|
|
72
72
|
|
|
73
|
+
## Applying the set
|
|
74
|
+
|
|
75
|
+
`canon labels apply <number>` reads the same earned set and adds each label the open pull request lacks, so a pull request opened outside `git-pr` takes one command to label.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
canon labels apply 123 --json
|
|
79
|
+
canon labels apply 123 --check
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
It binds to the pull request before anything is read or written, and refuses with `head-mismatch` unless the head is the current branch and the state is open, under `--check` as well. It adds and never removes, so a label a person applied stays. A label the remote does not carry lands in `missingOnRemote` and is never created. `--check` writes nothing and exits 2 when labels are owed. A project declaring no map adds nothing and exits 0.
|
|
83
|
+
|
|
73
84
|
## What it does not measure
|
|
74
85
|
|
|
75
86
|
A prefix reaching no path is invisible here. A row left behind by a deleted folder stays in the map forever, and this verb has nothing to say about it. That is the map going stale from the other side and a second measure rather than this one.
|
package/docs/agents/migrate.md
CHANGED
|
@@ -9,7 +9,7 @@ description: What each canon migrate verb moves and rewrites, what it refuses, t
|
|
|
9
9
|
|
|
10
10
|
`migrate rename` moves a project off the retired `aitk` name. It reports until `--write` is passed, and `--scope target` rewrites the toolkit-owned folders alone, reporting every other citation as one the project owns rather than editing prose somebody wrote. A project installing `canon` fresh never needs it.
|
|
11
11
|
|
|
12
|
-
`migrate skill-names` moves the plugin skills that carried a `claude-` prefix onto their two-word names and rewrites every citation of one. It carries two plain renames as well, where a skill carried no prefix and changed its name because the old one described a job it no longer does, landing on `ui-checklist` and `context-fold`, and one merge, where the five per-kind document drafters land on `draft-doc`. It leaves the pointer answering under the fold skill's old name in place. It shares its engine with `migrate rename` and differs in what it is scanning for: a skill name is a whole name rather than a word stem, so it matches only where the word ends, which is what keeps a longer word that merely opens with a skill name, such as `claude-worktrees`, out of it. It takes no `--scope`, since the skill folders it moves are authored in the toolkit and no target holds a copy of that catalog, which leaves a target's own citations of a renamed skill as the whole of what it rewrites there. The changelog and the eval transcripts are passed over on the argument the other sweep already carries, that each records what shipped or what a session ran under whatever name was current then.
|
|
12
|
+
`migrate skill-names` moves the plugin skills that carried a `claude-` prefix onto their two-word names and rewrites every citation of one. It carries two plain renames as well, where a skill carried no prefix and changed its name because the old one described a job it no longer does, landing on `ui-checklist` and `context-fold`, and one merge, where the five per-kind document drafters land on `draft-doc`. It carries one namespaced-only rename, `canvas` to `canvas-board`, keyed on `canon:canvas` and `skills/canvas` because a bare `canvas` key would rewrite the verb, its source folder, and its record folder. It leaves the pointer answering under the fold skill's old name in place. It shares its engine with `migrate rename` and differs in what it is scanning for: a skill name is a whole name rather than a word stem, so it matches only where the word ends, which is what keeps a longer word that merely opens with a skill name, such as `claude-worktrees`, out of it. It takes no `--scope`, since the skill folders it moves are authored in the toolkit and no target holds a copy of that catalog, which leaves a target's own citations of a renamed skill as the whole of what it rewrites there. The changelog and the eval transcripts are passed over on the argument the other sweep already carries, that each records what shipped or what a session ran under whatever name was current then. <!-- canon-keep-retired -->
|
|
13
13
|
|
|
14
14
|
`migrate records` moves a project's session records from `.claude/` to `.canon/` and rewrites every tracked file that cites one. It reports until `--write` is passed, and refuses outright when the project does not already ignore `.canon/`, since every folder it relocates is ignored where it stands and landing one under a tracked root commits the memory pen. Take the ignore entry with `canon tooling sync --write` first.
|
|
15
15
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The pull request evidence layout
|
|
3
|
+
description: How canon pr evidence groups screenshots into one block per view with a row per width and a column per theme, when a base column appears, where a name outside the form lands, how the commit line links, and when the blocks open
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# The pull request evidence layout
|
|
7
|
+
|
|
8
|
+
`canon pr evidence` renders the screenshots of a pull request as blocks a
|
|
9
|
+
reviewer reads by view. The record behind them, and the reasons a run can
|
|
10
|
+
refuse, are in `canon docs pr-evidence`.
|
|
11
|
+
|
|
12
|
+
## One block per view
|
|
13
|
+
|
|
14
|
+
A case name that ends in `-dark-<width>` or `-light-<width>` belongs to the
|
|
15
|
+
view named by everything before that suffix, so `menu-open-light-1440` is the
|
|
16
|
+
`menu-open` view. The name is split from the right because a view may carry
|
|
17
|
+
hyphens of its own.
|
|
18
|
+
|
|
19
|
+
Each view is one `<details>` block. Its summary carries the view and its case
|
|
20
|
+
count, a row holds one width in ascending number order, and a column holds one
|
|
21
|
+
theme:
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
| Width | Dark | Light |
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A view with any case already at the base takes a base and a head column per
|
|
28
|
+
theme, and a case the pull request added shows `*(new)*` in its base cell:
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
| Width | Dark base | Dark head | Light base | Light head |
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
A cell with no case in it stays empty. A theme no case of the view carries has
|
|
35
|
+
no column. A state under a named directory titles its blocks
|
|
36
|
+
`<state> / <view>`, so two states holding one view never repeat a name.
|
|
37
|
+
|
|
38
|
+
## Names outside the form
|
|
39
|
+
|
|
40
|
+
A case name that does not split into a view, a theme, and a width lands in a
|
|
41
|
+
flat `Case | Base | Head` block for its state, or `Case | Head` when every case
|
|
42
|
+
in it is new. Nothing is dropped, so `board.png` or a name with no width still
|
|
43
|
+
shows.
|
|
44
|
+
|
|
45
|
+
## The commit line
|
|
46
|
+
|
|
47
|
+
Under `## Evidence`, the Base and Head line names each commit as a short sha
|
|
48
|
+
that links to the full commit:
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
**Base:** [`<base>`](https://github.com/<repo>/commit/<base-sha>) · **Head:** [`<head>`](https://github.com/<repo>/commit/<head-sha>)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A reader opens what the screenshots were taken against in one click. The base
|
|
55
|
+
is the merge base the compare endpoint returns, not trunk's tip.
|
|
56
|
+
|
|
57
|
+
## When the blocks open
|
|
58
|
+
|
|
59
|
+
Every block opens while the comment carries six images or fewer, counting one
|
|
60
|
+
per case for the head plus one per case that is not new. Past that every block
|
|
61
|
+
closes, so the whole comment is open or closed together.
|
|
62
|
+
|
|
63
|
+
## What reads the body back
|
|
64
|
+
|
|
65
|
+
The case count that `would-empty` compares is the number of head images in the
|
|
66
|
+
body. It holds for the grouped rows, where one row carries up to two cases, and
|
|
67
|
+
for every layout posted before, so a comment rendered under an older shape
|
|
68
|
+
still counts. The bold `**Base:**` label and the `<details>` blocks are
|
|
69
|
+
unchanged, which keeps the address reader and the review skills working on both
|
|
70
|
+
layouts. An older comment keeps its shape until the next run edits it in place.
|
|
@@ -41,8 +41,9 @@ The record groups every evidence path by state, the remainder of its
|
|
|
41
41
|
directory under the `evidence/` segment, and within a state by filename stem,
|
|
42
42
|
so a `before/hero.png` and an `after/hero.png` naming the same case group as
|
|
43
43
|
one entry, not two files. Each entry carries whether it existed at the base
|
|
44
|
-
commit, so the comment shows a base image or marks it new.
|
|
45
|
-
|
|
44
|
+
commit, so the comment shows a base image or marks it new. Each `<img>` takes
|
|
45
|
+
its PNG width, at most 1000. `canon docs pr-evidence-layout` covers how the body
|
|
46
|
+
groups those entries by view.
|
|
46
47
|
|
|
47
48
|
`reason` on the record is what a caller branches on, not the exit code:
|
|
48
49
|
|
|
@@ -152,7 +153,7 @@ whichever previews apply, joined by a middle dot:
|
|
|
152
153
|
|
|
153
154
|
**Preview:** <url> · **Local preview:** <url>
|
|
154
155
|
|
|
155
|
-
**Base:** `<base>` · **Head:** `<head>`
|
|
156
|
+
**Base:** [`<base>`](<base-commit-url>) · **Head:** [`<head>`](<head-commit-url>)
|
|
156
157
|
```
|
|
157
158
|
|
|
158
159
|
The Base and Head line follows only when the comment carries screenshots.
|
|
@@ -258,12 +259,10 @@ the caller, and lifts only on `settled`, so a refusal holds it the same as
|
|
|
258
259
|
|
|
259
260
|
## When the comment opens
|
|
260
261
|
|
|
261
|
-
The comment opens every
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
reader whether the images match the latest push. The base is the merge base the
|
|
266
|
-
compare endpoint returns, not trunk's tip.
|
|
262
|
+
The comment opens every block while it carries six images or fewer and closes
|
|
263
|
+
every block past that. A line under `## Evidence` names the compared base and
|
|
264
|
+
head as linked short shas, which tells a reader whether the images match the
|
|
265
|
+
latest push. `canon docs pr-evidence-layout` covers the count and the blocks.
|
|
267
266
|
|
|
268
267
|
## What the comment still leaves to GitHub
|
|
269
268
|
|
package/docs/agents/pr-frames.md
CHANGED
|
@@ -12,6 +12,7 @@ the `canon-frames` branch and returns a link to its path there.
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
canon pr frames 1341 --add frames/3.png --box 3 --head <sha> --pass 20261002T154450Z --json
|
|
15
|
+
canon pr frames 1341 --add frames/3-dark.png --box 3 --theme dark --head <sha> --pass 20261002T154450Z --json
|
|
15
16
|
canon pr frames 1341 --drop --json
|
|
16
17
|
canon pr frames --prune 30 --json
|
|
17
18
|
```
|
|
@@ -23,7 +24,10 @@ through the GitHub git data API, being blobs, trees, commits, and that one ref,
|
|
|
23
24
|
so nothing is checked out, no worktree is entered, and neither `main` nor any
|
|
24
25
|
branch a pull request holds is touched. The branch never merges.
|
|
25
26
|
|
|
26
|
-
A frame lands at `pr-<number>/<short-head>/<pass>/box-<n>.png
|
|
27
|
+
A frame lands at `pr-<number>/<short-head>/<pass>/box-<n>.png`, or at
|
|
28
|
+
`box-<n>-<theme>.png` when `--theme` names `dark` or `light`, so two shots of
|
|
29
|
+
one box in one pass never take the same path. A frame without `--theme` keeps
|
|
30
|
+
the plain form. `--head` names
|
|
27
31
|
the commit the pass drove, 7 to 40 lowercase hex characters, and defaults to
|
|
28
32
|
the head the pull request object reports. `--pass` is the instant the pass
|
|
29
33
|
started, in compact UTC as `date -u +%Y%m%dT%H%M%SZ` prints it, which
|
|
@@ -59,6 +63,7 @@ be published with it.
|
|
|
59
63
|
| `bad-box` | `--add` carried no positive `--box`. |
|
|
60
64
|
| `bad-head` | `--head`, or the head the pull request reported, is not a 7 to 40 character sha. |
|
|
61
65
|
| `bad-pass` | `--add` carried no `--pass` stamp in compact UTC. |
|
|
66
|
+
| `bad-theme` | `--theme` is neither `dark` nor `light`, or came without `--add`. |
|
|
62
67
|
| `bad-days` | `--prune` carried no positive number of days. |
|
|
63
68
|
| `unreadable-frame` | The `--add` file is missing, empty, or not a PNG. Nothing is called. |
|
|
64
69
|
| `read-only` | GitHub refused a write with 403 or 404, which is what a fork's token gets. |
|
|
@@ -69,7 +74,7 @@ be published with it.
|
|
|
69
74
|
| `gh-missing` | `gh` is not on the path. |
|
|
70
75
|
| `gh-failed` | `gh` could not name the repository or read the pull request. |
|
|
71
76
|
|
|
72
|
-
An add's `ok` record carries `link`, `commit`, `path`, `box`, `head`, `pass`,
|
|
77
|
+
An add's `ok` record carries `link`, `commit`, `path`, `box`, `theme` when one was passed, `head`, `pass`,
|
|
73
78
|
and `created`, which is true when the add made the branch. A drop's carries
|
|
74
79
|
`removed`, the pull requests whose folders went, plus `commit` for the rewrite
|
|
75
80
|
or `deleted` when it emptied the branch. A prune adds `kept` and `unread`.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The pull request draft lift
|
|
3
|
+
description: How canon pr lift removes the draft mark once the reviews, evidence, standing, and CI all read clear at the head, the gate order and what each reads, the wait on a pending run, the re-read before the write, the refusal reasons it names, and what --check reports
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# The pull request draft lift
|
|
7
|
+
|
|
8
|
+
`canon pr lift` takes a pull request out of draft. It reads the gate itself, so
|
|
9
|
+
any session that closes a review can run it, and nobody has to judge whether a
|
|
10
|
+
message asking for the lift came from someone entitled to ask.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
canon pr lift 1341 --json
|
|
14
|
+
canon pr lift 1341 --check --json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
With no number it resolves the one open pull request on the checked-out branch.
|
|
18
|
+
The ship chain marks every pull request a draft, and this is the verb that
|
|
19
|
+
undoes it.
|
|
20
|
+
|
|
21
|
+
## What it reads
|
|
22
|
+
|
|
23
|
+
Five gates, read in this order. The first four need no wait, so they all run
|
|
24
|
+
before the check runs are read.
|
|
25
|
+
|
|
26
|
+
| Gate | Clear when |
|
|
27
|
+
| ---------- | --------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `review` | The newest `## Review` pass is closed, and its marker names the head. |
|
|
29
|
+
| `ui` | The newest `## UI review` verdict is closed at the head. Binds only where a checklist exists. |
|
|
30
|
+
| `evidence` | `canon pr evidence --check` reads `settled`, meaning no post-pull-request step is owed. |
|
|
31
|
+
| `standing` | The head merges into the freshly fetched base, and the base moved no path the branch writes. |
|
|
32
|
+
| `ci` | Every check run on the branch tip concluded and none failed. |
|
|
33
|
+
|
|
34
|
+
The head is the branch tip read from the remote, not the pull request object's
|
|
35
|
+
head, which trails a push by up to a minute. A review marker names the commit
|
|
36
|
+
the reviewer read, and it covers the head when it is that commit or a prefix of
|
|
37
|
+
it.
|
|
38
|
+
|
|
39
|
+
The UI gate binds only when `canon pr evidence --check --json` carries a
|
|
40
|
+
`checklist` field. The verb branches on that field and not on the exit, so a
|
|
41
|
+
branch with no rendered surface owes no UI review.
|
|
42
|
+
|
|
43
|
+
A review pass with no read-time marker refuses as `review-unmarked`. Its covered
|
|
44
|
+
commit would be the stamp GitHub wrote at submission, which the marker exists to
|
|
45
|
+
replace, and lifting on it reintroduces the defect `canon pr review-state`
|
|
46
|
+
documents.
|
|
47
|
+
|
|
48
|
+
## The wait
|
|
49
|
+
|
|
50
|
+
A pending CI run is waited on rather than refused. `--wait <seconds>` bounds it,
|
|
51
|
+
defaulting to 1200, and the check runs are read every 30 seconds until one of
|
|
52
|
+
four things happens:
|
|
53
|
+
|
|
54
|
+
- every run passed, and the verb goes on to the write
|
|
55
|
+
- a run failed, which refuses `ci-failing` at once
|
|
56
|
+
- the branch conflicts with its base, which refuses `ci-conflicted` at once,
|
|
57
|
+
since no run starts for a conflicted branch and the wait could not end
|
|
58
|
+
- the deadline passed, which refuses `ci-timeout`
|
|
59
|
+
|
|
60
|
+
A refusal on any of the first four gates comes before the wait starts. A code
|
|
61
|
+
reviewer whose UI partner is still driving refuses `ui-open` immediately
|
|
62
|
+
instead of holding a turn through a CI run.
|
|
63
|
+
|
|
64
|
+
## The re-read
|
|
65
|
+
|
|
66
|
+
A push during the wait moves the head off the commit every earlier gate
|
|
67
|
+
cleared. After the wait, and immediately before the write, the verb reads the
|
|
68
|
+
pull request, the branch tip, and the reviews again. A tip that moved refuses
|
|
69
|
+
`head-moved`, and a review that opened refuses with its own reason. The
|
|
70
|
+
standing is read again as well, so a sibling merging during the wait refuses
|
|
71
|
+
`standing-stale` instead of lifting a branch that read fresh before it. A pull
|
|
72
|
+
request already out of draft by then reports `already-ready`.
|
|
73
|
+
|
|
74
|
+
Two reviewers closing within seconds of each other can each read the other's
|
|
75
|
+
review as still open and both refuse. The re-read narrows that window and does
|
|
76
|
+
not close it, so a draft whose reviews both read closed is the controlling
|
|
77
|
+
session's to lift.
|
|
78
|
+
|
|
79
|
+
## The write
|
|
80
|
+
|
|
81
|
+
The lift is the `markPullRequestReadyForReview` GraphQL mutation, because the
|
|
82
|
+
REST pull request update carries no draft field. It is the one GraphQL call the
|
|
83
|
+
verb makes, and every read stays on REST. The verb reads `isDraft` back from the
|
|
84
|
+
mutation's answer, and a response that does not say `false` refuses `gh-failed`
|
|
85
|
+
rather than reporting a lift.
|
|
86
|
+
|
|
87
|
+
A cloud session's proxy refuses GraphQL, so a reviewer running there reaches
|
|
88
|
+
`gh-failed` on the write and hands the lift to the controlling session.
|
|
89
|
+
|
|
90
|
+
## What it reports
|
|
91
|
+
|
|
92
|
+
`reason` on the record is what a caller branches on. Exit 0 covers `lifted` and
|
|
93
|
+
`already-ready`, so the second of two reviewers to close owes nobody a message.
|
|
94
|
+
Every other reason exits 1.
|
|
95
|
+
|
|
96
|
+
| Reason | What it means |
|
|
97
|
+
| ------------------- | ---------------------------------------------------------------------- |
|
|
98
|
+
| `lifted` | The mark came off. |
|
|
99
|
+
| `already-ready` | The pull request was not a draft. Nothing is written. |
|
|
100
|
+
| `clear` | Under `--check`, every gate reads clear. |
|
|
101
|
+
| `pull-closed` | The pull request is closed. |
|
|
102
|
+
| `review-missing` | The thread carries no code review. |
|
|
103
|
+
| `review-open` | The newest code review is open. |
|
|
104
|
+
| `review-unmarked` | The newest code review carries no marker. |
|
|
105
|
+
| `review-behind` | The newest code review closed on an earlier commit than the head. |
|
|
106
|
+
| `ui-missing` | A checklist exists and no UI review has been posted. |
|
|
107
|
+
| `ui-open` | The newest UI review is open. |
|
|
108
|
+
| `ui-unmarked` | The newest UI review carries no head marker. |
|
|
109
|
+
| `ui-behind` | The newest UI review closed on an earlier commit than the head. |
|
|
110
|
+
| `evidence-owed` | The evidence check reads `owed`. |
|
|
111
|
+
| `standing-stale` | The base moved under a path the branch writes. |
|
|
112
|
+
| `standing-conflict` | The head does not merge cleanly into the base. |
|
|
113
|
+
| `standing-unknown` | The head or base did not resolve, which a fork or deleted head leaves. |
|
|
114
|
+
| `ci-pending` | Under `--check`, a run has yet to conclude. |
|
|
115
|
+
| `ci-failing` | A check run failed. |
|
|
116
|
+
| `ci-conflicted` | The branch conflicts, so no run will start. |
|
|
117
|
+
| `ci-timeout` | A run was still pending when `--wait` ran out. |
|
|
118
|
+
| `head-moved` | A push landed during the wait. |
|
|
119
|
+
| `gh-failed` | A read or the write was refused, so nothing is reported as lifted. |
|
|
120
|
+
|
|
121
|
+
`standing-unknown` waits on a person, matching the orchestrator poll's own rule
|
|
122
|
+
for a head it cannot resolve.
|
|
123
|
+
|
|
124
|
+
## `--check`
|
|
125
|
+
|
|
126
|
+
`--check` reports every gate and writes nothing. It reads the check runs once
|
|
127
|
+
and does not wait, so a pending run reports `ci-pending`. The record carries a
|
|
128
|
+
`gates` array with each gate's name, whether it is clear, and its reason, so a
|
|
129
|
+
caller sees every gate that blocks and not the first alone.
|
|
130
|
+
|
|
131
|
+
The orchestrator's poll and a session deciding whether to run the verb read the
|
|
132
|
+
same answer this way, rather than each restating the gate.
|
|
@@ -31,7 +31,7 @@ printf '.canon/\n' >> .gitignore
|
|
|
31
31
|
|
|
32
32
|
The ignore line is repeated here rather than left to the install, because the person running these commands is the one who creates the directory and the rule is worth reading beside the command that needs it. The claude manifest ships `.canon/` too, so a project that ran `canon tooling sync` already carries it and this line is a no-op there. One root entry covers the history and every record beside it, which is what makes the rule worth stating once rather than per folder.
|
|
33
33
|
|
|
34
|
-
Point it at a private repository, and at one that is not a remote of the project. Records carry the
|
|
34
|
+
Point it at a private repository, and at one that is not a remote of the project. Records carry the plans, the review reports, and the groundwork trails, so a public project publishes all of it to anyone who fetches all refs. `push` compares the configured origin against every remote of the project and refuses on a match. A read of that list which fails refuses as well, since an empty list clears the comparison for every origin and a gate that passes on its own failure is no gate.
|
|
35
35
|
|
|
36
36
|
## Refusals
|
|
37
37
|
|
|
@@ -58,4 +58,4 @@ The two `pull` refusals exist because the directions are not symmetric. A push o
|
|
|
58
58
|
|
|
59
59
|
## When it runs
|
|
60
60
|
|
|
61
|
-
`canon hooks post-merge`, which `.husky/post-merge` calls, runs `push` after the task archiving, on every merge rather than only on one that archived a task. A review report and a
|
|
61
|
+
`canon hooks post-merge`, which `.husky/post-merge` calls, runs `push` after the task archiving, on every merge rather than only on one that archived a task. A review report and a plan edit both land on runs that close nothing. The verb exits zero whatever the push answers, so an unreachable remote neither aborts the hook nor delays the archiving before it, and a checkout that never ran the setup reports nothing. `hooks.md` covers the verb. Anything the hook misses is covered by running the verb by hand.
|
|
@@ -1,64 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Records stale
|
|
3
|
-
description:
|
|
3
|
+
description: Counting the releases since the requirements record was last reviewed, where the review date is read from, and the exit codes and refusals
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Records stale
|
|
7
7
|
|
|
8
|
-
`canon records stale
|
|
8
|
+
`canon records stale canonical` reports when the requirements record was last reviewed and how many releases have shipped since. A skill takes the count from the verb rather than re-deriving it from the tag list.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
canon records stale
|
|
12
|
-
canon records stale memory --json
|
|
13
|
-
canon records stale memory --days 60 --json
|
|
11
|
+
canon records stale canonical
|
|
14
12
|
canon records stale canonical --json
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
| Option | Behavior
|
|
18
|
-
| --------------- |
|
|
19
|
-
| `--json` | Add a machine-readable record on stdout
|
|
20
|
-
| `--
|
|
21
|
-
| `--root <path>` | Project root, defaulting to the main worktree for `memory` and the current worktree for `canonical` |
|
|
15
|
+
| Option | Behavior |
|
|
16
|
+
| --------------- | ----------------------------------------------------------------- |
|
|
17
|
+
| `--json` | Add a machine-readable record on stdout |
|
|
18
|
+
| `--root <path>` | Project root, defaulting to the current worktree rather than main |
|
|
22
19
|
|
|
23
|
-
`
|
|
20
|
+
`canonical` is the one kind it reads. Any other argument refuses as `unknown-kind`, including `memory`, which the verb read until the memory pen retired.
|
|
24
21
|
|
|
25
|
-
It reports and never writes
|
|
26
|
-
|
|
27
|
-
## What makes an entry due
|
|
28
|
-
|
|
29
|
-
An entry is due when its frontmatter carries no `reviewed` date, or one older than `--days`. The field is optional, and a review that keeps an entry is what writes it. A `reviewed` value that is not a `YYYY-MM-DD` calendar date reads as never reviewed, and the record carries the raw value as `invalidReviewed` so a review can see it rather than the verb throwing over one hand edit.
|
|
30
|
-
|
|
31
|
-
The field is read off the raw frontmatter block rather than a parsed value, since a YAML parser resolves a bare date to a date object on one schema and a string on another.
|
|
32
|
-
|
|
33
|
-
## Cited paths
|
|
34
|
-
|
|
35
|
-
A cited path is a backticked token holding a `/` and ending in a file extension. A trailing `:12`, `:12-20`, or `#heading` anchor is stripped before the test, since otherwise every line citation reads as missing. The path resolves against the project root and never against the entry's own folder, because an entry cites the tree it was written about.
|
|
36
|
-
|
|
37
|
-
Tokens that look like paths and cite nothing in the tree are never reported:
|
|
38
|
-
|
|
39
|
-
- Anything under `.canon/`, the scratch folder, or `.claude/worktrees/`, which no tree commits
|
|
40
|
-
- A placeholder or glob holding `<`, `*`, or `{`, a variable holding `$`, and a path elided with `...`
|
|
41
|
-
- A URL, an absolute path, a home path, and a path opening with `../`
|
|
42
|
-
|
|
43
|
-
A missing path is a proxy for an entry the tree has moved under, not a verdict. It misses a rule the tree now contradicts in prose, and in a target project it flags a toolkit path the target never held. The review judges each one rather than retiring on the flag alone.
|
|
44
|
-
|
|
45
|
-
## Order
|
|
46
|
-
|
|
47
|
-
The pen is read at its top level alone. `review/` holds receipts, `archive/` holds retirements, and `index.md` is the generated catalog, so none is an entry a review would queue.
|
|
48
|
-
|
|
49
|
-
Entries come back due first. Among the due entries, one citing a missing path leads, then the longest unreviewed, with a never-reviewed entry ahead of any dated one, then by name so two runs over one pen agree. A caller takes the first N as a batch:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
canon records stale memory --json | jq -r '[.entries[] | select(.due)][0:20][] | .name'
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
The record carries `total`, `due`, `days`, the `folder` read relative to the root, and one `entries` row per entry with `name`, `category`, `reviewed`, `due`, and `unresolved`.
|
|
22
|
+
It reports and never writes, matching `validate` and `size`.
|
|
56
23
|
|
|
57
24
|
## Canonical records
|
|
58
25
|
|
|
59
26
|
`canonical` reads `REQUIREMENTS.md` at whichever surface root carries it, `canon/` ahead of `.claude/`, and omits it when the project does not hold one. It is tracked, so `--root` defaults to the worktree the caller stands in rather than the main one, and a stamp a branch just wrote reads back from that branch.
|
|
60
27
|
|
|
61
|
-
The review point is an optional `reviewed: YYYY-MM-DD` frontmatter field, set by whoever finishes a review, per `canon standards requirements`. It is a date rather than a commit, since a commit written on a feature branch never reaches a trunk that squash-merges. The field is read the
|
|
28
|
+
The review point is an optional `reviewed: YYYY-MM-DD` frontmatter field, set by whoever finishes a review, per `canon standards requirements`. It is a date rather than a commit, since a commit written on a feature branch never reaches a trunk that squash-merges. The field is read off the raw frontmatter block rather than a parsed value, since a YAML parser resolves a bare date to a date object on one schema and a string on another. A value that is not a calendar date reads as never reviewed, and the record carries the raw value as `invalidReviewed` so a review can see it rather than the verb throwing over one hand edit.
|
|
62
29
|
|
|
63
30
|
The count is every release tag merged into `HEAD` whose creator date falls after the reviewed day. A release tag ends in a dotted version, bare as `v5.25.0` or behind a component prefix as `canon-v2.1.0`, so an eval, deploy, or snapshot tag on the trunk never inflates it. A lightweight tag's creator date is its commit's date and an annotated tag's is the tagging date, so a project mixing both counts by two clocks.
|
|
64
31
|
|
|
@@ -68,8 +35,6 @@ It gates nothing, and no hook, gate stage, or workflow runs it. `canon:document-
|
|
|
68
35
|
|
|
69
36
|
## Exit codes and refusals
|
|
70
37
|
|
|
71
|
-
Exit codes: `0` the reading completed, whatever it found, and `1` refused. A
|
|
72
|
-
|
|
73
|
-
A `reason` field carries which gate fired: `no-folder` when the project holds no memory folder at either record root, `unknown-kind` for any kind but `memory` or `canonical`, `bad-days` when `--days` is not a positive whole number or is passed to `canonical`, and `unreadable-tags` when `canonical` cannot read the tags. An empty pen is not a refusal. It reports an empty list and exits `0`.
|
|
38
|
+
Exit codes: `0` the reading completed, whatever it found, and `1` refused. A release count is a prompt for the review to judge rather than a failure, so nothing here gates.
|
|
74
39
|
|
|
75
|
-
|
|
40
|
+
A `reason` field carries which gate fired: `unknown-kind` for any kind but `canonical`, and `unreadable-tags` when the tags cannot be read.
|