@orkestrel/scaffold 0.0.77 → 0.0.79

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 (158) hide show
  1. package/dist/agents/skills/orkestrel-dispatch/scripts/bench.js +204 -0
  2. package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +102 -0
  3. package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +95 -0
  4. package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +207 -0
  5. package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +108 -0
  6. package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +114 -0
  7. package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +108 -0
  8. package/dist/agents/skills/orkestrel-dispatch/scripts/sweep.js +156 -0
  9. package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +196 -0
  10. package/dist/agents/skills/orkestrel-publish/scripts/compare.js +206 -0
  11. package/dist/agents/skills/orkestrel-publish/scripts/pins.js +93 -0
  12. package/dist/agents/skills/orkestrel-publish/scripts/wave.js +458 -0
  13. package/dist/agents/skills/orkestrel-publish/scripts/window.js +188 -0
  14. package/dist/agents/skills/orkestrel-scout/scripts/map.js +300 -0
  15. package/dist/agents/templates/brief.md +55 -0
  16. package/dist/bin/main.js +58 -6
  17. package/dist/bin/main.js.map +1 -1
  18. package/dist/host/AGENTS.md +77 -135
  19. package/dist/host/agents/orchestration.md +147 -998
  20. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +2 -2
  21. package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +1 -1
  22. package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/SKILL.md +6 -13
  23. package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/agents/openai.yaml +1 -1
  24. package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/references/fleet.md +5 -7
  25. package/dist/host/agents/skills/{orkestrel-build-application → orkestrel-build}/SKILL.md +11 -22
  26. package/dist/host/agents/skills/{orkestrel-build-application → orkestrel-build}/agents/openai.yaml +1 -1
  27. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +8 -16
  28. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +3 -3
  29. package/dist/host/agents/skills/orkestrel-debrief/references/retention.md +13 -13
  30. package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +61 -0
  31. package/dist/host/agents/skills/orkestrel-dispatch/agents/openai.yaml +4 -0
  32. package/dist/host/agents/skills/orkestrel-dispatch/references/bench.md +25 -0
  33. package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +32 -0
  34. package/dist/host/agents/skills/orkestrel-dispatch/scripts/bench.ts +259 -0
  35. package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +110 -0
  36. package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +115 -0
  37. package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +239 -0
  38. package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +124 -0
  39. package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +123 -0
  40. package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +129 -0
  41. package/dist/host/agents/skills/orkestrel-dispatch/scripts/sweep.ts +157 -0
  42. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +42 -193
  43. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +38 -108
  44. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +35 -134
  45. package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/SKILL.md +10 -14
  46. package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/agents/openai.yaml +1 -1
  47. package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/hardening.md +3 -4
  48. package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +228 -0
  49. package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/SKILL.md +15 -23
  50. package/dist/host/agents/skills/orkestrel-journey/agents/openai.yaml +4 -0
  51. package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/captures.md +1 -1
  52. package/dist/host/agents/skills/{orkestrel-polish-surface → orkestrel-polish}/SKILL.md +25 -33
  53. package/dist/host/agents/skills/{orkestrel-polish-surface → orkestrel-polish}/agents/openai.yaml +1 -1
  54. package/dist/host/agents/skills/{orkestrel-polish-surface → orkestrel-polish}/references/capture-harness.md +3 -3
  55. package/dist/host/agents/skills/orkestrel-publish/SKILL.md +33 -20
  56. package/dist/host/agents/skills/orkestrel-publish/references/release.md +39 -0
  57. package/dist/host/agents/skills/orkestrel-publish/references/wave.md +22 -21
  58. package/dist/host/agents/skills/orkestrel-publish/references/window.md +27 -14
  59. package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +220 -0
  60. package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +114 -0
  61. package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +629 -0
  62. package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +242 -0
  63. package/dist/host/agents/skills/orkestrel-scout/SKILL.md +28 -0
  64. package/dist/host/agents/skills/orkestrel-scout/agents/openai.yaml +4 -0
  65. package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +352 -0
  66. package/dist/host/agents/templates/brief.md +21 -142
  67. package/dist/host/agents/transports/claude-cli.md +21 -0
  68. package/dist/host/agents/transports/codex.md +38 -159
  69. package/dist/host/agents/transports/cursor.md +16 -65
  70. package/dist/host/claude/AGENTS.md +38 -0
  71. package/dist/host/claude/agents/analyst.md +14 -53
  72. package/dist/host/claude/agents/astra.md +26 -0
  73. package/dist/host/claude/agents/builder.md +14 -30
  74. package/dist/host/claude/agents/checker.md +13 -57
  75. package/dist/host/claude/agents/distiller.md +11 -26
  76. package/dist/host/claude/agents/grok.md +12 -35
  77. package/dist/host/claude/agents/opus.md +14 -30
  78. package/dist/host/claude/agents/orkestrel.md +4 -4
  79. package/dist/host/claude/agents/planner.md +10 -44
  80. package/dist/host/claude/agents/researcher.md +11 -30
  81. package/dist/host/claude/agents/reviewer.md +11 -95
  82. package/dist/host/claude/agents/scout.md +9 -23
  83. package/dist/host/claude/agents/verifier.md +15 -33
  84. package/dist/host/claude/rules/documentation.md +8 -2
  85. package/dist/host/claude/rules/portability.md +7 -1
  86. package/dist/host/claude/rules/quality.md +36 -96
  87. package/dist/host/claude/rules/styles.md +3 -0
  88. package/dist/host/claude/rules/tests.md +6 -3
  89. package/dist/host/claude/rules/workspace.md +21 -15
  90. package/dist/host/claude/rules/writing.md +57 -108
  91. package/dist/host/claude/settings.json +5 -3
  92. package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +1 -1
  93. package/dist/host/claude/skills/{orkestrel-align-packages → orkestrel-align}/SKILL.md +2 -2
  94. package/dist/host/claude/skills/{orkestrel-build-application → orkestrel-build}/SKILL.md +2 -2
  95. package/dist/host/claude/skills/orkestrel-dispatch/SKILL.md +11 -0
  96. package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +2 -1
  97. package/dist/host/claude/skills/{orkestrel-harden-package → orkestrel-harden}/SKILL.md +2 -2
  98. package/dist/host/claude/skills/{orkestrel-prove-journey → orkestrel-journey}/SKILL.md +2 -2
  99. package/dist/host/claude/skills/orkestrel-polish/SKILL.md +12 -0
  100. package/dist/host/claude/skills/orkestrel-scout/SKILL.md +11 -0
  101. package/dist/host/codex/agents/analyst.toml +14 -31
  102. package/dist/host/codex/agents/astra.toml +25 -0
  103. package/dist/host/codex/agents/builder.toml +13 -20
  104. package/dist/host/codex/agents/checker.toml +13 -27
  105. package/dist/host/codex/agents/distiller.toml +9 -22
  106. package/dist/host/codex/agents/grok.toml +11 -30
  107. package/dist/host/codex/agents/opus.toml +14 -22
  108. package/dist/host/codex/agents/orkestrel.toml +1 -1
  109. package/dist/host/codex/agents/planner.toml +11 -28
  110. package/dist/host/codex/agents/researcher.toml +10 -22
  111. package/dist/host/codex/agents/reviewer.toml +11 -27
  112. package/dist/host/codex/agents/scout.toml +11 -17
  113. package/dist/host/codex/agents/verifier.toml +16 -12
  114. package/dist/host/codex/config.toml +18 -21
  115. package/dist/host/cursor/mcp.json +0 -4
  116. package/dist/host/cursor/rules/orchestration.mdc +12 -20
  117. package/dist/host/dotfiles/mcp.json +0 -4
  118. package/dist/host/dotfiles/oxlintrc.json +7 -0
  119. package/dist/host/guides/probe.md +18 -14
  120. package/dist/host/guides/scaffold.md +147 -83
  121. package/dist/host/guides/test.md +442 -148
  122. package/dist/host/manifest.json +322 -185
  123. package/dist/host/scripts/codex.sh +0 -0
  124. package/dist/host/scripts/cursor.sh +0 -0
  125. package/dist/host/scripts/deps.sh +0 -0
  126. package/dist/host/scripts/ollama.sh +0 -0
  127. package/dist/host/tests/config.test.ts +86 -55
  128. package/dist/host/tests/policy.test.ts +1 -5
  129. package/dist/host/tests/setupPolicy.ts +179 -4
  130. package/dist/src/core/index.cjs +264 -89
  131. package/dist/src/core/index.cjs.map +1 -1
  132. package/dist/src/core/index.d.cts +95 -30
  133. package/dist/src/core/index.d.ts +95 -30
  134. package/dist/src/core/index.js +262 -90
  135. package/dist/src/core/index.js.map +1 -1
  136. package/dist/src/server/index.cjs +55 -9
  137. package/dist/src/server/index.cjs.map +1 -1
  138. package/dist/src/server/index.d.cts +29 -4
  139. package/dist/src/server/index.d.ts +29 -4
  140. package/dist/src/server/index.js +56 -11
  141. package/dist/src/server/index.js.map +1 -1
  142. package/package.json +16 -12
  143. package/dist/host/CLAUDE.md +0 -61
  144. package/dist/host/agents/skills/orkestrel-prove-journey/agents/openai.yaml +0 -4
  145. package/dist/host/agents/transports/claude.md +0 -49
  146. package/dist/host/claude/agents/application.md +0 -36
  147. package/dist/host/claude/agents/sol.md +0 -61
  148. package/dist/host/claude/skills/orkestrel-polish-surface/SKILL.md +0 -12
  149. package/dist/host/codex/agents/application.toml +0 -25
  150. package/dist/host/codex/agents/sol.toml +0 -19
  151. /package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/references/integration.md +0 -0
  152. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/centralization.md +0 -0
  153. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/contract.md +0 -0
  154. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/research.md +0 -0
  155. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/decide.md +0 -0
  156. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/layer.md +0 -0
  157. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/statechart.md +0 -0
  158. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/styles.md +0 -0
@@ -0,0 +1,300 @@
1
+ // Map terrain before a brief, an absorption lane, or a rename. Run from the checkout root:
2
+ // node .agents/skills/orkestrel-scout/scripts/map.ts --tree PATH... [--headings PATH...] [--frontmatter PATH...] [--exports PATH...] [--census TERM...] [--refs PATH] [--anchors PATH...] [--paths a,b] [--ignore-case] [--json] [--out FILE]
3
+ // --tree lists every file under each path with its line count and size. --headings lists every
4
+ // Markdown heading with its line. --frontmatter lists every key of a Markdown frontmatter block, a
5
+ // TOML file, or a YAML file with its whole value, a nested key dotted under its parents
6
+ // (`interface.default_prompt`) and a TOML key under its table. --exports lists every `export`
7
+ // declaration line in a TypeScript file (a text reading, not the compiler's). --census lists every line carrying a term. --refs lists
8
+ // every line naming a path or its basename. --anchors lists every `§ Heading` reference whose
9
+ // heading the named file, or the same file, does not carry. Walks skip node_modules, .git, dist,
10
+ // tmp, .orkestrel, .idea, and host.json; --paths narrows a census or refs walk. Modes combine, each
11
+ // printing its section; --json prints one object; --out writes the output to FILE instead of the
12
+ // terminal. Give each flag once; a later duplicate is not read. Exit 0, or 64 when no mode is
13
+ // given or --refs names no path.
14
+ import { existsSync, readFileSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
15
+ import { basename, dirname } from 'node:path';
16
+ import { listFiles, normalizeSlashes, readList, readMissingFlags, readOption, } from "../../orkestrel-dispatch/scripts/helpers.js";
17
+ const EXPORT = /^export\s+(?:default\s+)?(?:async\s+)?(?:abstract\s+)?(function\*?|const|let|class|interface|type|enum|namespace)\s+([A-Za-z_$][\w$]*)/u;
18
+ const HEADING = /^(#{1,6})\s+(.+?)\s*#*\s*$/u;
19
+ const ANCHOR = /(?:`([^`\n]+\.md)`\s*)?§\s*"?([^"`\n|;,.)]+?)"?(?=\s*(?:[,.;)|]|\s(?:and|or|names|fixes|owns|states|binds|governs|decides|before|after)\b|$))/gu;
20
+ const BINARY = /\.(png|jpg|jpeg|gif|webp|ico|woff2?|ttf|otf|eot|zip|tgz|gz|pdf|wasm)$/u;
21
+ function isText(path) {
22
+ return !BINARY.test(path) && basename(path) !== 'host.json';
23
+ }
24
+ function expandPaths(paths) {
25
+ return paths.flatMap((path) => {
26
+ if (!existsSync(path))
27
+ return [];
28
+ if (statSync(path).isDirectory())
29
+ return listFiles(path).map((file) => file.path);
30
+ return [normalizeSlashes(path)];
31
+ });
32
+ }
33
+ function readLines(path) {
34
+ return readFileSync(path, 'utf8').split(/\r\n|\n/);
35
+ }
36
+ function mapTree(paths) {
37
+ return expandPaths(paths)
38
+ .filter(isText)
39
+ .map((path) => {
40
+ const text = readFileSync(path, 'utf8');
41
+ return {
42
+ path,
43
+ lines: text === '' ? 0 : text.split(/\r\n|\n/).length,
44
+ bytes: Buffer.byteLength(text),
45
+ };
46
+ })
47
+ .sort((left, right) => left.path.localeCompare(right.path));
48
+ }
49
+ function mapHeadings(paths) {
50
+ const rows = [];
51
+ for (const path of expandPaths(paths).filter((candidate) => candidate.endsWith('.md'))) {
52
+ let fenced = false;
53
+ readLines(path).forEach((text, index) => {
54
+ if (text.startsWith('```'))
55
+ fenced = !fenced;
56
+ if (fenced)
57
+ return;
58
+ const match = text.match(HEADING);
59
+ if (match?.[1] !== undefined && match[2] !== undefined) {
60
+ rows.push({ path, line: index + 1, text: `${match[1]} ${match[2]}` });
61
+ }
62
+ });
63
+ }
64
+ return rows;
65
+ }
66
+ function mapExports(paths) {
67
+ const rows = [];
68
+ for (const path of expandPaths(paths).filter((candidate) => /\.[cm]?ts$/u.test(candidate))) {
69
+ readLines(path).forEach((text, index) => {
70
+ const match = text.match(EXPORT);
71
+ if (match?.[1] !== undefined && match[2] !== undefined) {
72
+ rows.push({ path, line: index + 1, text: `${match[1]} ${match[2]}` });
73
+ }
74
+ else if (/^export\s+\*\s+from\s+/u.test(text)) {
75
+ rows.push({ path, line: index + 1, text: text.trim() });
76
+ }
77
+ });
78
+ }
79
+ return rows;
80
+ }
81
+ function buildMatcher(term, ignoreCase) {
82
+ const needle = ignoreCase ? term.toLowerCase() : term;
83
+ return (text) => (ignoreCase ? text.toLowerCase() : text).includes(needle);
84
+ }
85
+ function mapCensus(terms, roots, ignoreCase) {
86
+ const files = expandPaths(roots).filter(isText);
87
+ return terms.map((term) => {
88
+ const matches = buildMatcher(term, ignoreCase);
89
+ const rows = [];
90
+ for (const path of files) {
91
+ readLines(path).forEach((text, index) => {
92
+ if (matches(text))
93
+ rows.push({ path, line: index + 1, text: text.trim().slice(0, 160) });
94
+ });
95
+ }
96
+ return { term, rows };
97
+ });
98
+ }
99
+ function mapRefs(target, roots) {
100
+ const needle = normalizeSlashes(target);
101
+ const name = basename(needle);
102
+ const rows = [];
103
+ for (const path of expandPaths(roots).filter(isText)) {
104
+ if (path === needle)
105
+ continue;
106
+ readLines(path).forEach((text, index) => {
107
+ if (text.includes(needle) || text.includes(name)) {
108
+ rows.push({ path, line: index + 1, text: text.trim().slice(0, 160) });
109
+ }
110
+ });
111
+ }
112
+ return rows;
113
+ }
114
+ function readYamlKeys(path, lines, offset) {
115
+ const rows = [];
116
+ const stack = [];
117
+ lines.forEach((text, index) => {
118
+ const content = text.trimStart();
119
+ if (content === '' || content.startsWith('#'))
120
+ return;
121
+ const indent = text.length - content.length;
122
+ const match = content.match(/^([A-Za-z_][\w-]*)\s*:(?:\s+(.*))?$/u);
123
+ if (match?.[1] === undefined) {
124
+ // A list item, a block scalar line, or a wrapped value extends the key before it.
125
+ const last = rows.at(-1);
126
+ if (last !== undefined && indent >= (stack.at(-1)?.indent ?? 0)) {
127
+ rows[rows.length - 1] = { ...last, text: `${last.text} ${content.trim()}`.trimEnd() };
128
+ }
129
+ return;
130
+ }
131
+ while (stack.length > 0 && (stack.at(-1)?.indent ?? 0) >= indent)
132
+ stack.pop();
133
+ const key = [...stack.map((entry) => entry.key), match[1]].join('.');
134
+ stack.push({ indent, key: match[1] });
135
+ rows.push({ path, line: index + offset, text: `${key}: ${(match[2] ?? '').trim()}`.trimEnd() });
136
+ });
137
+ return rows;
138
+ }
139
+ function readTomlKeys(path, lines, offset) {
140
+ const rows = [];
141
+ let table = '';
142
+ let fence;
143
+ lines.forEach((text, index) => {
144
+ if (fence !== undefined) {
145
+ // The body of a multi-line string carries no key.
146
+ if (text.includes(fence))
147
+ fence = undefined;
148
+ return;
149
+ }
150
+ const header = text.match(/^\s*\[\[?([^\]]+)\]\]?\s*$/u);
151
+ if (header?.[1] !== undefined) {
152
+ table = header[1].trim();
153
+ return;
154
+ }
155
+ const match = text.match(/^\s*([A-Za-z0-9_.-]+|"[^"]+")\s*=\s*(.*)$/u);
156
+ if (match?.[1] === undefined)
157
+ return;
158
+ const value = (match[2] ?? '').trim();
159
+ const opening = value.match(/^("""|''')/u)?.[1];
160
+ if (opening !== undefined && value.indexOf(opening, 3) === -1)
161
+ fence = opening;
162
+ rows.push({
163
+ path,
164
+ line: index + offset,
165
+ text: `${table === '' ? '' : `${table}.`}${match[1]}: ${value}`.trimEnd(),
166
+ });
167
+ });
168
+ return rows;
169
+ }
170
+ function mapFrontmatter(paths) {
171
+ const rows = [];
172
+ for (const path of expandPaths(paths).filter((candidate) => /\.(md|mdc|toml|ya?ml)$/u.test(candidate))) {
173
+ const lines = readLines(path);
174
+ const markdown = /\.mdc?$/u.test(path);
175
+ const end = markdown ? lines.indexOf('---', 1) : lines.length;
176
+ if (markdown && (lines[0] !== '---' || end === -1))
177
+ continue;
178
+ const body = lines.slice(markdown ? 1 : 0, end);
179
+ const offset = markdown ? 2 : 1;
180
+ rows.push(...(path.endsWith('.toml')
181
+ ? readTomlKeys(path, body, offset)
182
+ : readYamlKeys(path, body, offset)));
183
+ }
184
+ return rows;
185
+ }
186
+ function readHeadingTexts(path) {
187
+ return new Set(mapHeadings([path]).map((row) => row.text.replace(/^#+\s+/u, '').toLowerCase()));
188
+ }
189
+ function mapAnchors(paths) {
190
+ const headings = new Map();
191
+ const rows = [];
192
+ for (const path of expandPaths(paths).filter((candidate) => candidate.endsWith('.md'))) {
193
+ readLines(path).forEach((text, index) => {
194
+ for (const match of text.matchAll(ANCHOR)) {
195
+ const target = match[1] === undefined ? path : normalizeSlashes(match[1]);
196
+ const heading = (match[2] ?? '').trim();
197
+ if (heading === '')
198
+ continue;
199
+ if (!existsSync(target)) {
200
+ rows.push({ path, line: index + 1, target, heading });
201
+ continue;
202
+ }
203
+ const known = headings.get(target) ?? readHeadingTexts(target);
204
+ headings.set(target, known);
205
+ if (!known.has(heading.toLowerCase()))
206
+ rows.push({ path, line: index + 1, target, heading });
207
+ }
208
+ });
209
+ }
210
+ return rows;
211
+ }
212
+ function renderReport(report) {
213
+ const lines = [];
214
+ if (report.tree !== undefined) {
215
+ lines.push('## Tree');
216
+ for (const row of report.tree)
217
+ lines.push(`${row.path}\t${row.lines} lines\t${row.bytes} bytes`);
218
+ lines.push(`total\t${report.tree.length} files\t${report.tree.reduce((sum, row) => sum + row.lines, 0)} lines`);
219
+ }
220
+ if (report.headings !== undefined) {
221
+ lines.push('## Headings');
222
+ for (const row of report.headings)
223
+ lines.push(`${row.path}:${row.line}\t${row.text}`);
224
+ }
225
+ if (report.frontmatter !== undefined) {
226
+ lines.push('## Frontmatter');
227
+ for (const row of report.frontmatter)
228
+ lines.push(`${row.path}:${row.line} ${row.text}`);
229
+ }
230
+ if (report.exports !== undefined) {
231
+ lines.push('## Exports (text reading)');
232
+ for (const row of report.exports)
233
+ lines.push(`${row.path}:${row.line}\t${row.text}`);
234
+ }
235
+ if (report.census !== undefined) {
236
+ for (const entry of report.census) {
237
+ lines.push(`## Census: ${entry.term} (${entry.rows.length})`);
238
+ for (const row of entry.rows)
239
+ lines.push(`${row.path}:${row.line}\t${row.text}`);
240
+ }
241
+ }
242
+ if (report.refs !== undefined) {
243
+ lines.push(`## Refs (${report.refs.length})`);
244
+ for (const row of report.refs)
245
+ lines.push(`${row.path}:${row.line}\t${row.text}`);
246
+ }
247
+ if (report.anchors !== undefined) {
248
+ lines.push(`## Unresolved anchors (${report.anchors.length})`);
249
+ for (const row of report.anchors)
250
+ lines.push(`${row.path}:${row.line}\t${row.target} § ${row.heading}`);
251
+ }
252
+ return `${lines.join('\n')}\n`;
253
+ }
254
+ function main(argv) {
255
+ const missing = readMissingFlags(argv, ['--refs', '--paths', '--out']);
256
+ if (missing.length > 0) {
257
+ console.error(`map: ${missing.join(', ')} given with no value`);
258
+ return 64;
259
+ }
260
+ const roots = (readOption(argv, '--paths') ?? '.').split(',');
261
+ const ignoreCase = argv.includes('--ignore-case');
262
+ const tree = readList(argv, '--tree');
263
+ const headings = readList(argv, '--headings');
264
+ const frontmatter = readList(argv, '--frontmatter');
265
+ const exports = readList(argv, '--exports');
266
+ const census = readList(argv, '--census');
267
+ const refs = readOption(argv, '--refs');
268
+ const anchors = readList(argv, '--anchors');
269
+ if (tree.length +
270
+ headings.length +
271
+ frontmatter.length +
272
+ exports.length +
273
+ census.length +
274
+ anchors.length ===
275
+ 0 &&
276
+ refs === undefined) {
277
+ console.error('usage: map.ts [--tree PATH...] [--headings PATH...] [--frontmatter PATH...] [--exports PATH...] [--census TERM...] [--refs PATH] [--anchors PATH...] [--paths a,b] [--ignore-case] [--json] [--out FILE]');
278
+ return 64;
279
+ }
280
+ const report = {
281
+ ...(tree.length > 0 ? { tree: mapTree(tree) } : {}),
282
+ ...(headings.length > 0 ? { headings: mapHeadings(headings) } : {}),
283
+ ...(frontmatter.length > 0 ? { frontmatter: mapFrontmatter(frontmatter) } : {}),
284
+ ...(exports.length > 0 ? { exports: mapExports(exports) } : {}),
285
+ ...(census.length > 0 ? { census: mapCensus(census, roots, ignoreCase) } : {}),
286
+ ...(refs === undefined ? {} : { refs: mapRefs(refs, roots) }),
287
+ ...(anchors.length > 0 ? { anchors: mapAnchors(anchors) } : {}),
288
+ };
289
+ const output = argv.includes('--json') ? `${JSON.stringify(report)}\n` : renderReport(report);
290
+ const out = readOption(argv, '--out');
291
+ if (out === undefined)
292
+ process.stdout.write(output);
293
+ else {
294
+ mkdirSync(dirname(out), { recursive: true });
295
+ writeFileSync(out, output);
296
+ console.log(`map: wrote ${out}`);
297
+ }
298
+ return 0;
299
+ }
300
+ process.exitCode = main(process.argv.slice(2));
@@ -0,0 +1,55 @@
1
+ # Unit UNIT_ID — SHORT_SUBJECT
2
+
3
+ Fill every section. Write `none` in an empty one. Replace each `UPPER_SNAKE_CASE` placeholder.
4
+
5
+ ## Role and engine
6
+
7
+ ROLE on ENGINE, reached as TRANSPORT. Executor: NATIVE_SUBAGENT | BENCH_ENGINE | BRIDGE_DRIVER.
8
+
9
+ ## Objective
10
+
11
+ ONE_OUTCOME.
12
+
13
+ ## Context
14
+
15
+ - **Evidence.** COMMANDS_AND_OUTPUT behind every fact.
16
+ - **Law.** `AGENTS.md`; RULE_FILES; SKILL and the references it names; GUIDE_OR_SPEC.
17
+ - **Installed primitives.** ORKESTREL_PACKAGES with the surface each unit reads first. A local helper whose job an installed export does is a defect.
18
+ - **Host.** SHELL, WORKING_PATH, SANDBOX_NETWORK_APPROVAL_LIMITS.
19
+ - **Standing conditions.** DIRTY_FILES, KNOWN_FAILING_COMMANDS, BLOCKED_TOOLS, and who repairs each.
20
+
21
+ ## Unknowns
22
+
23
+ UNKNOWN and how the unit reports it.
24
+
25
+ ## Scope
26
+
27
+ - **Owned.** FILES, including the tests that pin the behavior, the fixtures derived from a constant, and the materialized copy of a template.
28
+ - **Shared (report-only).** FILES; return an exact patch.
29
+ - **Off-limits.** FILES. Never list `tmp/probes/` here.
30
+ - **Made false by this change.** FILES, derived by running the suite or by a named search bound.
31
+ - **Tools and limits.** ALLOWED_TOOLS; scoped validation only; no tree-wide mutating command.
32
+
33
+ ## Execution
34
+
35
+ Perform the assignment yourself and spawn nothing. (Bridge driver: carry this brief unaltered, launch ENGINE through its CLI, and return the journal path and session id with the result.)
36
+
37
+ ## Output
38
+
39
+ RETURN_SHAPE through OUTPUT_MECHANISM. No process diary.
40
+
41
+ ## Deviation contract
42
+
43
+ Stop and report (expected, found, evidence, done or not done, one hypothesis) on OBJECTIVE_CONFLICT. Settle ANCILLARY_CHOICES yourself and record them.
44
+
45
+ ## Acceptance criteria
46
+
47
+ 1. CHEAPEST_GATE (regeneration, typecheck, or lint over owned files)
48
+ 2. SCOPED_TEST
49
+ 3. ARTIFACT_CRITERION
50
+
51
+ **Observations, not criteria.** TIMING_SENSITIVE_OR_TREE_WIDE_GATES the unit reports and the Orchestrator re-runs.
52
+
53
+ ## Review evidence
54
+
55
+ The actual diff and `git status --porcelain` for a code change; the capture portfolio for a rendered surface; the proposal, the canon it must satisfy, and its motivation for a process proposal.
package/dist/bin/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { align, renderTable, strip, stripControls, width } from "@orkestrel/console";
3
3
  import { attempt, isArray, isError, isInstance, isRecord, isString, parseJSON } from "@orkestrel/contract";
4
- import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, JOURNEY_CONFIG_PATH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, ScaffoldError, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, blueprintToTestArtifacts, blueprintToWritableScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isFloorPath, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, replaceManifestScripts, replacePlanRanges } from "../src/core/index.js";
4
+ import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, JOURNEY_CONFIG_PATH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, SKILLS_CONFIG_PATH, ScaffoldError, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, blueprintToTestArtifacts, blueprintToWritableScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isFloorPath, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, replaceManifestScripts, replacePlanRanges } from "../src/core/index.js";
5
5
  import { MAX_INVENTORY_PATHS, Materializer, Upstream, filesToHost, isExactCaseFile, isPhysicalDirectory, isWorktree, listFiles, readFileText, readHostFloor, readHostManifest, readSnapshot, resolveContainedPath } from "../src/server/index.js";
6
6
  import { createMarkdown, flattenText, isTableNode } from "@orkestrel/markdown";
7
7
  import { createSession } from "@orkestrel/process/server";
@@ -502,6 +502,55 @@ function manifestToWritableDependencies(manifest, blueprint) {
502
502
  };
503
503
  }
504
504
  /**
505
+ * Reads the manifest scripts a writing verb may write.
506
+ *
507
+ * @param manifest - The target manifest text.
508
+ * @param blueprint - The workspace shape that supplies the planned scripts.
509
+ * @returns The blueprint's writable scripts, followed by the planned `test` chain when the
510
+ * declared chain is a generated predecessor of it.
511
+ *
512
+ * @remarks
513
+ * A declared `test` chain is a generated predecessor when it runs fewer `&&` steps than the
514
+ * planned chain and every step it runs is a planned step, in the planned order. That is the chain
515
+ * a birth or an earlier write left before a structural fact planned another step, such as a root
516
+ * `tests/setupBrowser.test.ts` proof planning `npm run test:setup:browser`, so the write lands the
517
+ * planned chain in its place. A chain running a step the plan does not generate, or running the
518
+ * planned steps in another order, is one the package owns, and no entry names it.
519
+ *
520
+ * The planned chain joins only when every step it adds runs a script the manifest declares or the
521
+ * writable scripts supply. The `test:src` and `test:app` aggregates sit outside the writable
522
+ * scripts, so a planned chain adding an aggregate the manifest lacks stays with the package rather
523
+ * than landing a step that names a missing script.
524
+ */
525
+ function manifestToWritableScripts(manifest, blueprint) {
526
+ const writable = blueprintToWritableScripts(blueprint);
527
+ const planned = blueprintToScripts(blueprint).test;
528
+ const parsed = parseJSON(manifest);
529
+ const scripts = isRecord(parsed) && isRecord(parsed.scripts) ? parsed.scripts : {};
530
+ const declared = scripts.test;
531
+ if (planned === void 0 || !isString(declared)) return writable;
532
+ const steps = declared.split("&&").map((step) => step.trim());
533
+ const expected = planned.split("&&").map((step) => step.trim());
534
+ if (steps.length >= expected.length) return writable;
535
+ let cursor = 0;
536
+ for (const step of steps) {
537
+ while (cursor < expected.length && expected[cursor] !== step) cursor += 1;
538
+ if (cursor === expected.length) return writable;
539
+ cursor += 1;
540
+ }
541
+ const supplied = new Set(writable.map(({ name }) => name));
542
+ for (const step of expected) {
543
+ if (steps.includes(step)) continue;
544
+ const name = /^npm run (\S+)$/.exec(step)?.[1];
545
+ if (name === void 0 || !supplied.has(name) && !isString(scripts[name])) return writable;
546
+ }
547
+ return [...writable, {
548
+ name: "test",
549
+ command: planned,
550
+ accepted: [declared]
551
+ }];
552
+ }
553
+ /**
505
554
  * Keeps only dependencies published by the Orkestrel fleet.
506
555
  *
507
556
  * @param dependencies - The declared dependencies to inspect.
@@ -1447,7 +1496,7 @@ var CLI = class {
1447
1496
  if (refusal !== void 0) throw refusal;
1448
1497
  const result = mergeResults(host.materializer.repair(plan, audit, target), host.materializer.declare({
1449
1498
  pins: versions.pins,
1450
- scripts: blueprintToWritableScripts(blueprint)
1499
+ scripts: manifestToWritableScripts(this.#manifest(target), blueprint)
1451
1500
  }, target));
1452
1501
  const terminalBlueprint = this.#derive(target);
1453
1502
  const [measured] = this.#survey(host.materializer, terminalBlueprint, target, groups);
@@ -1549,7 +1598,7 @@ var CLI = class {
1549
1598
  }
1550
1599
  const declared = {
1551
1600
  pins: manifestToWritableDependencies(this.#manifest(target), blueprint),
1552
- scripts: blueprintToWritableScripts(blueprint)
1601
+ scripts: manifestToWritableScripts(this.#manifest(target), blueprint)
1553
1602
  };
1554
1603
  const local = mergeResults(host.materializer.repair(plan, audit, target), host.materializer.remove(plan, audit, command.dirty === true ? {
1555
1604
  tracked: worktree.tracked,
@@ -1853,6 +1902,7 @@ var CLI = class {
1853
1902
  const global = resolveContainedPath(target, GLOBAL_SETUP_PATH);
1854
1903
  const showcase = resolveContainedPath(target, SHOWCASE_CONFIG_PATH);
1855
1904
  const journey = resolveContainedPath(target, JOURNEY_CONFIG_PATH);
1905
+ const skills = resolveContainedPath(target, SKILLS_CONFIG_PATH);
1856
1906
  const setup = /* @__PURE__ */ new Set();
1857
1907
  if (tests !== void 0) for (const path of listFiles(tests)) {
1858
1908
  if (path.includes("/") || !path.startsWith("setup") || !path.endsWith(".test.ts")) continue;
@@ -1871,12 +1921,14 @@ var CLI = class {
1871
1921
  service: service !== void 0 && isExactCaseFile(service),
1872
1922
  global: global !== void 0 && isExactCaseFile(global),
1873
1923
  showcase: showcase !== void 0 && isExactCaseFile(showcase),
1874
- journey: journey !== void 0 && isExactCaseFile(journey)
1924
+ journey: journey !== void 0 && isExactCaseFile(journey),
1925
+ skills: skills !== void 0 && isExactCaseFile(skills)
1875
1926
  });
1876
1927
  }
1877
1928
  #projectQuestion(target, blueprint, writing = false) {
1878
1929
  const text = this.#manifest(target);
1879
- const manifest = replaceManifestScripts(text, blueprintToWritableScripts(blueprint)) ?? text;
1930
+ const writable = writing ? manifestToWritableScripts(text, blueprint) : blueprintToWritableScripts(blueprint);
1931
+ const manifest = replaceManifestScripts(text, writable) ?? text;
1880
1932
  const planned = blueprintToRootVite(blueprint);
1881
1933
  const parsed = parseJSON(manifest);
1882
1934
  const scripts = isRecord(parsed) && isRecord(parsed.scripts) ? parsed.scripts : {};
@@ -1982,7 +2034,7 @@ var CLI = class {
1982
2034
  const direct = names.map((project) => `test:${project}`);
1983
2035
  const declared = direct.filter((script) => isString(written[script]));
1984
2036
  const undeclared = direct.filter((script) => !isString(written[script]));
1985
- const remedies = [declared.length === 0 ? "" : `${declared.join(", ")} ${declared.length === 1 ? "is" : "are"} already declared, so the gate is missing rather than the script: invoke ${declared.length === 1 ? "it" : "each of them"} by name from the ${gateNames} chain.`, undeclared.length === 0 ? "" : `${undeclared.join(", ")} ${undeclared.length === 1 ? "is" : "are"} not declared, so the script is missing as well as the gate: declare ${undeclared.length === 1 ? "it" : "each of them"} and invoke ${undeclared.length === 1 ? "it" : "each of them"} by name from the ${gateNames} chain.`];
2037
+ const remedies = !writing && manifestToWritableScripts(text, blueprint).some(({ name }) => name === "test") ? ["The test chain runs generated steps only, so repair and overwrite write the planned chain and every missing direct script."] : [declared.length === 0 ? "" : `${declared.join(", ")} ${declared.length === 1 ? "is" : "are"} already declared, so the gate is missing rather than the script: invoke ${declared.length === 1 ? "it" : "each of them"} by name from the ${gateNames} chain.`, undeclared.length === 0 ? "" : `${undeclared.join(", ")} ${undeclared.length === 1 ? "is" : "are"} not declared, so the script is missing as well as the gate: declare ${undeclared.length === 1 ? "it" : "each of them"} and invoke ${undeclared.length === 1 ? "it" : "each of them"} by name from the ${gateNames} chain.`];
1986
2038
  return {
1987
2039
  field: "projects",
1988
2040
  message: `${writing ? "The configs group is blocked because " : ""}the manifest at ${target} does not reach ${names.length === 1 ? "a Vitest project" : "Vitest projects"} the planned configuration registers: ${names.join(", ")}. No chain from ${gateNames} invokes ${names.length === 1 ? "it" : "them"}. ${remedies.filter((remedy) => remedy !== "").join(" ")}${writing ? " Exclude configs from --groups to write another group." : ""}`,