@erclx/canon 5.67.0 → 5.69.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -1
  3. package/claude/.claude-plugin/plugin.json +1 -1
  4. package/claude/skills/app-drive/REQUIREMENT.md +5 -5
  5. package/claude/skills/app-drive/SKILL.md +14 -4
  6. package/claude/skills/app-drive/references/drive-record.md +12 -1
  7. package/claude/skills/canon-cli/SKILL.md +2 -2
  8. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
  9. package/claude/skills/canon-feedback/SKILL.md +1 -1
  10. package/claude/skills/design-identity/REQUIREMENT.md +4 -4
  11. package/claude/skills/design-identity/SKILL.md +7 -7
  12. package/claude/skills/{pick-by-eye → design-pick}/REQUIREMENT.md +6 -6
  13. package/claude/skills/{pick-by-eye → design-pick}/SKILL.md +18 -10
  14. package/claude/skills/{pick-by-eye → design-pick}/references/board.md +17 -11
  15. package/claude/skills/design-pick/references/design-config.md +33 -0
  16. package/claude/skills/design-record/REQUIREMENT.md +2 -2
  17. package/claude/skills/design-record/SKILL.md +1 -1
  18. package/claude/skills/design-taste/REQUIREMENT.md +2 -2
  19. package/claude/skills/design-taste/SKILL.md +3 -3
  20. package/claude/skills/design-taste/references/preflight.md +1 -1
  21. package/claude/skills/git-issue/REQUIREMENT.md +1 -1
  22. package/claude/skills/git-issue/references/issue.md +1 -1
  23. package/claude/skills/plan-feature/SKILL.md +1 -1
  24. package/claude/skills/plan-feature/references/plan.md +21 -6
  25. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  26. package/claude/skills/pr-evidence/REQUIREMENT.md +1 -1
  27. package/claude/skills/pr-evidence/SKILL.md +7 -1
  28. package/claude/skills/pr-evidence/references/evidence.md +33 -3
  29. package/claude/skills/review-craft/references/ui.md +30 -10
  30. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +3 -3
  31. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
  32. package/claude/skills/role-orchestrator/references/orchestrator-planning-wait.md +24 -0
  33. package/claude/skills/role-planner/SKILL.md +4 -2
  34. package/claude/skills/role-worker/SKILL.md +5 -6
  35. package/claude/skills/task-board/references/tasks.md +1 -1
  36. package/claude/skills/task-complete/references/receipt-sweep.md +1 -1
  37. package/claude/skills/{ux-audit → ui-audit}/REQUIREMENT.md +3 -3
  38. package/claude/skills/{ux-audit → ui-audit}/SKILL.md +7 -7
  39. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  40. package/claude/skills/ui-craft/SKILL.md +1 -1
  41. package/claude/skills/{ui-record → ui-film}/REQUIREMENT.md +7 -5
  42. package/claude/skills/{ui-record → ui-film}/SKILL.md +23 -12
  43. package/claude/skills/{ui-record → ui-film}/references/config.md +3 -3
  44. package/claude/skills/{ui-record → ui-film}/references/handoff.md +28 -9
  45. package/claude/skills/ui-film/references/pr-clip.md +84 -0
  46. package/claude/skills/{ui-record → ui-film}/references/take-craft.md +8 -1
  47. package/claude/skills/{ux-measure → ui-measure}/REQUIREMENT.md +3 -3
  48. package/claude/skills/{ux-measure → ui-measure}/SKILL.md +6 -6
  49. package/docs/agents/audits.md +1 -1
  50. package/docs/agents/migrate.md +13 -13
  51. package/docs/agents/records.md +1 -0
  52. package/docs/target/migrations.md +12 -10
  53. package/docs/target/projects.md +1 -1
  54. package/docs/target/sync.md +1 -1
  55. package/docs/workflow/skill-map-on-request.md +1 -2
  56. package/docs/workflow/skill-map.md +9 -10
  57. package/docs/workflow/visual-design-workflow.md +6 -1
  58. package/governance/ledger/claude/background.md +26 -0
  59. package/governance/rules/claude/background.md +19 -0
  60. package/governance/stacks/base.toml +1 -0
  61. package/package.json +8 -5
  62. package/scripts/ci/install-playwright-deps.sh +52 -0
  63. package/src/claude/cases/authoring.ts +2 -2
  64. package/src/claude/cases/misc.ts +1 -1
  65. package/src/claude/cases/setup.ts +0 -5
  66. package/src/claude/cases/workflow.ts +6 -6
  67. package/src/commands/fixtures/gh.sh +64 -0
  68. package/src/commands/gov.ts +33 -3
  69. package/src/commands/migrate.ts +12 -2
  70. package/src/commands/pr.ts +237 -79
  71. package/src/commands/take.ts +44 -8
  72. package/src/commands/tasks.ts +183 -0
  73. package/src/gate/stages.ts +2 -2
  74. package/src/gov/audit.ts +48 -11
  75. package/src/gov/detect.ts +1 -1
  76. package/src/markdown/scope.ts +9 -14
  77. package/src/migrate/record-layout.ts +5 -3
  78. package/src/migrate/skill-names.ts +21 -4
  79. package/src/pr/evidence.ts +208 -78
  80. package/src/pr/frames.ts +42 -4
  81. package/src/pr/pixels.ts +44 -0
  82. package/src/records/backup.ts +28 -4
  83. package/src/records/validate.ts +1 -0
  84. package/src/sandbox/headless/dispatch-shim.sh +15 -0
  85. package/src/sandbox/headless/dispatch.ts +12 -14
  86. package/src/sandbox/stub-gh.sh +26 -0
  87. package/src/sandbox/stub-remote.ts +8 -29
  88. package/src/sync/engine.ts +1 -1
  89. package/src/take/camera.ts +2 -2
  90. package/src/take/encode.ts +38 -1
  91. package/src/take/film.ts +26 -3
  92. package/src/take/pointer.ts +169 -0
  93. package/src/take/reel.ts +215 -0
  94. package/src/take/screencast.ts +5 -2
  95. package/src/take/stepper.ts +23 -6
  96. package/src/take/zoom/NOTICE.md +1 -1
  97. package/src/tasks/launch-wait.ts +160 -0
  98. package/tooling/claude/reference.md +1 -1
  99. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +0 -34
  100. package/claude/skills/canon-feedback-triage/SKILL.md +0 -98
  101. package/claude/skills/plan-ready/REQUIREMENT.md +0 -35
  102. package/claude/skills/plan-ready/SKILL.md +0 -136
  103. package/claude/skills/plan-ready/references/assembly.md +0 -75
  104. package/claude/skills/plan-ready/references/ready.md +0 -128
  105. /package/claude/skills/{pick-by-eye → design-pick}/references/live-arms.md +0 -0
@@ -143,11 +143,11 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
143
143
  {
144
144
  prompt:
145
145
  'Look over the interface and tell me what feels unfinished or confusing.',
146
- expect: 'ux-audit',
146
+ expect: 'ui-audit',
147
147
  },
148
148
  {
149
149
  prompt: 'Tell me the paint and layout cost of this page right now.',
150
- expect: 'ux-measure',
150
+ expect: 'ui-measure',
151
151
  },
152
152
  {
153
153
  prompt:
@@ -162,12 +162,12 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
162
162
  {
163
163
  prompt:
164
164
  'I need real footage of the board import flow for the launch video. Film it from our app so HyperFrames can zoom in on the clicks.',
165
- expect: 'ui-record',
165
+ expect: 'ui-film',
166
166
  },
167
167
  {
168
168
  prompt:
169
169
  'Shoot the takes for the storyboard we wrote, one clip per beat of the app doing its thing.',
170
- expect: 'ui-record',
170
+ expect: 'ui-film',
171
171
  },
172
172
  {
173
173
  prompt:
@@ -216,10 +216,10 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
216
216
  },
217
217
  {
218
218
  prompt: 'Find the rough, unfinished-feeling spots in this interface.',
219
- expect: 'ux-audit',
219
+ expect: 'ui-audit',
220
220
  },
221
221
  {
222
222
  prompt: 'Tell me the render cost of this page in the browser.',
223
- expect: 'ux-measure',
223
+ expect: 'ui-measure',
224
224
  },
225
225
  ]
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bash
2
+ # Fake gh for src/commands/pr.test.ts. Reads FAKE_GH_FX, FAKE_GH_COMMENTS, and FAKE_GH_API_LOG.
3
+ set -o pipefail
4
+ fx="$FAKE_GH_FX"
5
+ f=.
6
+ p=
7
+ for a in "$@"; do
8
+ [ "$p" = --jq ] && f=$a
9
+ p=$a
10
+ done
11
+ case "$*" in
12
+ *graphql* | "pr "* | "repo view"*) exit 1 ;;
13
+ api*pulls/7/files*)
14
+ echo "$*" >>"$fx/files-calls.log"
15
+ [ -f "$fx/files-fail" ] && exit 1
16
+ {
17
+ if [ -f "$fx/files.tsv" ]; then
18
+ cat "$fx/files.tsv"
19
+ else
20
+ git diff --name-status --no-renames main...HEAD | sed -e 's/^A/added/' -e 's/^M/modified/' -e 's/^D/removed/'
21
+ fi
22
+ } | jq -Rn '[inputs | select(length > 0) | split("\t") | {status: .[0], filename: .[1]}]' | jq -r "$f"
23
+ ;;
24
+ api*git/trees/*)
25
+ [ -f "$fx/base-tree.json" ] || exit 1
26
+ jq -r "$f" "$fx/base-tree.json"
27
+ ;;
28
+ api*contents/*)
29
+ a="$*"
30
+ p=${a##*contents/}
31
+ p=${p%%\?*}
32
+ r=${a##*ref=}
33
+ [ -f "$fx/img/$r-$(basename "$p")" ] && cat "$fx/img/$r-$(basename "$p")" || exit 1
34
+ ;;
35
+ api*compare/*)
36
+ if [ -f "$fx/merge-base" ]; then cat "$fx/merge-base"; else git merge-base main HEAD; fi
37
+ ;;
38
+ "api -X PUT repos/{owner}/{repo}/pulls/7/reviews/"*)
39
+ id=${4##*/}
40
+ echo "$id" >>"$fx/review-puts.log"
41
+ [ -f "$fx/review-put-fail-$id" ] && exit 1
42
+ printf '%s\n' "${@: -1}" >>"$fx/review-bodies.log"
43
+ echo "{}"
44
+ ;;
45
+ api*pulls/7/reviews*) [ -f "$fx/ui-reviews.json" ] && jq -r "$f" "$fx/ui-reviews.json" ;;
46
+ api*issues/7/comments*) jq '[.comments[] | {html_url: .url, body}]' "$FAKE_GH_COMMENTS" | jq -r "$f" ;;
47
+ "api -X PATCH repos/{owner}/{repo}/pulls/7 "*)
48
+ [ -f "$fx/body-fail" ] && exit 1
49
+ printf '%s' "${@: -1}" >"$fx/body-write.log"
50
+ echo "{}"
51
+ ;;
52
+ "api repos/{owner}/{repo}/pulls/7")
53
+ if [ -f "$fx/head" ]; then h=$(cat "$fx/head"); else h=$(git rev-parse HEAD); fi
54
+ b=
55
+ [ -f "$fx/pr-body" ] && b=$(cat "$fx/pr-body")
56
+ jq -n --arg h "$h" --arg b "$b" '{number:7,head:{ref:"feat/x",sha:$h},base:{ref:"main"},mergeable_state:"clean",body:$b}'
57
+ ;;
58
+ "api repos/{owner}/{repo}") echo "{\"full_name\":\"o/r\"}" ;;
59
+ api*)
60
+ printf '%s' "${@: -1}" >"$FAKE_GH_API_LOG"
61
+ echo "{}"
62
+ ;;
63
+ *) exit 1 ;;
64
+ esac
@@ -34,6 +34,7 @@ import {
34
34
  } from '@/gov/restated'
35
35
  import {
36
36
  auditExit,
37
+ CORE_FOLDERS,
37
38
  hasFinding,
38
39
  PRACTICE_FOLDERS,
39
40
  readRuleAudit,
@@ -62,6 +63,11 @@ import {
62
63
  readTestOrder,
63
64
  type TestOrderReport,
64
65
  } from '@/gov/test-order'
66
+ import {
67
+ type ChangedSet,
68
+ collectChangedFiles,
69
+ commandRunner,
70
+ } from '@/gate/sequencer'
65
71
  import { recordStamp, runDomainSync } from '@/sync/engine'
66
72
  import { detectRules } from '@/gov/detect'
67
73
  import { writeChainStamp } from '@/sync/stamp'
@@ -138,6 +144,7 @@ interface AuditOptions {
138
144
  readonly root?: string
139
145
  readonly json?: boolean
140
146
  readonly gate?: boolean
147
+ readonly touched?: boolean
141
148
  }
142
149
 
143
150
  /** What a reader does about each way the sweep produced no reading. */
@@ -613,6 +620,10 @@ export function register(program: Command): void {
613
620
  '--gate',
614
621
  'Set 2 only for a finding in a gated folder, which the push stage reads',
615
622
  )
623
+ .option(
624
+ '--touched',
625
+ 'Owe a ledger for each core rule the branch changed against origin/main',
626
+ )
616
627
  .addHelpText(
617
628
  'after',
618
629
  [
@@ -632,6 +643,9 @@ export function register(program: Command): void {
632
643
  ` asks a ledger of each rule under ${PRACTICE_FOLDERS.join(', ')}`,
633
644
  ' at governance/ledger/<folder>/<slug>.md, one table row per bullet',
634
645
  ' under a heading of the same name.',
646
+ ` A rule under ${CORE_FOLDERS.join(', ')} has its ledger checked where`,
647
+ ' one exists, and under --touched owes one once the branch changed it.',
648
+ ' With no baseline against main, --touched reads no rule as touched.',
635
649
  ' Any other tree reads .claude/rules/project/ alone and asks no ledger.',
636
650
  ' .claude/rules/canon/ is fixed at the toolkit source and never read',
637
651
  ' unless named. A named path resolves against --root and must sit',
@@ -654,6 +668,7 @@ export function register(program: Command): void {
654
668
  ' canon gov audit',
655
669
  ' canon gov audit .claude/rules/project/api.md',
656
670
  ' canon gov audit --json',
671
+ ' canon gov audit --gate --touched',
657
672
  '',
658
673
  ].join('\n'),
659
674
  )
@@ -672,7 +687,13 @@ async function runAudit(
672
687
  opts: AuditOptions,
673
688
  ): Promise<number> {
674
689
  const root = resolve(opts.root ?? process.cwd())
675
- const report = await readRuleAudit(root, paths)
690
+ const changed = opts.touched
691
+ ? await collectChangedFiles(commandRunner(root))
692
+ : undefined
693
+ // An unscoped set lists nothing, and reading it as every file would owe a
694
+ // ledger of every core rule on a branch that touched none of them.
695
+ const touched = changed?.scoped ? changed.files : []
696
+ const report = await readRuleAudit(root, paths, { touched })
676
697
  const emitJson = opts.json ?? false
677
698
 
678
699
  if (report.kind === 'unreadable') {
@@ -690,7 +711,7 @@ async function runAudit(
690
711
  return 1
691
712
  }
692
713
 
693
- reportAudit(report, root, paths.length > 0)
714
+ reportAudit(report, root, paths.length > 0, changed)
694
715
 
695
716
  if (emitJson) {
696
717
  process.stdout.write(
@@ -700,6 +721,9 @@ async function runAudit(
700
721
  limits: RULE_LIMITS,
701
722
  gated: RULE_GATED_FOLDERS,
702
723
  exempt: RULE_GATE_EXEMPT,
724
+ ...(changed === undefined
725
+ ? {}
726
+ : { touched: { scoped: changed.scoped } }),
703
727
  ...report,
704
728
  })}\n`,
705
729
  )
@@ -728,6 +752,7 @@ function reportAudit(
728
752
  report: Extract<RuleAuditReport, { kind: 'measured' }>,
729
753
  root: string,
730
754
  named: boolean,
755
+ changed: ChangedSet | undefined,
731
756
  ): void {
732
757
  intro('canon gov audit')
733
758
 
@@ -761,10 +786,15 @@ function reportAudit(
761
786
  }
762
787
 
763
788
  logStep('Ledgers')
789
+ if (changed !== undefined && !changed.scoped) {
790
+ logInfo(
791
+ 'no baseline against main, so --touched reads no core rule as touched',
792
+ )
793
+ }
764
794
  if (report.scope === 'target') {
765
795
  logInfo('not read, since ledgers live in the toolkit and never ship')
766
796
  } else if (ledgers.length === 0) {
767
- logInfo('every outside-practice rule has a ledger row per bullet')
797
+ logInfo('every rule owing a ledger has one, with a row per bullet')
768
798
  } else {
769
799
  for (const line of ledgers) logWarn(line)
770
800
  }
@@ -1309,6 +1309,13 @@ export function register(program: Command): void {
1309
1309
  'any ordinal evidence/ already carries. The dry run labels every',
1310
1310
  'derived destination, so check the split before passing --write.',
1311
1311
  '',
1312
+ 'Moves the design board to the folder Frameboard names:',
1313
+ ' canvas/ -> board/',
1314
+ '',
1315
+ 'Stop a frameboard serve on canvas/ before --write. A project holding',
1316
+ 'both folders gets a collision, and a design.toml board key naming',
1317
+ '.canon/canvas is left for you to update.',
1318
+ '',
1312
1319
  'A citation reaching into a moved folder or naming a moved file is',
1313
1320
  'repointed, live or archived. A bare mention of an emptied folder, such',
1314
1321
  'as review/evidence/ with no slug, matches no row and stays as written.',
@@ -1389,8 +1396,11 @@ export function register(program: Command): void {
1389
1396
  `It also carries ${Object.keys(SKILL_CITATION_MAP).length} namespaced-only rows for a skill renamed from a single word.`,
1390
1397
  'The seven draft- skills move onto verb-first names, such as',
1391
1398
  // The old spellings below are the rename itself. canon-keep-retired
1392
- 'draft-doc to write-doc and draft-and-pick to pick-by-eye, and a',
1393
- 'pointer left under each old name is never moved.',
1399
+ 'draft-doc to write-doc and draft-slides to make-deck, and a',
1400
+ 'pointer left under each old name is never moved. Four skills then',
1401
+ 'moved into the family their job belongs to, such as',
1402
+ // canon-keep-retired
1403
+ 'ux-audit to ui-audit and pick-by-eye to design-pick.',
1394
1404
  'It takes no scope. The skill folders it moves are authored in the',
1395
1405
  'toolkit and no target holds a copy of that catalog, so in a target it',
1396
1406
  'rewrites citations of a renamed skill and moves nothing.',