@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/src/sandbox/tree.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
1
2
|
import { randomBytes } from 'node:crypto'
|
|
2
3
|
import { homedir } from 'node:os'
|
|
3
4
|
import { join } from 'node:path'
|
|
@@ -5,10 +6,11 @@ import { join } from 'node:path'
|
|
|
5
6
|
/**
|
|
6
7
|
* Mints a short per-run identifier the first time it is asked for and holds it
|
|
7
8
|
* in `CANON_SANDBOX_RUN_ID` for the rest of this process, so a script that
|
|
8
|
-
* spawns a child inheriting `process.env` — `run
|
|
9
|
-
* and then `canon sandbox check` — resolves the same tree in every one
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* spawns a child inheriting `process.env` — `canon sandbox run` calling
|
|
10
|
+
* `canon sandbox` to provision and then `canon sandbox check` — resolves the same tree in every one
|
|
11
|
+
* of them, as do the hook and installer children provisioning spawns. A process
|
|
12
|
+
* that already carries the variable, inherited from such a parent, reuses it
|
|
13
|
+
* rather than minting a new one.
|
|
12
14
|
*
|
|
13
15
|
* Twin of `mint_sandbox_run_id` in `scripts/lib/sandbox-path.sh`.
|
|
14
16
|
*/
|
|
@@ -45,3 +47,96 @@ export function sandboxTree(): string {
|
|
|
45
47
|
|
|
46
48
|
return join(base, 'canon', `sandbox-${mintSandboxRunId()}`)
|
|
47
49
|
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Lexical rather than `realpath`, since the guard runs before the tree exists,
|
|
53
|
+
* so nothing here follows a symlink.
|
|
54
|
+
*/
|
|
55
|
+
export function normalizeSandboxPath(path: string): string {
|
|
56
|
+
if (path === '') return ''
|
|
57
|
+
|
|
58
|
+
const isAbsolute = path.startsWith('/')
|
|
59
|
+
const resolved: string[] = []
|
|
60
|
+
let climbed = ''
|
|
61
|
+
|
|
62
|
+
for (const segment of path.split('/')) {
|
|
63
|
+
if (segment === '' || segment === '.') continue
|
|
64
|
+
if (segment !== '..') resolved.push(segment)
|
|
65
|
+
else if (resolved.length > 0) resolved.pop()
|
|
66
|
+
else if (!isAbsolute) climbed += '../'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (isAbsolute) return `/${resolved.join('/')}`
|
|
70
|
+
|
|
71
|
+
const relative = `${climbed}${resolved.join('/')}`.replace(/\/+$/, '')
|
|
72
|
+
|
|
73
|
+
return relative === '' ? '.' : relative
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Whether `candidate` is `target` or a directory containing it. */
|
|
77
|
+
function isAtOrAbove(candidate: string, target: string): boolean {
|
|
78
|
+
return candidate === target || target.startsWith(`${candidate}/`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface SandboxRoots {
|
|
82
|
+
readonly home: string
|
|
83
|
+
readonly temp: string
|
|
84
|
+
readonly mainRoot: string
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The roots the guard measures against. The repository test reads the main
|
|
89
|
+
* worktree rather than `PROJECT_ROOT`, since a linked worktree sits inside it.
|
|
90
|
+
*/
|
|
91
|
+
export function sandboxRoots(projectRoot: string): SandboxRoots {
|
|
92
|
+
const listing = spawnSync('git', ['worktree', 'list', '--porcelain'], {
|
|
93
|
+
cwd: projectRoot,
|
|
94
|
+
encoding: 'utf8',
|
|
95
|
+
})
|
|
96
|
+
const line = (listing.stdout ?? '')
|
|
97
|
+
.split('\n')
|
|
98
|
+
.find((l) => l.startsWith('worktree '))
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
home: process.env.HOME || '/root',
|
|
102
|
+
temp: process.env.TMPDIR || '/tmp',
|
|
103
|
+
mainRoot: line === undefined ? projectRoot : line.slice('worktree '.length),
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Returns the reason a location cannot hold the tree, or undefined when it can.
|
|
109
|
+
* Provisioning removes the tree before staging, so the test is an allowlist: a
|
|
110
|
+
* strict descendant of the home folder or the temp root, outside the main
|
|
111
|
+
* worktree in both directions.
|
|
112
|
+
*/
|
|
113
|
+
export function assertSandboxDirSafe(
|
|
114
|
+
raw: string,
|
|
115
|
+
roots: SandboxRoots,
|
|
116
|
+
): string | undefined {
|
|
117
|
+
if (!raw.startsWith('/'))
|
|
118
|
+
return `CANON_SANDBOX_DIR must be an absolute path, got: ${raw || '<empty>'}`
|
|
119
|
+
|
|
120
|
+
if (raw.length > 4096)
|
|
121
|
+
return `Refusing the sandbox path. It is ${raw.length} characters, past the longest path any filesystem here accepts.`
|
|
122
|
+
|
|
123
|
+
const dir = normalizeSandboxPath(raw)
|
|
124
|
+
const home = normalizeSandboxPath(roots.home)
|
|
125
|
+
const temp = normalizeSandboxPath(roots.temp)
|
|
126
|
+
const mainRoot = normalizeSandboxPath(roots.mainRoot)
|
|
127
|
+
const resolution = dir === raw ? '' : ` It resolves to ${dir}.`
|
|
128
|
+
|
|
129
|
+
if (!isAtOrAbove(home, dir) && !isAtOrAbove(temp, dir))
|
|
130
|
+
return `Refusing ${raw} as the sandbox. Provisioning removes the tree first, so the path has to sit under ${home} or ${temp}.${resolution}`
|
|
131
|
+
|
|
132
|
+
if (dir === home || dir === temp)
|
|
133
|
+
return `Refusing ${raw} as the sandbox. Provisioning removes the tree first, so the path has to sit under ${dir} rather than be it.`
|
|
134
|
+
|
|
135
|
+
if (isAtOrAbove(dir, mainRoot))
|
|
136
|
+
return `Refusing ${raw} as the sandbox. Provisioning removes the tree first, and that path contains ${mainRoot}.${resolution}`
|
|
137
|
+
|
|
138
|
+
if (dir.startsWith(`${mainRoot}/`))
|
|
139
|
+
return `Sandbox at ${raw} sits inside ${mainRoot}, which puts the toolkit CLAUDE.md back on the session ancestor chain.${resolution} Point CANON_SANDBOX_DIR outside the repository.`
|
|
140
|
+
|
|
141
|
+
return undefined
|
|
142
|
+
}
|
package/src/secrets/marker.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { isMarked } from '@/exempt-marker'
|
|
1
|
+
import { isMarked } from '@/sweep/exempt-marker'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The inline token exempting one line from the secret scan.
|
|
5
5
|
*
|
|
6
|
-
* Shaped on the `stub: true` precedent in `src/seed-marker.ts`, which answers
|
|
6
|
+
* Shaped on the `stub: true` precedent in `src/tooling/seed-marker.ts`, which answers
|
|
7
7
|
* a check whose own comment records a false-positive class. The exemption
|
|
8
8
|
* travels with the line it exempts rather than sitting in a path list away
|
|
9
9
|
* from it, so a reader meeting a muted match finds the reason on the spot.
|
package/src/secrets/scan.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
|
-
import { isBinary } from '@/binary'
|
|
4
|
-
import { listRepositoryFiles } from '@/git
|
|
3
|
+
import { isBinary } from '@/sweep/binary'
|
|
4
|
+
import { listRepositoryFiles } from '@/git/files'
|
|
5
5
|
import { isExempt } from '@/secrets/marker'
|
|
6
6
|
import { matchLine } from '@/secrets/patterns'
|
|
7
7
|
import { readShipEntries, selectShipped } from '@/secrets/shipped'
|
package/src/sessions/claim.ts
CHANGED
package/src/sessions/resolve.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from 'node:fs'
|
|
11
11
|
import { basename, dirname, isAbsolute, join, relative } from 'node:path'
|
|
12
12
|
import { $ } from 'bun'
|
|
13
|
-
import { gitEnv } from '@/git
|
|
13
|
+
import { gitEnv } from '@/git/env'
|
|
14
14
|
import { recordDir, recordRoot, SCRATCH } from '@/record-root'
|
|
15
15
|
import { remoteIdentity } from '@/records/backup'
|
|
16
16
|
import {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
|
-
import { isMarked } from '@/exempt-marker'
|
|
3
|
+
import { isMarked } from '@/sweep/exempt-marker'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The corpora a target reader reaches, which is the `files` field less `src`.
|
|
@@ -113,7 +113,7 @@ const COMMIT_SHA = /(?<![0-9A-Za-z_@/#])([0-9a-f]{7,40})(?![0-9A-Za-z_])/g
|
|
|
113
113
|
* one.
|
|
114
114
|
*
|
|
115
115
|
* The literal is hardcoded rather than read from `package.json` or
|
|
116
|
-
* `git remote`, matching `src/github-format.ts` and `src/commands/repo.ts`,
|
|
116
|
+
* `git remote`, matching `src/feedback/github-format.ts` and `src/commands/repo.ts`,
|
|
117
117
|
* which already hardcode it.
|
|
118
118
|
*
|
|
119
119
|
* Same word-boundary discipline as the two patterns above: a word character
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
copyFileSync,
|
|
3
|
-
mkdirSync,
|
|
4
|
-
readdirSync,
|
|
5
|
-
readFileSync,
|
|
6
|
-
writeFileSync,
|
|
7
|
-
} from 'node:fs'
|
|
1
|
+
import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
8
2
|
import { basename, join } from 'node:path'
|
|
9
3
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
10
4
|
import JSZip from 'jszip'
|
|
@@ -42,6 +36,7 @@ import {
|
|
|
42
36
|
type WalkedSlide,
|
|
43
37
|
walkSlide,
|
|
44
38
|
} from '@/slides/convert/walk'
|
|
39
|
+
import { slideFiles } from '@/slides/decks'
|
|
45
40
|
import { embedFonts, type FontNotice } from '@/slides/package/fonts'
|
|
46
41
|
import {
|
|
47
42
|
type EntranceSpec,
|
|
@@ -127,15 +122,6 @@ function refused(reason: ExportRefusal, message: string): ExportResult {
|
|
|
127
122
|
return { status: 'refused', reason, message }
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
/** Every `.html` file directly in the folder, in filename order. */
|
|
131
|
-
export function slideFiles(sourceDir: string): string[] {
|
|
132
|
-
return readdirSync(sourceDir, { withFileTypes: true })
|
|
133
|
-
.filter((entry) => entry.isFile() && entry.name.endsWith('.html'))
|
|
134
|
-
.map((entry) => entry.name)
|
|
135
|
-
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))
|
|
136
|
-
.map((name) => join(sourceDir, name))
|
|
137
|
-
}
|
|
138
|
-
|
|
139
125
|
/** A picture whose bytes the post-write pass replaces or whose corners it rounds. */
|
|
140
126
|
interface Patch {
|
|
141
127
|
readonly slide: number
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
2
|
+
import { join, relative, resolve } from 'node:path'
|
|
3
|
+
import { creationRel, recordDir } from '@/record-root'
|
|
4
|
+
import { readDeck } from '@/slides/convert/deck'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A deck is a folder under the record root's `slides/`, holding its `.html`
|
|
8
|
+
* slides, an optional `deck.json`, and its assets. `layouts/` beside the decks
|
|
9
|
+
* holds the project's shared layouts and is never a deck itself.
|
|
10
|
+
*/
|
|
11
|
+
export const SLIDES_FOLDER = 'slides'
|
|
12
|
+
|
|
13
|
+
export const LAYOUTS_FOLDER = 'layouts'
|
|
14
|
+
|
|
15
|
+
export interface Deck {
|
|
16
|
+
readonly name: string
|
|
17
|
+
/** From `deck.json`, falling back to the folder name as the export does. */
|
|
18
|
+
readonly title: string
|
|
19
|
+
readonly slides: number
|
|
20
|
+
/** Relative to the project root. */
|
|
21
|
+
readonly path: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DeckRefusal = 'no-decks' | 'ambiguous' | 'no-deck'
|
|
25
|
+
|
|
26
|
+
export type DeckResolution =
|
|
27
|
+
| { readonly status: 'resolved'; readonly dir: string }
|
|
28
|
+
| {
|
|
29
|
+
readonly status: 'refused'
|
|
30
|
+
readonly reason: DeckRefusal
|
|
31
|
+
readonly message: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Every `.html` file directly in the folder, in filename order. */
|
|
35
|
+
export function slideFiles(dir: string): string[] {
|
|
36
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
37
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.html'))
|
|
38
|
+
.map((entry) => entry.name)
|
|
39
|
+
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))
|
|
40
|
+
.map((name) => join(dir, name))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function listDecks(root: string): Deck[] {
|
|
44
|
+
const dir = recordDir(root, SLIDES_FOLDER)
|
|
45
|
+
if (!isDirectory(dir)) return []
|
|
46
|
+
|
|
47
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
48
|
+
.filter((entry) => entry.isDirectory() && entry.name !== LAYOUTS_FOLDER)
|
|
49
|
+
.map((entry) => entry.name)
|
|
50
|
+
.sort((a, b) => a.localeCompare(b))
|
|
51
|
+
.flatMap((name) => {
|
|
52
|
+
const deckDir = join(dir, name)
|
|
53
|
+
const slides = slideFiles(deckDir).length
|
|
54
|
+
if (slides === 0) return []
|
|
55
|
+
const read = readDeck(deckDir)
|
|
56
|
+
const title = read.status === 'read' ? read.deck.title : name
|
|
57
|
+
return [{ name, title, slides, path: relative(root, deckDir) }]
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The folder `render` reads. A deck name wins over a folder of the same name
|
|
63
|
+
* relative to the root, and no name at all takes the only deck there is.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveDeck(
|
|
66
|
+
root: string,
|
|
67
|
+
target: string | undefined,
|
|
68
|
+
): DeckResolution {
|
|
69
|
+
const decks = listDecks(root)
|
|
70
|
+
const at = creationRel(root, SLIDES_FOLDER)
|
|
71
|
+
|
|
72
|
+
if (target === undefined) {
|
|
73
|
+
const [only, ...rest] = decks
|
|
74
|
+
if (only === undefined) {
|
|
75
|
+
return refuse('no-decks', `No deck under ${at}/. Draw one there first.`)
|
|
76
|
+
}
|
|
77
|
+
if (rest.length > 0) {
|
|
78
|
+
return refuse(
|
|
79
|
+
'ambiguous',
|
|
80
|
+
`${decks.length} decks under ${at}/, name one: ${names(decks)}`,
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
return { status: 'resolved', dir: join(root, only.path) }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const named = decks.find((deck) => deck.name === target)
|
|
87
|
+
if (named) return { status: 'resolved', dir: join(root, named.path) }
|
|
88
|
+
|
|
89
|
+
const folder = resolve(root, target)
|
|
90
|
+
if (isDirectory(folder)) return { status: 'resolved', dir: folder }
|
|
91
|
+
|
|
92
|
+
return refuse(
|
|
93
|
+
'no-deck',
|
|
94
|
+
decks.length === 0
|
|
95
|
+
? `${target} is neither a deck under ${at}/ nor a folder`
|
|
96
|
+
: `${target} is neither a deck nor a folder. Decks: ${names(decks)}`,
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function names(decks: readonly Deck[]): string {
|
|
101
|
+
return decks.map((deck) => deck.name).join(', ')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function refuse(reason: DeckRefusal, message: string): DeckResolution {
|
|
105
|
+
return { status: 'refused', reason, message }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isDirectory(path: string): boolean {
|
|
109
|
+
return existsSync(path) && statSync(path).isDirectory()
|
|
110
|
+
}
|
|
@@ -152,9 +152,13 @@ export function eotOf(bytes: Uint8Array): EotResult {
|
|
|
152
152
|
}
|
|
153
153
|
const strings = names(font, name)
|
|
154
154
|
const padding = Buffer.alloc(2)
|
|
155
|
-
// RootStringCheckSum, EUDCCodePage, Padding6, SignatureSize,
|
|
156
|
-
// and EUDCFontSize,
|
|
155
|
+
// RootStringCheckSum, then EUDCCodePage, Padding6, SignatureSize,
|
|
156
|
+
// EUDCFlags, and EUDCFontSize, zero for a face with no EUDC data. The
|
|
157
|
+
// checksum is the root string's byte sum XOR 0x50475342, so an empty root
|
|
158
|
+
// string still writes the constant, and PowerPoint refuses to install a
|
|
159
|
+
// face whose checksum is zero as tampered with.
|
|
157
160
|
const tail = Buffer.alloc(20)
|
|
161
|
+
tail.writeUInt32LE(0x50475342, 0)
|
|
158
162
|
const eot = Buffer.concat([
|
|
159
163
|
header(font, os2.offset, head.offset),
|
|
160
164
|
padding,
|
package/src/standards/audit.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
2
2
|
import { basename, join } from 'node:path'
|
|
3
3
|
import { $ } from 'bun'
|
|
4
|
-
import { gitEnv } from '@/git
|
|
5
|
-
import { resolveBaseRef } from '@/git
|
|
4
|
+
import { gitEnv } from '@/git/env'
|
|
5
|
+
import { resolveBaseRef } from '@/git/files'
|
|
6
6
|
import { INDEX_FILE, standardsSourceDir } from '@/standards/read'
|
|
7
7
|
|
|
8
8
|
/** Returned when a standard new to this branch states no success criterion under either heading `CRITERION_HEADING` accepts, the gating check. */
|
package/src/standards/read.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
2
|
import { basename, join } from 'node:path'
|
|
3
|
-
import { stripFrontmatter } from '@/frontmatter'
|
|
3
|
+
import { stripFrontmatter } from '@/markdown/frontmatter'
|
|
4
4
|
import { PROJECT_ROOT } from '@/project-root'
|
|
5
5
|
|
|
6
6
|
export const INDEX_FILE = 'index.md'
|
package/src/sync/check.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { basename, join, sep } from 'node:path'
|
|
3
3
|
import { execa } from 'execa'
|
|
4
|
-
import { gitEnv } from '@/git
|
|
4
|
+
import { gitEnv } from '@/git/env'
|
|
5
5
|
import { createDesignAdapter, DESIGN_INSTALL_DIR } from '@/design/adapter'
|
|
6
6
|
import { createGovAdapter, rulesSourceDir } from '@/gov/adapter'
|
|
7
7
|
import { successorResolver } from '@/gov/renames'
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
stampedCommit,
|
|
30
30
|
type StampDomain,
|
|
31
31
|
} from '@/sync/stamp'
|
|
32
|
-
import { isDirectory } from '@/
|
|
32
|
+
import { isDirectory } from '@/targets/validate'
|
|
33
33
|
import {
|
|
34
34
|
isWholeStack,
|
|
35
35
|
loadManifest,
|
package/src/sync/engine.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs'
|
|
2
2
|
import { rm } from 'node:fs/promises'
|
|
3
3
|
import { isAbsolute, relative, resolve } from 'node:path'
|
|
4
|
-
import { copyPreservingMode } from '@/copy'
|
|
4
|
+
import { copyPreservingMode } from '@/sync/copy'
|
|
5
5
|
import { checkoutMismatchWarning } from '@/project-root'
|
|
6
6
|
import { findInstalledOrigin, readHistoryIndex } from '@/sync/history'
|
|
7
7
|
import {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
toStampKey,
|
|
17
17
|
writeStamp,
|
|
18
18
|
} from '@/sync/stamp'
|
|
19
|
-
import { isDirectory } from '@/
|
|
19
|
+
import { isDirectory } from '@/targets/validate'
|
|
20
20
|
import {
|
|
21
21
|
intro,
|
|
22
22
|
isNonInteractive,
|
package/src/sync/git.ts
CHANGED
package/src/sync/history.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto'
|
|
|
2
2
|
import { readFileSync } from 'node:fs'
|
|
3
3
|
import { sep } from 'node:path'
|
|
4
4
|
import { execaSync } from 'execa'
|
|
5
|
-
import { gitEnv } from '@/git
|
|
5
|
+
import { gitEnv } from '@/git/env'
|
|
6
6
|
|
|
7
7
|
/** Blob SHA to the newest commit whose post-image for that path held it. */
|
|
8
8
|
export type PathHistory = ReadonlyMap<string, string>
|
package/src/sync/reverse.ts
CHANGED
package/src/sync/seeds-report.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs'
|
|
2
2
|
import { relative } from 'node:path'
|
|
3
3
|
import { planSeeds, type Seed } from '@/claude/seeds'
|
|
4
|
-
import { rewritesOnInstall, stripSeedMarker } from '@/seed-marker'
|
|
4
|
+
import { rewritesOnInstall, stripSeedMarker } from '@/tooling/seed-marker'
|
|
5
5
|
import { findInstalledOrigin, readHistoryIndex } from '@/sync/history'
|
|
6
6
|
|
|
7
7
|
/**
|
package/src/sync/target.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
3
|
import { DESIGN_INSTALL_DIR } from '@/design/adapter'
|
|
4
|
-
import { isDirectory } from '@/
|
|
4
|
+
import { isDirectory } from '@/targets/validate'
|
|
5
5
|
|
|
6
6
|
export const SYNC_DOMAINS = ['governance', 'design', 'claude'] as const
|
|
7
7
|
|
package/src/sync/workflow.ts
CHANGED
package/src/targets/pulls.ts
CHANGED
package/src/targets/sweep.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readdirSync } from 'node:fs'
|
|
2
2
|
import { join, resolve } from 'node:path'
|
|
3
3
|
import { $ } from 'bun'
|
|
4
|
-
import { gitEnv } from '@/git
|
|
4
|
+
import { gitEnv } from '@/git/env'
|
|
5
5
|
import {
|
|
6
6
|
claudeCanonStampPath,
|
|
7
7
|
isLegacyStamped,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
retiredNameStampPath,
|
|
10
10
|
stampPath,
|
|
11
11
|
} from '@/sync/stamp'
|
|
12
|
-
import { isDirectory } from '@/
|
|
12
|
+
import { isDirectory } from '@/targets/validate'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Folders a walk never descends into.
|
package/src/tasks/answers.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { readFile } from 'node:fs/promises'
|
|
3
3
|
import { isAbsolute, relative, resolve } from 'node:path'
|
|
4
|
-
import { isUnder } from '@/paths'
|
|
4
|
+
import { isUnder } from '@/tasks/paths'
|
|
5
5
|
import { recordDir, recordDirs } from '@/record-root'
|
|
6
6
|
import {
|
|
7
7
|
hasStagedBatches,
|
package/src/tasks/archive.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from 'node:fs'
|
|
|
2
2
|
import { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { basename, dirname, join, relative, resolve, sep } from 'node:path'
|
|
4
4
|
import { regenOne } from '@/indexes/regen'
|
|
5
|
-
import { isUnder } from '@/paths'
|
|
5
|
+
import { isUnder } from '@/tasks/paths'
|
|
6
6
|
import { recordDir, recordDirs } from '@/record-root'
|
|
7
7
|
|
|
8
8
|
const TASKS = 'tasks'
|
package/src/tasks/reach.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { readdir, readFile } from 'node:fs/promises'
|
|
3
3
|
import { basename, join } from 'node:path'
|
|
4
|
-
import { listChangedFiles, resolveBaseRef } from '@/git
|
|
4
|
+
import { listChangedFiles, resolveBaseRef } from '@/git/files'
|
|
5
5
|
import { recordDir } from '@/record-root'
|
|
6
6
|
import { splitPlanSections } from '@/records/validate'
|
|
7
7
|
import { type AnswersRefused, resolvePlanReference } from '@/tasks/answers'
|
package/src/tasks/trunk.ts
CHANGED
package/src/teach/nav.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from '@/design/components'
|
|
8
8
|
import { buildDesignCss } from '@/design/css'
|
|
9
9
|
import { FAVICON_COLORS, faviconLink, renderFavicon } from '@/design/favicon'
|
|
10
|
-
import { stripFrontmatter } from '@/frontmatter'
|
|
10
|
+
import { stripFrontmatter } from '@/markdown/frontmatter'
|
|
11
11
|
import { parseFrontmatter, readField } from '@/indexes/frontmatter'
|
|
12
12
|
import { PROJECT_ROOT } from '@/project-root'
|
|
13
13
|
import { compileScript } from '@/teach/browser/compile'
|
package/src/tooling/inject.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { existsSync } from 'node:fs'
|
|
|
2
2
|
import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { dirname, join, relative } from 'node:path'
|
|
4
4
|
import { $ } from 'bun'
|
|
5
|
-
import { copyPreservingMode } from '@/copy'
|
|
6
|
-
import { rewritesOnInstall, stripSeedMarker } from '@/seed-marker'
|
|
5
|
+
import { copyPreservingMode } from '@/sync/copy'
|
|
6
|
+
import { rewritesOnInstall, stripSeedMarker } from '@/tooling/seed-marker'
|
|
7
7
|
import { resolveSurfacePath } from '@/surface-root'
|
|
8
8
|
import { mergeSections, pruneSections } from '@/tooling/gitignore'
|
|
9
9
|
import {
|
package/src/tooling/subfolder.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, realpathSync } from 'node:fs'
|
|
2
2
|
import { basename, join, relative } from 'node:path'
|
|
3
|
-
import { gitEnv } from '@/git
|
|
3
|
+
import { gitEnv } from '@/git/env'
|
|
4
4
|
import { isWholeStack, type Manifest, seedFiles } from '@/tooling/manifest'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isMarked } from '@/exempt-marker'
|
|
1
|
+
import { isMarked } from '@/sweep/exempt-marker'
|
|
2
2
|
|
|
3
3
|
export const README_PARAPHRASE_MARKER = 'canon-allow-readme-paraphrase'
|
|
4
4
|
|
|
@@ -34,7 +34,7 @@ const QUOTED_PHRASE = /"([^"]+)"/g
|
|
|
34
34
|
* retired `README.md:<n>` form, reported rather than accepted so the fragile
|
|
35
35
|
* convention this replaces cannot come back on a later edit.
|
|
36
36
|
*
|
|
37
|
-
* Modeled on `clientCommandCitationsIn` in `src/client-commands.ts`, including
|
|
37
|
+
* Modeled on `clientCommandCitationsIn` in `src/gate/client-commands.ts`, including
|
|
38
38
|
* its use of `isMarked` for the exemption.
|
|
39
39
|
*/
|
|
40
40
|
export function readmeCitationsIn(
|
package/src/worktrees/reclaim.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $ } from 'bun'
|
|
2
2
|
import { execa } from 'execa'
|
|
3
3
|
import { existsSync } from 'node:fs'
|
|
4
|
-
import { gitEnv } from '@/git
|
|
4
|
+
import { gitEnv } from '@/git/env'
|
|
5
5
|
import {
|
|
6
6
|
repositoryOf,
|
|
7
7
|
type ResolvedSession,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
currentWorktreeRoot,
|
|
13
13
|
listWorktrees,
|
|
14
14
|
type WorktreeEntry,
|
|
15
|
-
} from '@/worktree'
|
|
15
|
+
} from '@/git/worktree'
|
|
16
16
|
|
|
17
17
|
const GH_TIMEOUT_MS = 30_000
|
|
18
18
|
|
package/src/worktrees/remove.ts
CHANGED
|
@@ -54,6 +54,7 @@ Use `## Overview`, `## Key technical decisions` with one named H3 per decision,
|
|
|
54
54
|
|
|
55
55
|
- Rewrite a decision a later one changed rather than appending the change beside it. A reader should find the design that stands in one place, with the alternative that lost stated once.
|
|
56
56
|
- Hold only what is open under `## Risks / open questions`. An entry leaves the section in the change that settles it, becoming a decision here when it fills a slot and moving to the domain context entry it constrains when it does not.
|
|
57
|
+
- Carry an optional `reviewed: YYYY-MM-DD` frontmatter field naming the day someone last read the record whole for 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.
|
|
57
58
|
|
|
58
59
|
## Verification anchors
|
|
59
60
|
|