@erclx/canon 5.25.0 → 5.27.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 +4 -3
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +2 -0
- package/claude/skills/auto-ship/SKILL.md +3 -11
- package/claude/skills/auto-ship/references/review-findings.md +20 -0
- package/claude/skills/backlog-triage/SKILL.md +2 -0
- package/claude/skills/bash-cli-script/SKILL.md +2 -0
- package/claude/skills/build-in-slices/SKILL.md +2 -0
- package/claude/skills/canon-cli/SKILL.md +2 -0
- package/claude/skills/canon-feedback/SKILL.md +2 -0
- package/claude/skills/canon-feedback-triage/SKILL.md +2 -0
- package/claude/skills/canon-operator/SKILL.md +2 -0
- package/claude/skills/canon-rollout/SKILL.md +3 -11
- package/claude/skills/canon-rollout/references/failure-recovery.md +20 -0
- package/claude/skills/canvas/SKILL.md +14 -1
- package/claude/skills/ci-workflow/SKILL.md +2 -0
- package/claude/skills/code-craft/SKILL.md +2 -0
- package/claude/skills/codebase-layout/SKILL.md +2 -0
- package/claude/skills/context-fold/REQUIREMENT.md +6 -2
- package/claude/skills/context-fold/SKILL.md +9 -21
- package/claude/skills/context-fold/references/anchor-sweep.md +2 -2
- package/claude/skills/context-fold/references/completion-report.md +26 -0
- package/claude/skills/create-rule/SKILL.md +2 -0
- package/claude/skills/create-skill/SKILL.md +2 -0
- package/claude/skills/create-standard/SKILL.md +2 -0
- package/claude/skills/decision-escalate/SKILL.md +2 -0
- package/claude/skills/deploy-app/SKILL.md +2 -0
- package/claude/skills/deprecation-migration/SKILL.md +2 -0
- package/claude/skills/design-extract/SKILL.md +2 -0
- package/claude/skills/design-taste/REQUIREMENT.md +1 -1
- package/claude/skills/design-taste/SKILL.md +6 -2
- package/claude/skills/design-taste/references/adopted.md +40 -0
- package/claude/skills/design-taste/references/kinds.md +1 -1
- package/claude/skills/design-taste/references/systems.md +1 -7
- package/claude/skills/design-taste/references/tells.md +2 -24
- package/claude/skills/docs-sync/REQUIREMENT.md +2 -1
- package/claude/skills/docs-sync/SKILL.md +2 -0
- package/claude/skills/document-health/REQUIREMENT.md +2 -0
- package/claude/skills/document-health/SKILL.md +23 -0
- package/claude/skills/document-health/references/axes.md +12 -0
- package/claude/skills/draft-and-pick/SKILL.md +3 -1
- package/claude/skills/draft-doc/SKILL.md +2 -0
- package/claude/skills/draft-doc/references/wiki.md +1 -1
- package/claude/skills/draft-figure/SKILL.md +2 -0
- package/claude/skills/draft-identity/SKILL.md +3 -1
- package/claude/skills/draft-ready/SKILL.md +2 -0
- package/claude/skills/draft-screencast/SKILL.md +11 -7
- package/claude/skills/draft-slides/REQUIREMENT.md +17 -12
- package/claude/skills/draft-slides/SKILL.md +33 -20
- package/claude/skills/git-branch/SKILL.md +2 -0
- package/claude/skills/git-commit/SKILL.md +2 -0
- package/claude/skills/git-followup/SKILL.md +2 -0
- package/claude/skills/git-issue/SKILL.md +2 -0
- package/claude/skills/git-issue/references/issue.md +10 -0
- package/claude/skills/git-pr/SKILL.md +2 -0
- package/claude/skills/git-pr/references/evidence.md +14 -6
- package/claude/skills/git-pr/references/labels.md +12 -0
- package/claude/skills/git-ship/SKILL.md +2 -0
- package/claude/skills/git-split/SKILL.md +21 -8
- package/claude/skills/git-stage/SKILL.md +2 -0
- package/claude/skills/git-worktree/SKILL.md +2 -0
- package/claude/skills/index-lookup/SKILL.md +2 -0
- package/claude/skills/markdown-propose/SKILL.md +2 -0
- package/claude/skills/markdown-propose/references/format.md +9 -0
- package/claude/skills/memory-capture/SKILL.md +2 -0
- package/claude/skills/memory-review/SKILL.md +2 -0
- package/claude/skills/memory-review/references/later-phases.md +7 -0
- package/claude/skills/plan-feature/SKILL.md +2 -0
- package/claude/skills/plan-groundwork/SKILL.md +2 -0
- package/claude/skills/plan-intake/SKILL.md +2 -0
- package/claude/skills/plan-intake-answer/SKILL.md +2 -0
- package/claude/skills/project-commands/SKILL.md +2 -0
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +2 -0
- package/claude/skills/repo-metadata/SKILL.md +2 -0
- package/claude/skills/restate-plainly/SKILL.md +2 -0
- package/claude/skills/review-address/SKILL.md +3 -7
- package/claude/skills/review-address/references/post-review-findings.md +16 -0
- package/claude/skills/review-branch/SKILL.md +2 -0
- package/claude/skills/review-craft/SKILL.md +2 -0
- package/claude/skills/review-craft/references/ui.md +2 -2
- package/claude/skills/review-pr/SKILL.md +4 -8
- package/claude/skills/review-pr/references/body-variants.md +52 -0
- package/claude/skills/review-pr/references/key-changes.md +16 -0
- package/claude/skills/review-pr/references/post.md +15 -43
- package/claude/skills/review-ui/SKILL.md +3 -1
- package/claude/skills/review-ui/references/post.md +4 -2
- package/claude/skills/role-orchestrator/SKILL.md +5 -14
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +8 -0
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +13 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +23 -0
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +5 -33
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +1 -21
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +38 -0
- package/claude/skills/role-orchestrator/references/orchestrator-watch.md +26 -0
- package/claude/skills/role-planner/SKILL.md +2 -0
- package/claude/skills/role-reviewer/REQUIREMENT.md +1 -1
- package/claude/skills/role-reviewer/SKILL.md +2 -0
- package/claude/skills/role-worker/SKILL.md +2 -0
- package/claude/skills/search-craft/REQUIREMENT.md +1 -1
- package/claude/skills/search-craft/SKILL.md +5 -1
- package/claude/skills/search-craft/references/adopted.md +30 -0
- package/claude/skills/seed-sync/SKILL.md +2 -0
- package/claude/skills/session-compact/SKILL.md +2 -0
- package/claude/skills/session-map/SKILL.md +2 -0
- package/claude/skills/session-relay/SKILL.md +2 -0
- package/claude/skills/session-resume/SKILL.md +2 -0
- package/claude/skills/session-worktree/SKILL.md +3 -11
- package/claude/skills/session-worktree/references/install-command.md +20 -0
- package/claude/skills/sketch-design/SKILL.md +2 -0
- package/claude/skills/systematic-debugging/SKILL.md +2 -0
- package/claude/skills/target-check/SKILL.md +2 -0
- package/claude/skills/target-setup/SKILL.md +2 -0
- package/claude/skills/target-setup/references/detect.md +8 -0
- package/claude/skills/target-setup/references/indexes.md +13 -0
- package/claude/skills/target-setup/references/verify.md +8 -0
- package/claude/skills/task-board/SKILL.md +2 -0
- package/claude/skills/teach-workspace/SKILL.md +5 -15
- package/claude/skills/teach-workspace/references/lesson-build.md +75 -0
- package/claude/skills/teach-workspace/references/lesson-craft.md +13 -69
- package/claude/skills/teach-workspace/references/revisit.md +22 -0
- package/claude/skills/test-craft/SKILL.md +2 -0
- package/claude/skills/test-first/SKILL.md +4 -0
- package/claude/skills/test-first/references/adopted.md +36 -0
- package/claude/skills/ui-checklist/SKILL.md +2 -0
- package/claude/skills/ux-audit/SKILL.md +2 -0
- package/claude/skills/ux-measure/SKILL.md +2 -0
- package/claude/skills/ux-walkthrough/SKILL.md +2 -0
- package/claude/skills/video-craft/SKILL.md +2 -0
- package/claude/skills/write-human/SKILL.md +3 -1
- package/claude/skills/write-human/references/machine-tells.md +13 -0
- package/claude/skills/youtube-transcripts/SKILL.md +2 -0
- package/docs/agents/canvas.md +24 -6
- package/docs/agents/capture.md +6 -6
- package/docs/agents/commands.md +5 -5
- package/docs/agents/index.md +5 -5
- package/docs/agents/install-and-sync.md +7 -0
- package/docs/agents/key-changes.md +1 -1
- package/docs/agents/pr-evidence.md +38 -15
- package/docs/agents/pr-local.md +19 -13
- package/docs/agents/pr-preview.md +44 -21
- package/docs/agents/records-stale.md +22 -9
- package/docs/agents/records.md +1 -1
- package/docs/agents/sandbox.md +29 -5
- package/docs/agents/scripting.md +8 -1
- package/docs/agents/skills-audit.md +11 -3
- package/docs/agents/slides.md +15 -3
- package/docs/workflow/ai-workflow.md +1 -1
- package/docs/workflow/index.md +1 -0
- package/docs/workflow/operating-model.md +5 -6
- package/docs/workflow/parallel-features.md +23 -2
- package/docs/workflow/skill-map-on-request.md +42 -0
- package/docs/workflow/skill-map.md +3 -34
- package/docs/workflow/zshrc-aliases.md +1 -1
- package/package.json +1 -1
- package/scripts/core/regen-hero.ts +1 -1
- package/scripts/lib/sandbox-git.sh +1 -9
- package/scripts/lib/sandbox-path.sh +6 -162
- package/scripts/sandbox-hook.sh +99 -0
- package/src/audits/run.ts +1 -1
- package/src/canvas/address.ts +12 -3
- package/src/canvas/capture.ts +1 -9
- package/src/canvas/client/inspector/align-grid.tsx +162 -0
- package/src/canvas/client/inspector/color-field.tsx +398 -0
- package/src/canvas/client/inspector/color-inputs.tsx +139 -0
- package/src/canvas/client/inspector/color-picker.tsx +668 -0
- package/src/canvas/client/inspector/color-space.ts +240 -0
- package/src/canvas/client/inspector/field.tsx +5 -1
- package/src/canvas/client/inspector/fields.css +547 -17
- package/src/canvas/client/inspector/size-field.tsx +69 -0
- package/src/canvas/client/inspector/values.ts +166 -1
- package/src/canvas/client/inspector.tsx +236 -73
- package/src/canvas/client/selection.tsx +197 -0
- package/src/canvas/client/shell.css +104 -12
- package/src/canvas/client/state.ts +69 -9
- package/src/canvas/client/surface.tsx +147 -22
- package/src/canvas/content.ts +50 -1
- package/src/canvas/edit.ts +37 -4
- package/src/canvas/editing.ts +203 -0
- package/src/canvas/global.d.ts +15 -0
- package/src/canvas/server.ts +149 -12
- package/src/canvas/tokens.ts +59 -17
- package/src/capture/render.ts +45 -7
- package/src/capture/sources.ts +43 -0
- package/src/census/count.ts +2 -2
- package/src/claude/cases/workflow.ts +5 -0
- package/src/claude/seeds.ts +2 -2
- package/src/claude/skills-audit.ts +96 -14
- package/src/claude/skills-drift.ts +1 -1
- package/src/claude/skills-families.ts +36 -0
- package/src/claude/skills-list.ts +76 -15
- package/src/commands/audits.ts +2 -2
- package/src/commands/canvas.ts +179 -2
- package/src/commands/claude.ts +94 -11
- package/src/commands/design.ts +142 -2
- package/src/commands/feedback.ts +3 -3
- package/src/commands/gov.ts +1 -1
- package/src/commands/hooks.ts +1 -1
- package/src/commands/indexes.ts +1 -1
- package/src/commands/init.ts +1 -1
- package/src/commands/intake.ts +1 -1
- package/src/commands/migrate.ts +1 -1
- package/src/commands/pr.ts +105 -58
- package/src/commands/records.ts +89 -7
- package/src/commands/repo.ts +1 -1
- package/src/commands/sandbox.ts +103 -11
- package/src/commands/sessions.ts +1 -1
- package/src/commands/slides.ts +31 -77
- package/src/commands/sync.ts +1 -1
- package/src/commands/tasks.ts +2 -2
- package/src/commands/teach.ts +1 -1
- package/src/commands/transcripts.ts +1 -1
- package/src/commands/worktrees.ts +1 -1
- package/src/comments/scan.ts +1 -1
- package/src/comments/trend.ts +1 -1
- package/src/context/audit.ts +1 -1
- package/src/context/citations.ts +1 -1
- package/src/context/classify/extract.ts +2 -2
- package/src/design/project-fonts.ts +392 -0
- package/src/design/tokens.ts +2 -18
- package/src/docs/read.ts +1 -1
- package/src/{github.ts → feedback/github.ts} +2 -2
- package/src/{client-commands.ts → gate/client-commands.ts} +1 -1
- package/src/gate/measures.ts +53 -13
- package/src/gate/sequencer.ts +1 -1
- package/src/gate/stages.ts +9 -0
- package/src/{git-files.ts → git/files.ts} +2 -2
- package/src/{git-ignore.ts → git/ignore.ts} +1 -1
- package/src/{worktree.ts → git/worktree.ts} +1 -1
- package/src/gov/citations.ts +2 -2
- package/src/gov/install.ts +1 -1
- package/src/gov/payload.ts +1 -1
- package/src/gov/superseded.ts +3 -3
- package/src/gov/test-order.ts +2 -2
- package/src/help.ts +1 -1
- package/src/hooks/post-merge.ts +1 -1
- package/src/indexes/walk.ts +1 -1
- package/src/labels/audit.ts +1 -1
- package/src/markdown/ceiling.ts +1 -1
- package/src/markdown/files.ts +1 -1
- package/src/migrate/apply.ts +1 -1
- package/src/pr/bijection.ts +1 -1
- package/src/pr/evidence.ts +96 -43
- package/src/pr/local.ts +16 -10
- package/src/pr/preview.ts +78 -2
- package/src/record-root.ts +1 -0
- package/src/records/backup.ts +2 -1
- package/src/records/push-guard.ts +1 -1
- package/src/records/stale-canonical.ts +146 -0
- package/src/records/stale.ts +1 -1
- package/src/sandbox/headless/dispatch.ts +264 -0
- package/src/sandbox/headless/run.ts +653 -0
- package/src/sandbox/headless/watch.ts +145 -0
- package/src/sandbox/hooks.ts +128 -0
- package/src/sandbox/provision.ts +607 -0
- package/src/sandbox/tree.ts +99 -4
- package/src/secrets/marker.ts +2 -2
- package/src/secrets/scan.ts +2 -2
- package/src/sessions/claim.ts +1 -1
- package/src/sessions/resolve.ts +1 -1
- package/src/sessions/transfer/bundle.ts +1 -1
- package/src/shipped/references.ts +2 -2
- package/src/slides/convert/export.ts +2 -16
- package/src/slides/decks.ts +110 -0
- package/src/slides/package/fonts.ts +6 -2
- package/src/standards/audit.ts +2 -2
- package/src/standards/read.ts +1 -1
- package/src/sync/check.ts +2 -2
- package/src/sync/engine.ts +2 -2
- package/src/sync/git.ts +1 -1
- package/src/sync/history.ts +1 -1
- package/src/sync/reverse.ts +1 -1
- package/src/sync/seeds-report.ts +1 -1
- package/src/sync/target.ts +1 -1
- package/src/sync/workflow.ts +1 -1
- package/src/targets/pulls.ts +2 -2
- package/src/targets/sweep.ts +2 -2
- package/src/tasks/answers.ts +1 -1
- package/src/tasks/archive.ts +1 -1
- package/src/tasks/reach.ts +1 -1
- package/src/tasks/trunk.ts +1 -1
- package/src/teach/nav.ts +1 -1
- package/src/tooling/inject.ts +2 -2
- package/src/tooling/subfolder.ts +1 -1
- package/src/web/readme-citations.ts +2 -2
- package/src/worktrees/bare-flag.ts +1 -1
- package/src/worktrees/reclaim.ts +2 -2
- package/src/worktrees/remove.ts +1 -1
- package/standards/architecture.md +1 -0
- package/standards/canvas.md +3 -2
- package/standards/requirements.md +2 -0
- package/standards/skill-practice.md +2 -1
- package/standards/skill.md +2 -0
- package/standards/wiki.md +12 -3
- package/tooling/base/configs/.github/workflows/pr-local-preview.yml +2 -2
- package/scripts/lib/sandbox-dispatch.sh +0 -190
- package/scripts/manage-sandbox.sh +0 -472
- package/src/slides/layouts.ts +0 -478
- package/src/slides/parse.ts +0 -84
- package/src/slides/render.ts +0 -110
- package/src/slides/styles.ts +0 -96
- /package/claude/skills/write-human/references/{source-material.md → adopted.md} +0 -0
- /package/src/{commands/feedback-format.ts → feedback/body.ts} +0 -0
- /package/src/{github-format.ts → feedback/github-format.ts} +0 -0
- /package/src/{git-base.ts → git/base.ts} +0 -0
- /package/src/{git-env.ts → git/env.ts} +0 -0
- /package/src/{frontmatter.ts → markdown/frontmatter.ts} +0 -0
- /package/src/{binary.ts → sweep/binary.ts} +0 -0
- /package/src/{exempt-marker.ts → sweep/exempt-marker.ts} +0 -0
- /package/src/{copy.ts → sync/copy.ts} +0 -0
- /package/src/{target.ts → targets/validate.ts} +0 -0
- /package/src/{paths.ts → tasks/paths.ts} +0 -0
- /package/src/{seed-marker.ts → tooling/seed-marker.ts} +0 -0
package/standards/canvas.md
CHANGED
|
@@ -41,7 +41,8 @@ A canvas failing these is non-conforming even when it satisfies every shape rule
|
|
|
41
41
|
## Frames
|
|
42
42
|
|
|
43
43
|
- Write one frame as one `.html` file inside its page folder. The filename without its extension is the frame's name, and the name follows the page naming rule.
|
|
44
|
-
- Write
|
|
44
|
+
- Write a frame as a whole document or as a fragment. The server writes in the `html`, `head`, and `body` a fragment leaves out, marked so a pick still matches the file.
|
|
45
|
+
- State a `body` whenever the frame states a `head`. The browser builds one the file leaves out, and an address the operator picks inside the frame can no longer be matched to the file.
|
|
45
46
|
- Write every table with its `tbody` stated, for the same reason. A browser adds one the file leaves out.
|
|
46
47
|
- Keep a frame self-contained. Inline its own styles and scripts, or link a file inside the same page folder, since a frame is served from its page and nothing outside the canvas resolves.
|
|
47
48
|
- Use the project's custom properties, `var(--<name>)`, for every value the token stylesheet defines. A literal copied from it shows the right color today and the wrong one after the next token change.
|
|
@@ -78,7 +79,7 @@ The keys below are the ones a reader parses. The frame names are placeholders.
|
|
|
78
79
|
- Do not assume a viewport. A frame renders at its layout width on the canvas and in a capture alike, so size it with media queries against that width rather than against the operator's window.
|
|
79
80
|
- Do not assume the theme. The canvas theme toggle is the operator's own state, and a capture shows each frame in its default theme.
|
|
80
81
|
- Do not assume a network. Name only fonts the machine has, or ship the font beside the frame, since a capture refuses a frame naming a font it cannot find.
|
|
81
|
-
- Do not assume a default font. Set `font-family`
|
|
82
|
+
- Do not assume a default font. Set `font-family` with an installed family first on an element the frame's text inherits from, since a capture checks the first family of the text it renders and the browser's default serif is absent from many machines.
|
|
82
83
|
- Do not assume the frame is the source. A picked direction is carried into the project's design document or its wireframes, and the operator clears the frame once it has been carried.
|
|
83
84
|
- Do not assume the canvas survives the checkout. The folder is gitignored, so a lost checkout loses every page in it.
|
|
84
85
|
|
|
@@ -46,6 +46,8 @@ This file loads into every session, so its weight is paid before any work starts
|
|
|
46
46
|
|
|
47
47
|
Once every entry in the MVP list, or in a later scope section, has shipped, delete the section. Git keeps the old text, and the document states the project as it stands. Do not annotate an entry as shipped and leave it in place. While any entry is unshipped, do not renumber the list or append to it.
|
|
48
48
|
|
|
49
|
+
The record may carry an optional `reviewed: YYYY-MM-DD` frontmatter field naming the day someone last read it whole for identity drift. Whoever finishes that review sets it as the review's last edit, and `canon records stale canonical` reads it to count the releases shipped since. A record with no field reads as never reviewed.
|
|
50
|
+
|
|
49
51
|
Later scope arrives as a new section rather than as an extension of the MVP list. Name the section for what it delivers and state its entries as outcomes, the same way the goals are stated. Nothing sequences either list into versions. Work reaches the board as discrete tasks under `tasks.md`, and `board.md` orders them by readiness, so a section here states what is wanted and never when it lands.
|
|
50
52
|
|
|
51
53
|
## Distribution
|
|
@@ -47,5 +47,6 @@ A practice skill failing any of these is non-conforming even when every heading
|
|
|
47
47
|
## Which skills are practice skills
|
|
48
48
|
|
|
49
49
|
- `canon claude skills audit` keeps the list of practice skills and checks each listed one for the three closing sections and the ledger.
|
|
50
|
+
- It keeps a wider ledger list beside it, holding every practice skill plus the skills that teach a craft drawn from outside sources without a practice's closing shape. A skill on the wider list alone owes the ledger and none of the three sections.
|
|
50
51
|
- Never mark a skill as a practice skill in its own frontmatter, since a self-declared kind lets a skill exempt itself.
|
|
51
|
-
-
|
|
52
|
+
- Both lists name this toolkit's shipped skills alone, so a project's own practice skill takes this shape with no check behind it.
|
package/standards/skill.md
CHANGED
|
@@ -100,6 +100,7 @@ allowed-tools: <tools required>
|
|
|
100
100
|
- `disable-model-invocation: true`: user-invoked only, Claude will not auto-trigger. Set it on a skill that starts a process the operator owns, never on one reachable by a matched trigger.
|
|
101
101
|
- `allowed-tools`: restrict tool access when the skill is active
|
|
102
102
|
- `metadata`: optional key-value pairs (`author`, `version`, `mcp-server`)
|
|
103
|
+
- `metadata.family` (required on a skill under `claude/skills/`): the skill map group the skill's row sits under, as one key from `families` in `canon claude skills list --json`. A skill under `.claude/skills/` takes none.
|
|
103
104
|
|
|
104
105
|
## Description
|
|
105
106
|
|
|
@@ -130,6 +131,7 @@ allowed-tools: <tools required>
|
|
|
130
131
|
- Below the ceiling, name the branch that skips a block before moving it. A block every run dereferences costs a read and saves nothing.
|
|
131
132
|
- Past the ceiling, move a whole step to a reference, preferring a step a named branch skips. Keep the step heading in the body with one line naming the file to read on reaching it, so the body still shows every step in order.
|
|
132
133
|
- Name every file under `references/` in the body at the point a session reads it, since an unnamed reference is never loaded.
|
|
134
|
+
- Open a file under `references/` running over 100 lines with a `## Contents` H2 of anchor links after its H1 and intro, so a session that reads only the top of the file still sees everything it holds.
|
|
133
135
|
- Keep the trigger, the skip condition, and the guard in the body. A run that never reaches the block has to decide that without opening the reference.
|
|
134
136
|
- Never point one skill at a sibling skill's folder for a reference both read. Each skill carries its own copy under `references/`, generated rather than hand-copied by the rule in `## Path resolution`.
|
|
135
137
|
|
package/standards/wiki.md
CHANGED
|
@@ -47,9 +47,18 @@ A page failing either is non-conforming even when it satisfies every shape rule
|
|
|
47
47
|
## Sourcing
|
|
48
48
|
|
|
49
49
|
- Close the intro paragraph with a `Source:` sentence naming the owner. Link the canonical page where one exists, and name the owner alone where the subject has no single URL.
|
|
50
|
+
- Link a docs page in its fetchable form, `https://code.claude.com/docs/en/<page>.md`, so a session reads the live text rather than a copy.
|
|
50
51
|
- Fetch current information through the `claude-code-guide` agent when the subject is Claude Code. Do not work from training knowledge.
|
|
51
52
|
- Propose an addition or correction and wait for confirmation. Do not write to a wiki file unasked.
|
|
52
53
|
|
|
54
|
+
## Shape
|
|
55
|
+
|
|
56
|
+
- Keep a page thin: the `Source:` sentence, an orientation paragraph, and lesson sections. The source owns the reference detail and a paraphrase of it falls behind within days.
|
|
57
|
+
- Apply the lesson test per section: keep a fact about the subject only when the source page does not state it. Such a fact is a gotcha this project hit, a constraint it relies on, or how it uses the feature.
|
|
58
|
+
- Read the current source before keeping or cutting a section. A fact kept from memory is the drift this shape exists to prevent.
|
|
59
|
+
- Send a session that wants reference detail to the source and fetch it live. The page answers orientation and lessons only.
|
|
60
|
+
- Leave a page with no lessons as the source link and the orientation paragraph. A catalog routes a reader by page, so the stub stays.
|
|
61
|
+
|
|
53
62
|
## Template
|
|
54
63
|
|
|
55
64
|
```markdown
|
|
@@ -60,9 +69,9 @@ description: <one line naming what this page covers>
|
|
|
60
69
|
|
|
61
70
|
# <Subject>
|
|
62
71
|
|
|
63
|
-
<What the subject is and why it matters.> Source: <owner, with a link to the canonical page where one exists>.
|
|
72
|
+
<What the subject is and why it matters, in a short orientation.> Source: <owner, with a link to the canonical page where one exists>.
|
|
64
73
|
|
|
65
|
-
## <
|
|
74
|
+
## <Lesson>
|
|
66
75
|
|
|
67
|
-
<
|
|
76
|
+
<A fact the source page does not state.>
|
|
68
77
|
```
|
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
# Say so and pass rather than failing a close nobody can fix.
|
|
17
17
|
- name: Skip a fork pull request
|
|
18
18
|
if: github.event.pull_request.head.repo.full_name != github.repository
|
|
19
|
-
run: echo "::notice::Fork pull request, so the token cannot edit the evidence comment. The
|
|
19
|
+
run: echo "::notice::Fork pull request, so the token cannot edit the evidence comment. The preview line stays."
|
|
20
20
|
|
|
21
21
|
- name: Setup Bun
|
|
22
22
|
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
with:
|
|
25
25
|
bun-version: latest
|
|
26
26
|
|
|
27
|
-
- name:
|
|
27
|
+
- name: Drop the preview line from the evidence comment
|
|
28
28
|
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
29
29
|
env:
|
|
30
30
|
GH_TOKEN: ${{ github.token }}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
# The bound on a nested background dispatch, and the recording behind it.
|
|
4
|
-
#
|
|
5
|
-
# An arm invoked without the narration its fixture states dispatched a real
|
|
6
|
-
# `claude --bg` session against the machine's own process table, and nothing in
|
|
7
|
-
# the harness noticed. `snapshot_tree` reads the sandbox and `snapshot_root`
|
|
8
|
-
# reads four scratch directories, and a dispatched session writes into none of
|
|
9
|
-
# them, so the escape watch reported clean throughout and was right to. The run
|
|
10
|
-
# spent real cost until a person found it, and `SIGTERM` alone did not end it.
|
|
11
|
-
#
|
|
12
|
-
# Three mechanisms sit here rather than in `sandbox/run.sh`, which is the
|
|
13
|
-
# only caller. Each is reachable from a test that never launches a session:
|
|
14
|
-
# `src/sandbox-dispatch.test.ts` drives the shim against a stub binary and the
|
|
15
|
-
# reap against a `sleep`, where proving either through `run.sh` would mean
|
|
16
|
-
# spawning the thing the bound exists to prevent.
|
|
17
|
-
|
|
18
|
-
# The prevention. Writes a `claude` that refuses a background dispatch by flag
|
|
19
|
-
# name and delegates everything else, for `run.sh` to place first on the PATH of
|
|
20
|
-
# the session it spawns.
|
|
21
|
-
#
|
|
22
|
-
# The real binary is baked into the file rather than passed through the
|
|
23
|
-
# environment. An env var carrying it would sit in the spawned session's own
|
|
24
|
-
# environment, which hands any arm the exact string that walks around the shim.
|
|
25
|
-
#
|
|
26
|
-
# It names itself in its refusal. No arm shells to `claude` today, and one
|
|
27
|
-
# written tomorrow would meet this and read it as the harness being broken
|
|
28
|
-
# unless the text says which layer refused and why.
|
|
29
|
-
#
|
|
30
|
-
# It is not the whole bound. A dispatch reaching the binary by an absolute path
|
|
31
|
-
# never resolves through PATH at all, which is what `reap_process_group`
|
|
32
|
-
# backstops.
|
|
33
|
-
install_dispatch_shim() {
|
|
34
|
-
local dir="$1"
|
|
35
|
-
local real="$2"
|
|
36
|
-
|
|
37
|
-
cat >"$dir/claude" <<SHIM
|
|
38
|
-
#!/usr/bin/env bash
|
|
39
|
-
# Generated by install_dispatch_shim in scripts/lib/sandbox-dispatch.sh.
|
|
40
|
-
for arg in "\$@"; do
|
|
41
|
-
case "\$arg" in
|
|
42
|
-
--bg | --background)
|
|
43
|
-
echo "canon sandbox harness: refusing \$arg. A sandbox run may not dispatch a background session, so this shim stands first on PATH in place of the real claude binary. Drive the refusal the fixture asks for, or run this outside the harness." >&2
|
|
44
|
-
exit 64
|
|
45
|
-
;;
|
|
46
|
-
esac
|
|
47
|
-
done
|
|
48
|
-
exec "$real" "\$@"
|
|
49
|
-
SHIM
|
|
50
|
-
|
|
51
|
-
chmod +x "$dir/claude"
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
# True while any process still carries this group id. Reads the whole table
|
|
55
|
-
# rather than `ps -g`, which selects by session on some builds and reports an
|
|
56
|
-
# empty group as a clean exit either way.
|
|
57
|
-
process_group_alive() {
|
|
58
|
-
ps -eo pgid= 2>/dev/null | tr -d ' ' | grep -qx "$1"
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
# The backstop. Signals a process group `run.sh` created, escalating rather than
|
|
62
|
-
# sending one signal and reporting success, since the dispatch that produced this
|
|
63
|
-
# row took two signals to reap.
|
|
64
|
-
#
|
|
65
|
-
# Prints its outcome and always exits zero. Every caller runs under `set -e`, and
|
|
66
|
-
# a survivor is something to report rather than a reason to abandon the verdict
|
|
67
|
-
# the run already took.
|
|
68
|
-
#
|
|
69
|
-
# The group has to be one the run created, and the refusal below is what makes
|
|
70
|
-
# that property travel with the function rather than living in one caller.
|
|
71
|
-
# `run.sh` reads the harness group once and reports `inherited` when the session
|
|
72
|
-
# failed to lead a group of its own, which is a diagnosis; this is the floor
|
|
73
|
-
# under it, and under every caller after it, because the cost of getting the
|
|
74
|
-
# argument wrong is the operator's own shell.
|
|
75
|
-
#
|
|
76
|
-
# What it cannot reach is a dispatch that called `setsid` on its way out, which
|
|
77
|
-
# leaves the group before this reads it. That is the half the shim covers.
|
|
78
|
-
reap_process_group() {
|
|
79
|
-
local pgid="$1"
|
|
80
|
-
|
|
81
|
-
if [ "$pgid" = "$(ps -o pgid= -p $$ 2>/dev/null | tr -d ' ')" ]; then
|
|
82
|
-
printf 'refused-own-group\n'
|
|
83
|
-
return 0
|
|
84
|
-
fi
|
|
85
|
-
|
|
86
|
-
if ! process_group_alive "$pgid"; then
|
|
87
|
-
printf 'clear\n'
|
|
88
|
-
return 0
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
kill -TERM -"$pgid" 2>/dev/null || true
|
|
92
|
-
wait_for_group_exit "$pgid"
|
|
93
|
-
|
|
94
|
-
if ! process_group_alive "$pgid"; then
|
|
95
|
-
printf 'reaped-term\n'
|
|
96
|
-
return 0
|
|
97
|
-
fi
|
|
98
|
-
|
|
99
|
-
kill -KILL -"$pgid" 2>/dev/null || true
|
|
100
|
-
wait_for_group_exit "$pgid"
|
|
101
|
-
|
|
102
|
-
if process_group_alive "$pgid"; then
|
|
103
|
-
printf 'survived\n'
|
|
104
|
-
else
|
|
105
|
-
printf 'reaped-kill\n'
|
|
106
|
-
fi
|
|
107
|
-
return 0
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
# Five seconds per signal. A shorter window reports a survivor for a process
|
|
111
|
-
# that was already exiting, and a longer one stalls a run whose verdict is
|
|
112
|
-
# already taken.
|
|
113
|
-
wait_for_group_exit() {
|
|
114
|
-
local pgid="$1"
|
|
115
|
-
local waited=0
|
|
116
|
-
|
|
117
|
-
while [ "$waited" -lt 20 ] && process_group_alive "$pgid"; do
|
|
118
|
-
sleep 0.25
|
|
119
|
-
waited=$((waited + 1))
|
|
120
|
-
done
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
# The client's own session registry, which is the only surface a nested dispatch
|
|
124
|
-
# leaves a trace on that this harness can read. It is client-owned and carries no
|
|
125
|
-
# contract, so a client that stops writing a record per session breaks the
|
|
126
|
-
# detection silently. That is why what reads it reports rather than asserts.
|
|
127
|
-
sessions_dir() {
|
|
128
|
-
printf '%s/sessions\n' "${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
# Set whenever the registry directory existed at snapshot time. An absent
|
|
132
|
-
# registry produces the same empty manifest a quiet run does, and the two mean
|
|
133
|
-
# opposite things, so the report carries this rather than letting an unwatched
|
|
134
|
-
# run read as a clean one. Same distinction `escape_watched` draws in `run.sh`,
|
|
135
|
-
# which is also the only reader, hence the exemption on the write below.
|
|
136
|
-
sessions_watched=0
|
|
137
|
-
|
|
138
|
-
# Record names only, never hashes. A live session rewrites its own record on
|
|
139
|
-
# every status change, so a content manifest would name every session running
|
|
140
|
-
# beside this one, which is the noise the escape watch was already narrowed to
|
|
141
|
-
# avoid. A record that appears between the two snapshots is a session that
|
|
142
|
-
# started during the run, and that is the whole question.
|
|
143
|
-
snapshot_sessions() {
|
|
144
|
-
local manifest="$1"
|
|
145
|
-
local dir
|
|
146
|
-
dir="$(sessions_dir)"
|
|
147
|
-
|
|
148
|
-
: >"$manifest"
|
|
149
|
-
[ -d "$dir" ] || return 0
|
|
150
|
-
# shellcheck disable=SC2034
|
|
151
|
-
sessions_watched=1
|
|
152
|
-
|
|
153
|
-
find "$dir" -maxdepth 1 -type f -name '*.json' 2>/dev/null |
|
|
154
|
-
sed 's|.*/||' | sort >"$manifest"
|
|
155
|
-
return 0
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
# The new side alone, unlike `writes_between`. A record that vanished is a
|
|
159
|
-
# session that ended and a record that changed is one that was already running,
|
|
160
|
-
# and neither is a dispatch this run made.
|
|
161
|
-
sessions_between() {
|
|
162
|
-
comm -13 "$1" "$2"
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
# The side `sessions_between` drops. A record present on both sides is a session
|
|
166
|
-
# that was already running before this run started and still was after, which
|
|
167
|
-
# rules it out as this run's own dispatch and rules it in as a witness able to
|
|
168
|
-
# explain a write the escape watch attributes to nobody.
|
|
169
|
-
sessions_concurrent() {
|
|
170
|
-
comm -12 "$1" "$2"
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
# Turns a record name into a line a person can act on. The file can be gone by
|
|
174
|
-
# the time this reads it, since a session that started and exited inside the run
|
|
175
|
-
# takes its record with it, so an unreadable record still reports its name rather
|
|
176
|
-
# than dropping out of the list.
|
|
177
|
-
#
|
|
178
|
-
# One record is one line. The name is written by whatever peer claimed the
|
|
179
|
-
# session, so a newline inside it would split one record across two entries in a
|
|
180
|
-
# list every reader takes as one line each.
|
|
181
|
-
describe_session() {
|
|
182
|
-
local record desc
|
|
183
|
-
record="$(sessions_dir)/$1"
|
|
184
|
-
|
|
185
|
-
desc="$(jq -r '"\(.name // "unnamed") in \(.cwd // "an unrecorded directory")"
|
|
186
|
-
| gsub("\\s+"; " ")' "$record" 2>/dev/null || true)"
|
|
187
|
-
[ -z "$desc" ] && desc="record already gone"
|
|
188
|
-
|
|
189
|
-
printf '%s: %s\n' "$1" "$desc"
|
|
190
|
-
}
|