@ersbeth/codelife 0.0.0-bootstrap.0 → 0.11.1

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 (214) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +66 -0
  4. package/agents/evaluate.md +97 -0
  5. package/agents/ground.md +49 -0
  6. package/agents/implementer.md +49 -0
  7. package/agents/judge.md +128 -0
  8. package/agents/planner.md +45 -0
  9. package/agents/prerequisites.md +62 -0
  10. package/agents/reader.md +40 -0
  11. package/agents/reproduce.md +65 -0
  12. package/bin/codelife +4 -0
  13. package/package.json +40 -1
  14. package/presets/tsconfig.json +14 -0
  15. package/presets/vite.config.d.mts +3 -0
  16. package/presets/vite.config.mjs +49 -0
  17. package/scripts/audit/cadence.mjs +24 -0
  18. package/scripts/audit/close.mjs +57 -0
  19. package/scripts/audit/file.mjs +70 -0
  20. package/scripts/audit/fold.mjs +48 -0
  21. package/scripts/audit/lib.mjs +93 -0
  22. package/scripts/audit/prepare.mjs +180 -0
  23. package/scripts/audit/table.mjs +65 -0
  24. package/scripts/brainstorm/decided.mjs +6 -0
  25. package/scripts/brainstorm/lib.mjs +33 -0
  26. package/scripts/brainstorm/named.mjs +9 -0
  27. package/scripts/changelog.mjs +100 -0
  28. package/scripts/check-tag.mjs +19 -0
  29. package/scripts/checks.mjs +53 -0
  30. package/scripts/codelife.mjs +42 -0
  31. package/scripts/commit-msg.mjs +43 -0
  32. package/scripts/contract.mjs +179 -0
  33. package/scripts/former-form.mjs +170 -0
  34. package/scripts/git/branches.mjs +6 -0
  35. package/scripts/git/commit.mjs +40 -0
  36. package/scripts/git/diff.mjs +17 -0
  37. package/scripts/git/diff_lines.mjs +5 -0
  38. package/scripts/git/held.mjs +53 -0
  39. package/scripts/git/is_ancestor.mjs +28 -0
  40. package/scripts/git/lib.mjs +20 -0
  41. package/scripts/git/log_since.mjs +27 -0
  42. package/scripts/git/parent.mjs +51 -0
  43. package/scripts/git/show.mjs +4 -0
  44. package/scripts/git/status.mjs +25 -0
  45. package/scripts/git/submodules.mjs +5 -0
  46. package/scripts/init.mjs +21 -0
  47. package/scripts/install.mjs +32 -0
  48. package/scripts/lenses/A11Y.md +91 -0
  49. package/scripts/lenses/ARCH.md +90 -0
  50. package/scripts/lenses/BUG.md +52 -0
  51. package/scripts/lenses/BUILD.md +40 -0
  52. package/scripts/lenses/COMPAT.md +67 -0
  53. package/scripts/lenses/CONF.md +49 -0
  54. package/scripts/lenses/DEPS.md +43 -0
  55. package/scripts/lenses/DOC.md +73 -0
  56. package/scripts/lenses/FAIL.md +57 -0
  57. package/scripts/lenses/GOV.md +56 -0
  58. package/scripts/lenses/GUARD.md +47 -0
  59. package/scripts/lenses/INTENT.md +52 -0
  60. package/scripts/lenses/LEAN.md +49 -0
  61. package/scripts/lenses/LINES.md +48 -0
  62. package/scripts/lenses/PERF.md +61 -0
  63. package/scripts/lenses/PKG.md +58 -0
  64. package/scripts/lenses/SEC.md +49 -0
  65. package/scripts/lenses/STANDARDS.md +62 -0
  66. package/scripts/lenses/TYPE.md +56 -0
  67. package/scripts/lenses/VERIF.md +81 -0
  68. package/scripts/link.mjs +40 -0
  69. package/scripts/methods/cause.md +21 -0
  70. package/scripts/methods/comments.md +157 -0
  71. package/scripts/methods/description.md +67 -0
  72. package/scripts/methods/message.md +24 -0
  73. package/scripts/methods/red-green.md +28 -0
  74. package/scripts/methods/refusal.md +22 -0
  75. package/scripts/mr/open.mjs +219 -0
  76. package/scripts/node-floor.mjs +19 -0
  77. package/scripts/onboard/prep.mjs +93 -0
  78. package/scripts/overview/codelife-line.mjs +33 -0
  79. package/scripts/overview/next.mjs +76 -0
  80. package/scripts/overview/overview.mjs +308 -0
  81. package/scripts/package-manager.mjs +20 -0
  82. package/scripts/port/item.mjs +94 -0
  83. package/scripts/port/lib.mjs +194 -0
  84. package/scripts/port/prep.mjs +33 -0
  85. package/scripts/port/version.mjs +50 -0
  86. package/scripts/pre-commit.mjs +43 -0
  87. package/scripts/pre-push.mjs +53 -0
  88. package/scripts/prepare-lib.mjs +81 -0
  89. package/scripts/read-roadmap/lib.mjs +116 -0
  90. package/scripts/read-roadmap/moved.mjs +70 -0
  91. package/scripts/read-roadmap/range.mjs +15 -0
  92. package/scripts/release/cut.mjs +120 -0
  93. package/scripts/release/entry.mjs +52 -0
  94. package/scripts/release/lib.mjs +136 -0
  95. package/scripts/release/prep.mjs +58 -0
  96. package/scripts/review-mr/prepare.mjs +163 -0
  97. package/scripts/roadmap/assemble.mjs +269 -0
  98. package/scripts/roadmap/cut.mjs +88 -0
  99. package/scripts/roadmap/prepare.mjs +249 -0
  100. package/scripts/roadmap/roadmap.md +30 -0
  101. package/scripts/roadmap/write.mjs +53 -0
  102. package/scripts/search.mjs +29 -0
  103. package/scripts/setup/contract.mjs +25 -0
  104. package/scripts/setup/item.mjs +166 -0
  105. package/scripts/setup/lib.mjs +205 -0
  106. package/scripts/setup/prep.mjs +106 -0
  107. package/scripts/spec-form.mjs +444 -0
  108. package/scripts/spec.mjs +56 -0
  109. package/scripts/tags.mjs +27 -0
  110. package/scripts/target/target-app.md +134 -0
  111. package/scripts/target/target-base.md +127 -0
  112. package/scripts/target/target-lib.md +143 -0
  113. package/scripts/target/templates/audit/README.md +21 -0
  114. package/scripts/target/templates/characterisation/bundle.test.ts +43 -0
  115. package/scripts/target/templates/characterisation/declarations.test.ts +44 -0
  116. package/scripts/target/templates/characterisation/entries.ts +50 -0
  117. package/scripts/target/templates/characterisation/examples.test.ts +18 -0
  118. package/scripts/target/templates/characterisation/import.test.ts +22 -0
  119. package/scripts/target/templates/characterisation/surface.test.ts +68 -0
  120. package/scripts/target/templates/cliff.toml +61 -0
  121. package/scripts/target/templates/githooks/commit-msg +9 -0
  122. package/scripts/target/templates/githooks/pre-commit +9 -0
  123. package/scripts/target/templates/githooks/pre-push +9 -0
  124. package/scripts/target/templates/playground/index.html +11 -0
  125. package/scripts/target/templates/playground/main.ts +9 -0
  126. package/scripts/target/templates/spec/README.md +35 -0
  127. package/scripts/target/templates/spec/capability.md +36 -0
  128. package/scripts/target/templates/spec/glossary.md +5 -0
  129. package/scripts/target/templates/spec/journey.md +29 -0
  130. package/scripts/target/templates/spec/principles.md +15 -0
  131. package/scripts/target/templates/spec/users.md +15 -0
  132. package/scripts/target/templates/tsconfig.json +9 -0
  133. package/scripts/target/templates/vite.config.ts +4 -0
  134. package/scripts/text.mjs +6 -0
  135. package/scripts/tracker/account.mjs +5 -0
  136. package/scripts/tracker/auth.mjs +9 -0
  137. package/scripts/tracker/cli.version.mjs +5 -0
  138. package/scripts/tracker/close.mjs +20 -0
  139. package/scripts/tracker/create.mjs +47 -0
  140. package/scripts/tracker/issue.section.mjs +25 -0
  141. package/scripts/tracker/issue.update.mjs +13 -0
  142. package/scripts/tracker/issue.view.mjs +16 -0
  143. package/scripts/tracker/lib.mjs +130 -0
  144. package/scripts/tracker/list.mjs +14 -0
  145. package/scripts/tracker/list.whole.mjs +20 -0
  146. package/scripts/tracker/lot.row.mjs +42 -0
  147. package/scripts/tracker/mr.checkout_command.mjs +5 -0
  148. package/scripts/tracker/mr.comments.mjs +50 -0
  149. package/scripts/tracker/mr.create.mjs +12 -0
  150. package/scripts/tracker/mr.description.mjs +8 -0
  151. package/scripts/tracker/mr.fetch_head.mjs +5 -0
  152. package/scripts/tracker/mr.find_for_branch.mjs +9 -0
  153. package/scripts/tracker/mr.post.mjs +40 -0
  154. package/scripts/tracker/mr.update_description.mjs +8 -0
  155. package/scripts/tracker/mr.verdict.mjs +34 -0
  156. package/scripts/tracker/mr.view.mjs +20 -0
  157. package/scripts/tracker/none.mjs +79 -0
  158. package/scripts/tracker/note.mjs +12 -0
  159. package/scripts/tracker/reopen.mjs +8 -0
  160. package/scripts/tracker/search.mjs +8 -0
  161. package/scripts/tracker/search_id.mjs +18 -0
  162. package/scripts/tracker/templates/bug.md +35 -0
  163. package/scripts/tracker/templates/feature.md +40 -0
  164. package/scripts/tracker/templates/lot.md +46 -0
  165. package/scripts/tracker/title.join.mjs +6 -0
  166. package/scripts/tracker/title.leave.mjs +7 -0
  167. package/scripts/tracker/title.lot_of.mjs +8 -0
  168. package/scripts/tracker/title.search_id_filter.mjs +17 -0
  169. package/scripts/tracker/title.sentence_of.mjs +5 -0
  170. package/scripts/tracker/view.mjs +25 -0
  171. package/scripts/verbs.mjs +579 -0
  172. package/scripts/verify/BUILD.mjs +33 -0
  173. package/scripts/verify/DEPS.mjs +15 -0
  174. package/scripts/verify/GOV.mjs +34 -0
  175. package/scripts/verify/GUARD.mjs +34 -0
  176. package/scripts/verify/LINES.mjs +22 -0
  177. package/scripts/verify/PKG.mjs +56 -0
  178. package/scripts/verify/TYPE.mjs +34 -0
  179. package/scripts/verify/cut.mjs +73 -0
  180. package/scripts/verify/history.mjs +32 -0
  181. package/scripts/verify/lib.mjs +129 -0
  182. package/scripts/verify/report.mjs +104 -0
  183. package/scripts/verify/timing.mjs +19 -0
  184. package/scripts/verify.mjs +29 -0
  185. package/scripts/work/branch.mjs +81 -0
  186. package/scripts/work/close.mjs +74 -0
  187. package/scripts/work/member.mjs +73 -0
  188. package/scripts/work/prepare.mjs +116 -0
  189. package/scripts/work/reopen.mjs +40 -0
  190. package/scripts/work-feedback/prepare.mjs +96 -0
  191. package/skills/audit/SKILL.md +110 -0
  192. package/skills/audit/templates/index.md +36 -0
  193. package/skills/audit/templates/lens.md +44 -0
  194. package/skills/brainstorm/SKILL.md +144 -0
  195. package/skills/brainstorm/references/exit.md +57 -0
  196. package/skills/brainstorm/templates/note.md +79 -0
  197. package/skills/commit/SKILL.md +68 -0
  198. package/skills/mr/SKILL.md +82 -0
  199. package/skills/new-issue/SKILL.md +87 -0
  200. package/skills/onboard/SKILL.md +103 -0
  201. package/skills/onboard/templates/CLAUDE.md +31 -0
  202. package/skills/onboard/templates/CONTRIBUTING.md +34 -0
  203. package/skills/onboard/templates/README.md +30 -0
  204. package/skills/onboard/templates/SKILL.md +24 -0
  205. package/skills/onboard/templates/package-CLAUDE.md +15 -0
  206. package/skills/overview/SKILL.md +59 -0
  207. package/skills/port-toolchain/SKILL.md +127 -0
  208. package/skills/release/SKILL.md +78 -0
  209. package/skills/review-mr/SKILL.md +106 -0
  210. package/skills/review-mr/templates/pass.md +29 -0
  211. package/skills/roadmap/SKILL.md +137 -0
  212. package/skills/setup/SKILL.md +112 -0
  213. package/skills/work/SKILL.md +139 -0
  214. package/skills/work-feedback/SKILL.md +113 -0
@@ -0,0 +1,579 @@
1
+ // The verbs of the `codelife` command line (K-43): each runs one script of the package with the
2
+ // arguments that follow its name, and carries the manual `codelife help <verb>` prints. The one
3
+ // list: scripts/codelife.mjs dispatches on it, and tests/skills.test.mjs holds every verb a brief
4
+ // names to it (C-843). A script's path is from the package's root; `lead` goes before the arguments.
5
+ import './node-floor.mjs'
6
+ import { readdirSync, readFileSync } from 'node:fs'
7
+
8
+ export const VERBS = {
9
+ help: {
10
+ summary: 'list the verbs, or print one verb\'s manual, one shared method or one template',
11
+ manual: `codelife help [<verb>]
12
+ codelife help method [<name>]
13
+ codelife help template [<name>]
14
+
15
+ With no verb, one line per verb. With one, its manual: what it runs, its arguments, what it prints.
16
+ \`help method\` lists the methods two briefs share; with a name, prints that method, read at the
17
+ step that uses it (anatomy.md C-845). \`help template\` lists the templates a brief drafts from —
18
+ an issue's, which \`setup item templates\` also copies to the forge, and a specification
19
+ document's —; with a name, prints that template.`,
20
+ },
21
+ init: {
22
+ script: 'scripts/init.mjs',
23
+ lead: ['init'],
24
+ summary: 'install codelife into the repository you stand in (R-272)',
25
+ manual: `codelife init [<package spec>]
26
+
27
+ Adds @ersbeth/codelife as a devDependency of the repository you stand in, with its own package
28
+ manager, and links the plugin; nothing else — /setup does the rest. The spec defaults to the
29
+ published version this binary belongs to. Run as \`pnpm dlx @ersbeth/codelife init\`.`,
30
+ },
31
+ spec: {
32
+ script: 'scripts/spec.mjs',
33
+ summary: 'print one rule, case, persona, journey or capability of docs/spec/ by its identifier',
34
+ manual: `codelife spec <identifier>
35
+
36
+ Run from the repository's root. Prints the file and line where the identifier is defined, then:
37
+ a rule, a case, a persona — its heading and its text, a rule's cases included; a capability or a
38
+ journey — its title and the outline of its headings, never the document whole. Then the lines of
39
+ Rejected that open on the identifier, if any; a retired identifier prints those alone. Exit 1
40
+ when it resolves to nothing, 2 on a malformed identifier or no docs/spec/.`,
41
+ },
42
+ search: {
43
+ script: 'scripts/search.mjs',
44
+ summary: 'search what is already known about a subject: the open issues, what docs/spec/ decided, the pending notes (R-179)',
45
+ manual: `codelife search <terms file>
46
+
47
+ Run from the repository's root. One term per line of the file. Searches each term alone, as a whole
48
+ word, regardless of case: over the open issues — the forge's search, or the issues/ files under
49
+ \`tracker.kind: none\` —, then over what docs/spec/ decided, each rule's heading and each line of a
50
+ \`## Rejected\`, by its text, then over the notes of docs/brainstorm/, each one's title and its
51
+ **Open** items. Prints a \`### search\` block: the terms, then each pass's count and
52
+ its first ten lines, each line once after the number of terms it matched and a tab, the most first.
53
+ Writes nothing. Exit 2 on a missing or empty file.`,
54
+ },
55
+ form: {
56
+ script: 'scripts/spec-form.mjs',
57
+ summary: 'hold docs/spec/ to its form, check a note was copied into it whole, or print what a plan is cut from (K-23)',
58
+ manual: `codelife form spec
59
+ codelife form note <note>
60
+ codelife form fold <note> [--base <rev>]
61
+ codelife form cases
62
+
63
+ Run from the repository's root; the form script the pre-commit hook runs. \`spec\` holds docs/spec/
64
+ to its form. \`note\` holds a note's own shape against docs/spec/ as it stands, before its
65
+ writing: each decision's target, rejected options and cases, the cases under one rule. \`fold\`
66
+ checks that the writing of <note> into docs/spec/ lost nothing against <rev>, HEAD by default —
67
+ each case, refusal line and identifier — and the note's shape against <rev>. A blocking rule prints
68
+ \`<file>:<line>: <rule>: <what is wrong>\` and exits 1; an \`orphan:\` line is a report. \`cases\`
69
+ prints every rule and case with its capability, the cases each journey cites and the index of their
70
+ headings, and holds nothing. On a docs/spec/ without its seven entries each mode prints that it is
71
+ not in the form and holds nothing, \`fold\` blocking. Exit 2 on no mode.`,
72
+ },
73
+ checks: {
74
+ script: 'scripts/checks.mjs',
75
+ summary: 'run the push tier, the guards a diff fires, the reading hygiene scripts, the stale outputs and How to test\'s commands, before any agent (C-853)',
76
+ manual: `codelife checks <base> [<commands file>]
77
+
78
+ Run from the repository's root, before any agent of a review starts. Runs the push tier
79
+ (verify:push), then every guards[] command of the contract whose \`when\` matches a path the diff
80
+ from <base> to HEAD touches, then the hygiene scripts that only read — DEPS and GUARD, and TYPE
81
+ under \`kind: lib\` —, then checks each generated[] output whose \`when\` the diff matches,
82
+ failed when the diff leaves it untouched, then runs each distinct line of the commands file, a
83
+ \`<manager> verify:push\` line skipped — one after the other. Prints one line per check, \`passed: <check>\`,
84
+ \`failed: <check>\` or, for a hygiene script whose subject is absent, \`could not tell: <check>\`,
85
+ anything but a pass followed by the last lines of its output and a guard's note, and nothing else.
86
+ Exit 0 when no check failed, 1 when one failed or could not run, 2 when <base> resolves to no
87
+ commit or git finds no diff from it to HEAD — no merge base, a shallow clone.`,
88
+ },
89
+ 'review prep': {
90
+ script: 'scripts/review-mr/prepare.mjs',
91
+ summary: 'prepare a review: the merge request, the head asserted, the diff, the known list, the reader\'s case (C-762)',
92
+ manual: `codelife review prep <mr>
93
+
94
+ Run from the repository's root, at the merge request's head, on a clean tree, on another person's merge request. Reads the merge
95
+ request, the account, the forge CLI against its floor, the diff from the merge base, the submodules at the head, the open issues
96
+ and the debt the description names, and the issues the commits close with what each cites; writes
97
+ nothing in the tree. Writes a run folder outside it — mr.json, comments.md, diff.diff, lines.tsv,
98
+ known.txt, case.md — and prints one \`### prepare\` summary; a \`- stop:\` line names what stops the review
99
+ before any agent, and the exit is 1.`,
100
+ },
101
+ 'feedback prep': {
102
+ script: 'scripts/work-feedback/prepare.mjs',
103
+ summary: 'prepare an answer to a review: your merge request, its branch asserted, the rows left to answer (K-13)',
104
+ manual: `codelife feedback prep [<mr>]
105
+
106
+ Run from the repository's root, on the merge request's branch, at its head or ahead of it, on a
107
+ clean tree, as its author. Reads the merge request — the argument, or the one open for the current
108
+ branch —, the latest review pass, the answers to it, the comments people wrote after it and the
109
+ threads they opened, and the \`Answers:\` trailers since the merge base; writes nothing in the tree.
110
+ A row is a pass's number still \`new\`, \`open\` or \`refused … kept\`, a comment or an open thread,
111
+ less those an answer's table already carries; one a trailer names is marked with its commit. Writes
112
+ rows.md in a run folder outside the tree and prints one \`### prepare\` summary; a \`- stop:\` line
113
+ names what stops the run — nothing left to answer among them — and the exit is 1.`,
114
+ },
115
+ 'issue view': {
116
+ script: 'scripts/tracker/issue.view.mjs',
117
+ summary: 'print an issue whole: its description, then every comment and close, oldest first',
118
+ manual: `codelife issue view <n>
119
+
120
+ Run from the repository's root, the tracker connected. Prints the issue's title, state and labels,
121
+ its description, then each comment and each close or reopening under a \`## <date> — <author or
122
+ state>\` heading, oldest first — every page, system notes left out. Under \`tracker.kind: none\`, the
123
+ file's \`## Notes\` sections, with no history of its state.`,
124
+ },
125
+ 'issue section': {
126
+ script: 'scripts/tracker/issue.section.mjs',
127
+ summary: 'print one section of an issue, or its latest plan',
128
+ manual: `codelife issue section <n> <heading>
129
+
130
+ Run from the repository's root, the tracker connected. Prints the issue's description from its
131
+ \`## <heading>\` line — the heading's opening words, any case — to the next \`## \`. The heading
132
+ \`plan\` prints instead the latest comment opening on \`codelife: plan — \`. Exit 1 when there is none.`,
133
+ },
134
+ verify: {
135
+ script: 'scripts/verify.mjs',
136
+ summary: 'run a tier, the guards the change fires and the outputs it makes stale (R-199)',
137
+ manual: `codelife verify commit|push [<base>]
138
+
139
+ Run from the repository's root. Runs each contract \`generated[]\` command whose \`when\` matches
140
+ a path the working tree changed — or the diff from <base> to HEAD, when given — and stages its path,
141
+ then the \`verify:commit\` or \`verify:push\` script through the package manager and each
142
+ \`guards[]\` entry whose \`when\` matches. Prints one line per check, \`passed\`
143
+ or \`failed\` with its last lines and a guard's note; exit 1 on a failure or a tier not ported.`,
144
+ },
145
+ 'issue note': {
146
+ script: 'scripts/tracker/note.mjs',
147
+ summary: 'post one new comment on an issue from a file (R-199)',
148
+ manual: `codelife issue note <n> <comment file>
149
+
150
+ Run from the repository's root, the tracker connected. Posts the file as one new comment on the
151
+ issue — under \`tracker.kind: none\`, a dated section appended to its file — and prints \`noted #<n>\`.`,
152
+ },
153
+ 'issue create': {
154
+ script: 'scripts/tracker/create.mjs',
155
+ summary: 'file one new issue from a file, its title tagged by its origin, and print its number (C-868)',
156
+ manual: `codelife issue create [--once] <bug|feature|lot|-> <critical|high|mid|low|-> <origin|-> <file>
157
+
158
+ Run from the repository's root, the tracker connected. The file opens on a \`# <sentence>\` line, the
159
+ rest is the body. Files one issue titled \`[<origin>] <sentence>\` — the sentence alone for \`-\` —,
160
+ labelled with the nature and \`severity-<s>\`; a \`lot\` is an umbrella, titled \`[lot · <origin>]\` and
161
+ labelled \`lot\` alone; a nature \`-\` takes no label, as the roadmap does. Under \`tracker.kind: none\`, a new issues/ file.
162
+ Prints \`created #<n> — <link or path>\`; exit 1 when the number does not read back. With --once, an
163
+ issue whose tag already holds the origin, open or closed, files nothing: \`exists #<n> — <its line>\`.`,
164
+ },
165
+ 'issue update': {
166
+ script: 'scripts/tracker/issue.update.mjs',
167
+ summary: 'replace an issue\'s description from a file, its title from another (K-8)',
168
+ manual: `codelife issue update <n> <body file>|- [<title file>]
169
+
170
+ Run from the repository's root, the tracker connected. Replaces the issue's description with the
171
+ file — \`-\` leaves it — and its title with the second file's first line, when given; under
172
+ \`tracker.kind: none\`, its issues/ file. Prints \`updated #<n>\`.`,
173
+ },
174
+ 'issue close': {
175
+ script: 'scripts/work/close.mjs',
176
+ summary: 'close an issue on its own commit, tick its umbrella, close the umbrella with its last member (R-193)',
177
+ manual: `codelife issue close <n> <comment file> <hash>… [--wontfix]
178
+
179
+ Run from the repository's root, the tracker connected. Posts nothing unless HEAD contains every
180
+ hash the comment cites and each one's \`Closes:\` footer names the issue — or, for \`Already fixed
181
+ in <hash> (#<earlier>)\`, whose \`Closes:\` or \`Refs:\` footer names that issue, closed on the tracker;
182
+ with \`--wontfix\`, a hash may instead add to docs/spec/ the refusal line the comment quotes. Then posts the comment and closes the issue, ticks its line
183
+ in its umbrella with every row whose issue is already closed, and when no member is open closes
184
+ the umbrella on a \`lot-closing\` comment. A \`- stop:\` line names a refusal, and the exit is 1.`,
185
+ },
186
+ 'issue reopen': {
187
+ script: 'scripts/work/reopen.mjs',
188
+ summary: 'reopen an issue whose held choice you refused, its reason posted, its umbrella line unticked (R-295)',
189
+ manual: `codelife issue reopen <n> <comment file>
190
+
191
+ Run from the repository's root, the tracker connected. Reads the issue and its umbrella first, then
192
+ posts the comment, reopens the issue, unticks its line in its umbrella and reopens the umbrella when
193
+ it was closed. Under tracker.kind none, or a task list that cannot be unticked, a \`- stop:\` line,
194
+ exit 1, nothing posted.`,
195
+ },
196
+ 'mr comments': {
197
+ script: 'scripts/tracker/mr.comments.mjs',
198
+ summary: 'print the latest review pass, the comments people wrote after it and the threads they opened (C-865)',
199
+ manual: `codelife mr comments <mr>
200
+
201
+ Run from the repository's root, the tracker connected. Prints a \`### comments\` block — the latest
202
+ pass (\`codelife: review — pass <k> — <sha>\`) with its number, sha, author and link, every pass's
203
+ link, and how many answers, comments and open threads people left after it — then the pass whole,
204
+ each answer to it (\`codelife: answer — pass <k> — \`), each comment written after it, and each
205
+ open thread a person opened. Writes nothing.`,
206
+ },
207
+ 'mr post': {
208
+ script: 'scripts/tracker/mr.post.mjs',
209
+ summary: 'post one new comment from a file, never edited, and print its link (C-864)',
210
+ manual: `codelife mr post <mr> <file>
211
+
212
+ Run from the repository's root, the tracker connected. Posts the file as one new general comment
213
+ and prints its link, read back. A file whose first line opens on \`codelife:\` and ends on a sha
214
+ is about that head: when the merge request's head is another, nothing is posted and the exit is 1;
215
+ when that very comment is already there, nothing is posted and its link is printed.`,
216
+ },
217
+ 'mr verdict': {
218
+ script: 'scripts/tracker/mr.verdict.mjs',
219
+ summary: 'send the forge\'s own verdict: approve, or request changes (C-866)',
220
+ manual: `codelife mr verdict <mr> approve|request [<pass link>]
221
+
222
+ Run from the repository's root, the tracker connected. On GitLab, approves, or sets the account's
223
+ reviewer state to requested changes and reads it back; on GitHub, submits a review in that state,
224
+ its body the pass's link. An approval of the account's own merge request is refused, exit 1.`,
225
+ },
226
+ 'mr open': {
227
+ script: 'scripts/mr/open.mjs',
228
+ summary: 'print what a branch\'s merge request sends, or push it and open or update the request (C-873)',
229
+ manual: `codelife mr open [<description file>] [--send] [--wrap | --append]
230
+
231
+ Run from the repository's root, the tracker connected, on the branch to open. Without --send prints
232
+ a \`### mr open\` block and sends nothing: the branch and its derived target, how many commits the
233
+ target holds that it lacks and whether a merge of them conflicts or changes its tree, the commits
234
+ leaving with their count, each held choice waiting and each one a \`Replaces:\` took out of the wait,
235
+ the members of the lot still open each with its last STATUS, and whether a merge request opens or
236
+ \`!n\` is updated, the existing description written to a file it names. Then what the description
237
+ is written from: a \`linked:\` line per issue the commits cite, lot member and umbrella, with its title;
238
+ each \`hand commit:\`, the ones no unit's closing comment cites; the \`links:\` base, the \`run:\` prefix,
239
+ the \`generated:\` outputs the diff touches, a \`debt:\` line per number the file's Debt noticed cites,
240
+ and, when the only new commit merges the target in, that the description is kept. A line that asks
241
+ a question says so: a held choice's later commits on its files, a merge of the target to accept. With --send checks again and refuses, exit 1 with a \`- stop:\` line and nothing
242
+ sent, a branch behind its target whose merge changes its tree or conflicts, or a tree not clean; runs
243
+ the push tier against the target, a red naming its failure; pushes with the upstream set, never
244
+ forced; then creates the merge request or replaces the tagged region of the existing description,
245
+ nothing outside it, and prints the link. A new request's title is the file's first line when it reads
246
+ \`# <title>\`, dropped from the description, or else the branch's issue's — the dry run saying so when
247
+ the commits close several issues and no umbrella names them. The file must carry the region and the template's headings;
248
+ an existing description with no region is refused unless --wrap (the region replaces it whole) or
249
+ --append (the region is added below it) says which; an update without a file keeps the description; the dry run needs none, a --send that creates does. Under tracker.kind none, exit 1. Exit 2 on a usage error.`,
250
+ },
251
+ 'audit prep': {
252
+ script: 'scripts/audit/prepare.mjs',
253
+ summary: 'open or resume an audit campaign: its lenses, the known list, the fingerprint, the push tier, the facts and the cut, a folder per part to judge (C-869)',
254
+ manual: `codelife audit prep [full | targeted <LENS>…] [--red]
255
+
256
+ Run from the repository's root, before any agent. Stops, exit 1 with a \`- stop:\` line, on a tree
257
+ not clean but for a campaign folder, a campaign under way at another commit than HEAD, a retired lens
258
+ or one with no reference, no verify:push script, or a red push tier unless --red audits it. Resumes
259
+ the campaign under way — its index reads IN PROGRESS —, with its own lenses; otherwise opens the next
260
+ number of docs/audit/README.md's table: every lens the contract's kind makes applicable and every
261
+ domain lens for full, the named ones for targeted. Writes the known list — the open issues and what
262
+ docs/spec/ decided —, takes the fingerprint of every file outside docs/audit/, runs verify's report
263
+ at HEAD (the push tier, the hygiene scripts, the history, PERF's timings, the cut), then writes the
264
+ campaign folder, its index and fingerprint.tsv, and outside the tree a folder for the judge of every
265
+ part whose folder holds no part.md, emptied for it, listed in judges.tsv. Prints one
266
+ \`### audit prep\` summary, ending on the cap of judges at once. Exit 2 on a usage error.`,
267
+ },
268
+ 'audit table': {
269
+ script: 'scripts/audit/table.mjs',
270
+ summary: 'print the table one lens\'s findings are confirmed on, every part judged and accounted for (R-110)',
271
+ manual: `codelife audit table <LENS>[,<LENS>…]
272
+
273
+ Run from the repository's root, a campaign under way. Stops, exit 1, on a part with no part.md or
274
+ whose judge left a received candidate id unaccounted, naming what to run again. Prints one row per
275
+ finding of the lenses across the parts — id, title, severity with UNVERIFIED, effort, and its state:
276
+ its disposition, filed #n when an issue's tag carries its id, known #n, or new, a title two rows share
277
+ flagged — then, below the rows, each To watch, Deliberate choice and False line of its judges, and
278
+ the Contested ones. Writes nothing.`,
279
+ },
280
+ 'audit file': {
281
+ script: 'scripts/audit/file.mjs',
282
+ summary: 'file one confirmed table: an issue per new finding, a re-reported comment per known one, each disposition written back (R-111, R-112)',
283
+ manual: `codelife audit file <rows file>
284
+
285
+ Run from the repository's root, a campaign under way. One row a line: \`<id> <bug|feature> <severity>\`,
286
+ \`<id> known\`, \`<id> false\`, \`<id> refused <address>\` or \`<id> merged <id>\`. Checks every row
287
+ first. A new finding is filed through \`issue create --once\` with the origin audit:<id>, its body the
288
+ finding's lead, then the finding whole as its first comment, \`codelife: finding\`; an issue already
289
+ tagged with the id is taken as filed. A known one gets a \`codelife: re-reported\` comment. Each
290
+ disposition is appended to its finding's file as its row is done; a row already disposed is skipped.
291
+ Prints one line per row; exit 1 with a \`- stop:\` line on a bad row or a forge write that fails.`,
292
+ },
293
+ 'audit close': {
294
+ script: 'scripts/audit/close.mjs',
295
+ summary: 'close the campaign under way: the checks, the findings by lens, the banner frozen, the fingerprint compared (R-226, R-227)',
296
+ manual: `codelife audit close
297
+
298
+ Run from the repository's root. Stops, exit 1 and nothing written, on a finding with no disposition
299
+ or an index still holding a placeholder the session writes. Then fills the index's findings by lens
300
+ and the paths no lens read in the end, turns its banner FROZEN, names every file outside docs/audit/
301
+ that differs from the fingerprint — docs/spec/'s refusal lines apart —, removes fingerprint.tsv, and
302
+ prints the close commit's message and paths.`,
303
+ },
304
+ 'audit fold': {
305
+ script: 'scripts/audit/fold.mjs',
306
+ summary: 'once the close commit is HEAD, delete the campaign folder and write its row in the campaign table (R-226)',
307
+ manual: `codelife audit fold
308
+
309
+ Run from the repository's root, HEAD being \`docs(audits): close campaign A<n>\`. Stages the deletion
310
+ of that campaign's folder and writes its row at the top of docs/audit/README.md's table — its id
311
+ linked to the index at that commit on the forge, or the sha and the path with no forge —, then prints
312
+ the fold commit's message and paths. Exit 1 with a \`- stop:\` line otherwise.`,
313
+ },
314
+ 'work prep': {
315
+ script: 'scripts/work/prepare.mjs',
316
+ summary: 'prepare a lot or a lone issue: its members in order, or the issue, its branch, its joins (R-288)',
317
+ manual: `codelife work prep <umbrella-or-issue>
318
+
319
+ Run from the repository's root, on a clean tree, the tracker connected, with a \`test:one\` script.
320
+ Reads the number as an umbrella — an issue labelled lot — or a lone issue: the umbrella, its
321
+ members and the orphans a debt-link on it points at; or the issue, its evidence and its last plan or refusal; then the
322
+ branch the work belongs on, and whether a rule a member or the issue cites moved since the
323
+ roadmap's mark; writes nothing. A lot's member names its umbrella and stops. Prints one
324
+ \`### prepare\` summary; a \`- stop:\` line names what stops the run before any table, and the exit is 1.`,
325
+ },
326
+ overview: {
327
+ script: 'scripts/overview/overview.mjs',
328
+ summary: 'print where the repository stands, one screen, and the first rule of Next that holds (K-6)',
329
+ manual: `codelife overview
330
+
331
+ Run from the repository's root. Reads the contract, the tree, git, origin, the tracker and the
332
+ registry, and prints one \`### overview\` screen: the connection, the contract, the target, the
333
+ audit, the issues by lot then the orphans by severity, the merge requests, the resumption
334
+ artefacts, then \`**Next**\`, the first rule of R-173 that holds with its reason and its row. A
335
+ source that does not answer prints as unreadable with its error, never as empty, and stops Next
336
+ at the first rule that reads it. Writes nothing, asks nothing; exit 0.`,
337
+ },
338
+ 'roadmap prep': {
339
+ script: 'scripts/roadmap/prepare.mjs',
340
+ summary: 'prepare a plan: the roadmap and its mark, what docs/spec/ changed since, the open issues sorted, a folder per capability to cut (K-8)',
341
+ manual: `codelife roadmap prep [<label-or-milestone>] [--from <sha>]
342
+
343
+ Run from the repository's root, the tracker connected. Reads the roadmap — its mark, its order, the
344
+ orphans it left alone — or, with none, where a first run starts; then what docs/spec/ changed from
345
+ the mark, or <sha>, to HEAD: each case with the commit that last wrote it, proposed built when the
346
+ merge that brought it changed a file outside docs/. Reads every open issue, each written to
347
+ issues/<n>.md, and prints the umbrellas with their Done when, each member whose latest plan says
348
+ \`Waits for: C-<n>\` and the issue that builds it, the issues citing what changed, the orphans — those
349
+ the label or milestone names, when given. Writes a run folder outside the tree — cases.tsv,
350
+ cut.tsv, built.tsv, journeys.txt, one K-<n>/ per capability to cut, its document and index.txt, on
351
+ a first run over tests its tests.txt — and prints one \`### prepare\` summary; a \`- stop:\` line names
352
+ what stops the run before any table, and the exit is 1. Writes nothing on the forge.`,
353
+ },
354
+ 'roadmap cut': {
355
+ script: 'scripts/roadmap/cut.mjs',
356
+ summary: 'cut a prepared range into lots from the prerequisites blocks saved in its folder (K-8)',
357
+ manual: `codelife roadmap cut <run folder>
358
+
359
+ Run from the repository's root on the folder \`codelife roadmap prep\` printed, each prerequisites
360
+ block saved in its blocks/. Cuts the cases into lots — each one capability's cases at one stage,
361
+ within about ten, after the lots it waits for — places them after the roadmap's confirmed lines,
362
+ adds the open lot building a case a lot presumes outside the cut and the last open lot of each of
363
+ its capabilities, proposes an orphan citing one of a member's cases as that member and an effort
364
+ from the member's cases. Writes table.md in the folder and prints one \`### cut\` summary, a line per
365
+ lot and per flag; a \`- stop:\` line names what the cut could not judge, and the exit is 1.`,
366
+ },
367
+ 'roadmap write': {
368
+ script: 'scripts/roadmap/write.mjs',
369
+ summary: 'rewrite the roadmap, last: the mark read, the orphans left alone, the open lots in order (R-263)',
370
+ manual: `codelife roadmap write <run folder> <order file> [<left alone file>]
371
+
372
+ Run from the repository's root on the folder \`codelife roadmap prep\` printed. The order file holds
373
+ one \`#<n> <sentence>\` line per open lot, in order, \` — after #<a>, #<b>\` when it waits for open
374
+ lots; the left-alone file one \`#<n> <sentence>\` per orphan grouped with nothing. Writes the roadmap
375
+ from its template, the mark at the HEAD the folder read, and updates it — or creates the first.
376
+ A line out of shape is refused, nothing sent, exit 1.`,
377
+ },
378
+ 'lot join': {
379
+ script: 'scripts/work/member.mjs',
380
+ lead: ['join'],
381
+ summary: 'join issues to a lot: each title\'s lot half and its row in the umbrella (R-251)',
382
+ manual: `codelife lot join <umbrella> <n>[:S|M|L]...
383
+
384
+ Run from the repository's root, the tracker connected. Writes the lot into each issue's title and
385
+ appends its row, with the effort when given, to the umbrella's \`## The order\` in the order given,
386
+ the umbrella read and written once, every write computed before the first; a part already written is
387
+ left as it is; \`<n> S|M|L\` reads as \`<n>:S|M|L\`. Refuses an issue of another lot, writing nothing.
388
+ Prints one \`### lot join\` summary; a \`- stop:\` line, exit 1.`,
389
+ },
390
+ 'lot leave': {
391
+ script: 'scripts/work/member.mjs',
392
+ lead: ['leave'],
393
+ summary: 'take an issue out of a lot, its reason written on both (R-202)',
394
+ manual: `codelife lot leave <umbrella> <n> <reason file>
395
+
396
+ Run from the repository's root, the tracker connected. Removes the lot from the issue's title,
397
+ opens its body on \`Left lot #<umbrella> on <date>: <reason>\`, and replaces its row in the
398
+ umbrella's \`## The order\` with one \`Left on\` line; when no row left is an open issue, closes the
399
+ open umbrella on a \`lot-closing\` comment, \`wontfix\` when no row is left. Prints one
400
+ \`### lot leave\` summary.`,
401
+ },
402
+ commit: {
403
+ script: 'scripts/git/commit.mjs',
404
+ summary: 'commit the named paths from a message file, waiting on no input (R-84)',
405
+ manual: `codelife commit <message file> <path>...
406
+
407
+ Run from the repository's root; reads no stdin. Checks first, touching nothing, and refuses with
408
+ exit 2 naming the problem: no path or message file, a named path holding a newline (\`unreadable\`),
409
+ a file staged that no named path covers (\`staged beforehand: <path>\`, not checked during a merge,
410
+ cherry-pick or revert), a path \`git add\` cannot take (ignored, unmatched) — a path, a file or a folder
411
+ gone from the disk, whose deletion \`git rm\` already staged is that path's change. Then stages the paths and commits the index whole
412
+ with the message file's text; a refusing hook is printed as git prints it, exit 1, the only 1. Then prints \`<hash> <subject>\`, \`left unstaged: <path>\` per named path still
413
+ changed (what a hook reformatted), and \`not committed: <path>\` per other change; a name holding a
414
+ newline prints \`unreadable: <label>\` in place of the path. Any other failure exits 2.`,
415
+ },
416
+ 'release prep': {
417
+ script: 'scripts/release/prep.mjs',
418
+ summary: 'state a release before its version is asked: the branch, origin, the last tag, the commits since it, the bump, a release prepared, the audit due (K-16)',
419
+ manual: `codelife release prep [--prepare]
420
+
421
+ Run from the repository's root. Reads only. Prints one \`### release prep\` block: the branch and the
422
+ release it makes — develop, main after a hotfix, a support/ line; any branch with --prepare —, origin
423
+ as the forge has it, the version file, the line's last tag (\`v<version>\`, \`<name>--v<version>\` or
424
+ \`r<version>\`), the commits since it by type and each breaking one, the scheme and the bump it
425
+ gives, a support/ line the moved peer opens, a version prepared and untagged — \`resume:\` when
426
+ nothing landed after its release commit —, the audit the cadence proposes, the changelog generator
427
+ run with --check, the tracker. A \`- stop:\` line per thing that stops the release — a work branch, a
428
+ tree not clean, a branch behind or diverged, nothing since the tag — and exit 1.`,
429
+ },
430
+ 'release cut': {
431
+ script: 'scripts/release/cut.mjs',
432
+ summary: 'make the confirmed release locally: version, changelog, outputs, release tier, commit, then merge and tag; push nothing (R-245, R-246)',
433
+ manual: `codelife release cut [<version>] [--prepare]
434
+
435
+ Run from the repository's root, on a clean tree, with the version you confirmed — none to resume a
436
+ prepared one. Writes the version into the version file and every published package.json, renders
437
+ the changelog section, regenerates the generated[] outputs the range since the last tag fires, then
438
+ runs verify:release and the guards that range fires: a red, a generator failing, or a path changed
439
+ outside those declared restores every tracked file and stops. Then commits \`chore(release):
440
+ <version>\` and prints a \`- section:\` line, the section's lines and entries per heading
441
+ counted; with --prepare it stops there. Otherwise, on develop: merged into main with a merge
442
+ commit, the annotated \`v<version>\` tag on main, develop fast-forwarded; on main: tagged, then
443
+ merged back into develop; on a support/ branch: tagged there. Pushes nothing: prints one
444
+ \`- push:\` line per branch and one for the tag, each yours to run. Exit 1 on a stop, 2 on usage.`,
445
+ },
446
+ 'release entry': {
447
+ script: 'scripts/release/entry.mjs',
448
+ summary: 'once the tag is on origin, create the forge\'s release entry from the changelog section, then print the hand-off (R-247)',
449
+ manual: `codelife release entry
450
+
451
+ Run from the repository's root, once \`v<version>\` is on origin. Creates the forge's release entry on
452
+ the tag, its notes the version's changelog section; an entry that exists is left, one the forge
453
+ refuses is a \`degraded\` line; under tracker.kind none, or with no origin, the section is the entry.
454
+ Then prints the pipeline's URL, the registry page of a package that is not private, and the three
455
+ failure modes to recognise. Publishes and watches nothing. Exit 1 when the tag is missing here or
456
+ on origin.`,
457
+ },
458
+ 'setup prep': {
459
+ script: 'scripts/setup/prep.mjs',
460
+ summary: 'state a repository before /setup asks: the mode, origin and its connection, what the contract is inferred from, the forge settings, each base item (K-1)',
461
+ manual: `codelife setup prep
462
+
463
+ Run from the repository's root. Reads only. Prints one \`### setup prep\` block: the mode — first run,
464
+ or update with the contract current, stale or invalid —, origin and the forge its host is, the CLI,
465
+ the connection and its expiry, a token variable set in the shell, and when not connected the
466
+ guide: the token page, its name and boundary, every permission, the login command for your own
467
+ terminal. Then what the contract's values come from — kind, release.version_file, generated
468
+ candidates —, the prose to read whole, the default branch, the merge method, the package, the
469
+ former form, and one \`- item <name>:\` line per base item, done, to do with why, not applicable
470
+ or not read. A \`- stop:\` line per thing that stops the run — not connected, an invalid contract, a
471
+ default branch other than main —, and exit 1.`,
472
+ },
473
+ 'setup contract': {
474
+ script: 'scripts/setup/contract.mjs',
475
+ summary: 'hold the contract you confirmed to its schema and write it, the settings settled (K-1)',
476
+ manual: `codelife setup contract <file>
477
+
478
+ Run from the repository's root. Reads the file — a draft, or .claude/codelife.md you edited — and
479
+ holds it to the schema: a \`- invalid:\` line each and exit 1, nothing written; a \`- stale:\` line
480
+ each. Then writes it to .claude/codelife.md, and replaces a former marketplace's lines in
481
+ .claude/settings.json by "codelife@codelife": false. Prints \`- paths:\`, what \`codelife commit\` takes.`,
482
+ },
483
+ 'setup item': {
484
+ script: 'scripts/setup/item.mjs',
485
+ summary: 'show what one base item changes, or with --write do it and run its check; commit nothing (K-1)',
486
+ manual: `codelife setup item <labels|templates|scripts|hooks|folders|changelog|develop> [--write] [--test <file>]
487
+
488
+ Run from the repository's root. Without --write, reads only: what the item would create, write or
489
+ move, an existing file's difference included. With --write, does it, then runs the item's check:
490
+ labels — each fixed one on the tracker; templates — the forge's three files; scripts — engines, the
491
+ packageManager pnpm wrote, node_modules/ ignored, then each of the five run (test:one on --test);
492
+ hooks — verify:commit and verify:push green first, the former form migrated, the three stubs, the
493
+ prepare line, ## Setup's line, the install run, a \`wip\` commit refused; folders — the base's;
494
+ changelog — the marker, the generated part, --check reproducing it; develop — created from main,
495
+ or fast-forwarded. Prints \`- paths:\` for \`codelife commit\`; a \`- stop:\` line exits 1 with nothing
496
+ written, a \`- failed:\` line exits 1 after.`,
497
+ },
498
+ 'port prep': {
499
+ script: 'scripts/port/prep.mjs',
500
+ summary: 'state a toolchain port before /port-toolchain proposes: each item done, to do, deferred, refused or blocked, the summary line, the next item (K-2)',
501
+ manual: `codelife port prep
502
+
503
+ Run from the repository's root. Reads only. Prints one \`### port prep\` block: the kind and the ported
504
+ package — the directory of release.version_file —, one \`- item <name>:\` line per toolchain item, in
505
+ the order the port plays them — done, not applicable, not read, to do with why, deferred or refused
506
+ with its \`port:\` issue, blocked by the item its precondition waits on —, the \`- toolchain:\` summary
507
+ line, and \`- next:\`, the first item to do whose precondition is done. A \`- stop:\` line — no
508
+ contract or an invalid one, kind none, the base's scripts or hooks to do, not connected, a tree not
509
+ clean — and exit 1.`,
510
+ },
511
+ 'port item': {
512
+ script: 'scripts/port/item.mjs',
513
+ summary: 'show what one toolchain item writes from the templates, or with --write write it and run its checks, or --check alone; commit nothing (K-2)',
514
+ manual: `codelife port item <a1|a2|b|c|d|e|e'|f> [--write | --check] [--test <file>] [--playground]
515
+
516
+ Run from the repository's root. Without a flag, reads only: what the item writes from the plugin —
517
+ b the characterisation tests, their declaration half left out when the build ships none; d
518
+ vite.config.ts, and with --playground the playground and its dev script; e tsconfig.json; f the
519
+ target's five scripts — each file's difference included, the generated[] entry d implies, and the
520
+ checks it runs. With --write, writes them, then runs the checks: the item's own, then test:all — f
521
+ runs the five, test:one on --test. With --check, the checks alone. Prints \`- paths:\` for
522
+ \`codelife commit\`; a \`- stop:\` line exits 1 with nothing written, a \`- failed:\` line exits 1 after.`,
523
+ },
524
+ 'port version': {
525
+ script: 'scripts/port/version.mjs',
526
+ summary: 'the version a tool moves to: past minimumReleaseAge, vite-plus\'s exact pin, or the newest every peer range admits (R-162)',
527
+ manual: `codelife port version <tool>
528
+
529
+ Run from the repository's root. Reads the registry through pnpm, and pnpm-lock.yaml. Prints one
530
+ \`### port version\` block: the current version, the window, each lockfile package's peer range on the
531
+ tool, then \`- version:\` — vite-plus's newest release past the window, the exact version it pins for a
532
+ tool it carries (Vitest and @vitest/*, Oxlint, Oxfmt, Vite), else the newest past the window every
533
+ range admits. \`- ask:\` for a move across a major, with the newest release inside the current one;
534
+ \`- held:\` for a newer release the window still holds. Exit 1 when the registry does not answer.`,
535
+ },
536
+ 'onboard prep': {
537
+ script: 'scripts/onboard/prep.mjs',
538
+ summary: 'state the documentation set before /onboard proposes: the set the kind makes, each document and when it changed, the facts, the open bugs and pending notes (K-3)',
539
+ manual: `codelife onboard prep
540
+
541
+ Run from the repository's root. Reads only. Prints one \`### onboard prep\` block: \`- kind:\` and the set it
542
+ makes — README, CONTRIBUTING, CLAUDE.md, a library's SKILL.md beside its version file, a workspace
543
+ package's CLAUDE.md where one exists —; one \`- document <name>:\` line each, absent, or present with its
544
+ last commit against the code's, and for SKILL.md a frontmatter name that is no skill name or a
545
+ \`files\` list it is missing from; the facts — package, entry points, workspace packages, source and
546
+ test files by directory, hooks, release, generated[], licence —; \`- known:\` the open bugs by title,
547
+ \`not read\` with the reason when the tracker does not answer; \`- notes:\` the pending notes of
548
+ docs/brainstorm/. A \`- stop:\` line — no contract or an invalid one, a document of the set with changes
549
+ not committed — and exit 1.`,
550
+ },
551
+ 'log since': {
552
+ script: 'scripts/git/log_since.mjs',
553
+ summary: 'print the commits since a ref whose footer cites an issue (R-201)',
554
+ manual: `codelife log since <ref> <n>
555
+
556
+ Run from the repository's root. Prints one \`<sha> <subject>\` line per commit of <ref>..HEAD whose
557
+ \`Closes:\` or \`Refs:\` footer cites #<n>; exit 1, nothing on stdout, when none does.`,
558
+ },
559
+ }
560
+
561
+ // The methods two briefs share (anatomy.md R-289), scripts/methods/<name>.md, and the templates a
562
+ // brief drafts from — an issue's, scripts/tracker/templates/, a specification document's,
563
+ // scripts/target/templates/spec/: one file each, printed by `codelife help method|template <name>`
564
+ // rather than loaded as a skill. `method` and `template` return its text, or undefined.
565
+ const shelf = (...dirs) => {
566
+ const files = () => Object.fromEntries(dirs.flatMap((d) => readdirSync(d).filter((f) => f.endsWith('.md')).map((f) => [f.slice(0, -3), new URL(f, d)])))
567
+ return [() => Object.keys(files()).sort(), (name) => Object.hasOwn(files(), name) ? readFileSync(files()[name], 'utf8') : undefined]
568
+ }
569
+ export const [methods, method] = shelf(new URL('./methods/', import.meta.url))
570
+ export const [templates, template] = shelf(new URL('./tracker/templates/', import.meta.url), new URL('./target/templates/spec/', import.meta.url))
571
+
572
+ // verb <words> — the longest verb whose words open the list, and the words after it; or undefined.
573
+ export const verb = (words) => {
574
+ for (let k = words.length; k > 0; k--) {
575
+ const name = words.slice(0, k).join(' ')
576
+ if (Object.hasOwn(VERBS, name)) return [name, words.slice(k)]
577
+ }
578
+ return undefined
579
+ }
@@ -0,0 +1,33 @@
1
+ // BUILD's facts: the build runs, silently, leaves the committed output as it is, and gives the same
2
+ // bytes twice. It builds in the tree, as the campaign that runs it says in its *Method*.
3
+ import { createHash } from 'node:crypto';
4
+ import { existsSync, readFileSync, statSync } from 'node:fs';
5
+ import { absent, fail, lines, manifest, named, paths, runner, sh } from './lib.mjs';
6
+
7
+ const pkg = manifest();
8
+ if (!pkg.scripts?.build) absent('no build script — BUILD has no subject');
9
+ const [pm, run] = runner(pkg);
10
+ const build = () => sh(pm, [...run, 'build']);
11
+
12
+ // What a build wrote: tracked files it changed, and files it created, ignored ones included.
13
+ const touched = () =>
14
+ [
15
+ ...paths('diff', '--name-only'),
16
+ ...paths('ls-files', '--others', '--exclude-standard'),
17
+ ...paths('ls-files', '--others', '--ignored', '--exclude-standard'),
18
+ ].filter((p) => !p.startsWith('node_modules/') && existsSync(p) && statSync(p).isFile());
19
+ const hashes = (paths) => new Map(paths.map((p) => [p, createHash('sha256').update(readFileSync(p)).digest('hex')]));
20
+
21
+ const first = build();
22
+ if (first.status !== 0) {
23
+ fail(`build fails: exit ${first.status}`);
24
+ process.exit(0);
25
+ }
26
+ for (const l of lines(`${first.out}\n${first.err}`))
27
+ if (/\bwarn(ing)?\b/i.test(l) && !/^(npm|pnpm|yarn) warn/i.test(l)) fail(`build warns: ${l.trim()}`);
28
+ for (const p of paths('diff', '--name-only')) fail(`stale committed output: ${named(p)}`);
29
+
30
+ const once = hashes(touched());
31
+ build();
32
+ const twice = hashes([...once.keys()].filter(existsSync));
33
+ for (const [p, h] of once) if (twice.get(p) !== h) fail(`not reproducible: ${named(p)}`);
@@ -0,0 +1,15 @@
1
+ // DEPS's facts: one lockfile, the manager's own, and a runtime and a manager pinned. Which
2
+ // dependency fixes a horizon, and what the scripts call undeclared, are the hygiene subagent's.
3
+ import { existsSync } from 'node:fs';
4
+ import { fail, manifest } from './lib.mjs';
5
+
6
+ const pkg = manifest();
7
+ const managers = { 'package-lock.json': 'npm', 'pnpm-lock.yaml': 'pnpm', 'yarn.lock': 'yarn' };
8
+ const locks = Object.keys(managers).filter((f) => existsSync(f));
9
+ const named = (pkg.packageManager || '').split('@')[0];
10
+
11
+ if (locks.length > 1) fail(`several lockfiles: ${locks.join(' ')}`);
12
+ for (const lock of locks)
13
+ if (named && managers[lock] !== named) fail(`lockfile ${lock} does not match packageManager ${named}`);
14
+ if (!pkg.engines) fail('no engines');
15
+ if (!pkg.packageManager) fail('no packageManager');