smol-symphony 0.1.0 → 0.2.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 (140) hide show
  1. package/AGENTS.md +105 -38
  2. package/PRODUCT.md +2 -1
  3. package/README.md +195 -98
  4. package/SPEC.md +543 -1915
  5. package/WORKFLOW.md +654 -179
  6. package/WORKFLOW.template.md +761 -121
  7. package/dist/acp-bridge.js +324 -0
  8. package/dist/acp-bridge.js.map +1 -0
  9. package/dist/actions/cache.js +191 -0
  10. package/dist/actions/cache.js.map +1 -0
  11. package/dist/actions/effects.js +41 -0
  12. package/dist/actions/effects.js.map +1 -0
  13. package/dist/actions/executor.js +570 -0
  14. package/dist/actions/executor.js.map +1 -0
  15. package/dist/actions/index.js +13 -0
  16. package/dist/actions/index.js.map +1 -0
  17. package/dist/actions/parsing.js +273 -0
  18. package/dist/actions/parsing.js.map +1 -0
  19. package/dist/actions/predicate-env.js +27 -0
  20. package/dist/actions/predicate-env.js.map +1 -0
  21. package/dist/actions/predicates.js +49 -0
  22. package/dist/actions/predicates.js.map +1 -0
  23. package/dist/actions/templating.js +66 -0
  24. package/dist/actions/templating.js.map +1 -0
  25. package/dist/actions/types.js +15 -0
  26. package/dist/actions/types.js.map +1 -0
  27. package/dist/agent/acp.js +232 -63
  28. package/dist/agent/acp.js.map +1 -1
  29. package/dist/agent/adapter-names.js +159 -0
  30. package/dist/agent/adapter-names.js.map +1 -0
  31. package/dist/agent/adapters.js +338 -102
  32. package/dist/agent/adapters.js.map +1 -1
  33. package/dist/agent/credential-extractors.js +342 -0
  34. package/dist/agent/credential-extractors.js.map +1 -0
  35. package/dist/agent/credential-secrets.js +628 -0
  36. package/dist/agent/credential-secrets.js.map +1 -0
  37. package/dist/agent/credential-ticker.js +57 -0
  38. package/dist/agent/credential-ticker.js.map +1 -0
  39. package/dist/agent/gondolin-creds-staging.js +356 -0
  40. package/dist/agent/gondolin-creds-staging.js.map +1 -0
  41. package/dist/agent/gondolin-dispatch.js +375 -0
  42. package/dist/agent/gondolin-dispatch.js.map +1 -0
  43. package/dist/agent/gondolin.js +124 -0
  44. package/dist/agent/gondolin.js.map +1 -0
  45. package/dist/agent/runner-decisions.js +134 -0
  46. package/dist/agent/runner-decisions.js.map +1 -0
  47. package/dist/agent/runner.js +1352 -290
  48. package/dist/agent/runner.js.map +1 -1
  49. package/dist/agent/tool-call-summary.js +102 -0
  50. package/dist/agent/tool-call-summary.js.map +1 -0
  51. package/dist/agent/vm-acp-mapping.js +73 -0
  52. package/dist/agent/vm-acp-mapping.js.map +1 -0
  53. package/dist/agent/vm-guards.js +262 -0
  54. package/dist/agent/vm-guards.js.map +1 -0
  55. package/dist/agent/vm-port.js +22 -0
  56. package/dist/agent/vm-port.js.map +1 -0
  57. package/dist/agent/vm-process-registry.js +79 -0
  58. package/dist/agent/vm-process-registry.js.map +1 -0
  59. package/dist/bin/cli-args.js +105 -0
  60. package/dist/bin/cli-args.js.map +1 -0
  61. package/dist/bin/symphony.js +719 -130
  62. package/dist/bin/symphony.js.map +1 -1
  63. package/dist/errors.js +15 -0
  64. package/dist/errors.js.map +1 -0
  65. package/dist/http-disk.js +135 -0
  66. package/dist/http-disk.js.map +1 -0
  67. package/dist/http-handlers.js +180 -0
  68. package/dist/http-handlers.js.map +1 -0
  69. package/dist/http.js +1476 -764
  70. package/dist/http.js.map +1 -1
  71. package/dist/issues.js +178 -0
  72. package/dist/issues.js.map +1 -0
  73. package/dist/logging.js +163 -5
  74. package/dist/logging.js.map +1 -1
  75. package/dist/mcp.js +391 -163
  76. package/dist/mcp.js.map +1 -1
  77. package/dist/memory.js +85 -0
  78. package/dist/memory.js.map +1 -0
  79. package/dist/orchestrator-decisions.js +331 -0
  80. package/dist/orchestrator-decisions.js.map +1 -0
  81. package/dist/orchestrator.js +1189 -303
  82. package/dist/orchestrator.js.map +1 -1
  83. package/dist/prompt.js +5 -5
  84. package/dist/prompt.js.map +1 -1
  85. package/dist/reconciler/cache.js +65 -0
  86. package/dist/reconciler/cache.js.map +1 -0
  87. package/dist/reconciler/index.js +448 -0
  88. package/dist/reconciler/index.js.map +1 -0
  89. package/dist/reconciler/ledger.js +131 -0
  90. package/dist/reconciler/ledger.js.map +1 -0
  91. package/dist/reconciler/pr-adapters.js +174 -0
  92. package/dist/reconciler/pr-adapters.js.map +1 -0
  93. package/dist/reconciler/pr-decide.js +167 -0
  94. package/dist/reconciler/pr-decide.js.map +1 -0
  95. package/dist/reconciler/pr.js +422 -0
  96. package/dist/reconciler/pr.js.map +1 -0
  97. package/dist/reconciler/types.js +12 -0
  98. package/dist/reconciler/types.js.map +1 -0
  99. package/dist/reconciler/vm.js +243 -0
  100. package/dist/reconciler/vm.js.map +1 -0
  101. package/dist/reconciler/workspace-defaults.js +83 -0
  102. package/dist/reconciler/workspace-defaults.js.map +1 -0
  103. package/dist/reconciler/workspace.js +272 -0
  104. package/dist/reconciler/workspace.js.map +1 -0
  105. package/dist/runlog.js +403 -0
  106. package/dist/runlog.js.map +1 -0
  107. package/dist/scaffold.js +165 -0
  108. package/dist/scaffold.js.map +1 -0
  109. package/dist/trackers/local.js +234 -133
  110. package/dist/trackers/local.js.map +1 -1
  111. package/dist/trackers/types.js +1 -1
  112. package/dist/trackers/types.js.map +1 -1
  113. package/dist/types.js +1 -1
  114. package/dist/util/clock.js +12 -0
  115. package/dist/util/clock.js.map +1 -0
  116. package/dist/util/crypto.js +25 -0
  117. package/dist/util/crypto.js.map +1 -0
  118. package/dist/util/frontmatter.js +70 -0
  119. package/dist/util/frontmatter.js.map +1 -0
  120. package/dist/util/fs-issues.js +22 -0
  121. package/dist/util/fs-issues.js.map +1 -0
  122. package/dist/util/process.js +152 -0
  123. package/dist/util/process.js.map +1 -0
  124. package/dist/util/workspace-key.js +10 -0
  125. package/dist/util/workspace-key.js.map +1 -0
  126. package/dist/workflow-loader.js +147 -0
  127. package/dist/workflow-loader.js.map +1 -0
  128. package/dist/workflow.js +656 -219
  129. package/dist/workflow.js.map +1 -1
  130. package/dist/workspace-types.js +8 -0
  131. package/dist/workspace-types.js.map +1 -0
  132. package/dist/workspace.js +367 -120
  133. package/dist/workspace.js.map +1 -1
  134. package/package.json +14 -6
  135. package/scripts/vm-agent.mjs +211 -0
  136. package/dist/agent/codex.js +0 -439
  137. package/dist/agent/codex.js.map +0 -1
  138. package/dist/agent/smolvm.js +0 -174
  139. package/dist/agent/smolvm.js.map +0 -1
  140. package/scripts/build-vm.sh +0 -67
@@ -17,11 +17,12 @@
17
17
  // <description body>
18
18
  //
19
19
  // The state of an issue is taken verbatim from the parent directory name.
20
- // State comparison is case-insensitive (SPEC §4.2 "Normalized Issue State").
21
- import { mkdir, readdir, readFile, rename, stat } from 'node:fs/promises';
20
+ // State comparison is case-insensitive (SPEC §3.2 "Normalized Issue State").
21
+ import { mkdir, open, readdir, readFile, rename, stat } from 'node:fs/promises';
22
22
  import path from 'node:path';
23
- import { parse as parseYaml } from 'yaml';
23
+ import { parseFrontMatter, FrontMatterError } from '../util/frontmatter.js';
24
24
  import { TrackerError } from './types.js';
25
+ import { activeStateNames, terminalStateNames } from '../issues.js';
25
26
  import { log } from '../logging.js';
26
27
  function asString(v) {
27
28
  return typeof v === 'string' ? v : null;
@@ -45,39 +46,31 @@ function asTimestamp(v) {
45
46
  return v.toISOString();
46
47
  return null;
47
48
  }
49
+ // Compose the appended-notes body. Pure: extracted so `appendNotesBlock` stays small
50
+ // enough for the imperative-shell complexity budget. Guarantees a blank line between the
51
+ // prior body and the new header; the block itself ends with a newline so subsequent
52
+ // appends stay readable.
53
+ function buildNotesAppendedBody(original, fromState, toState, notes, actor) {
54
+ const who = actor && actor.length > 0 ? actor : 'unknown';
55
+ const ts = new Date().toISOString();
56
+ const header = `## ${who} — ${ts} — ${fromState} → ${toState}`;
57
+ const sep = original.endsWith('\n\n') ? '' : original.endsWith('\n') ? '\n' : '\n\n';
58
+ return `${original}${sep}${header}\n\n${notes}\n`;
59
+ }
60
+ // Thin wrapper over the shared parser. Translates FrontMatterError → TrackerError
61
+ // so the scanner's existing skip-and-log catch picks them up under the same code.
48
62
  function splitFrontMatter(text) {
49
- if (!text.startsWith('---'))
50
- return { config: {}, body: text.trim() };
51
- const lines = text.split(/\r?\n/);
52
- const isFence = (l) => /^---\s*$/.test(l ?? '');
53
- if (!isFence(lines[0]))
54
- return { config: {}, body: text.trim() };
55
- let endIdx = -1;
56
- for (let i = 1; i < lines.length; i++) {
57
- if (isFence(lines[i])) {
58
- endIdx = i;
59
- break;
60
- }
63
+ let fm;
64
+ try {
65
+ fm = parseFrontMatter(text);
61
66
  }
62
- if (endIdx < 0)
63
- return { config: {}, body: text.trim() };
64
- const fmText = lines.slice(1, endIdx).join('\n').trim();
65
- const body = lines.slice(endIdx + 1).join('\n').trim();
66
- let parsed = {};
67
- if (fmText.length > 0) {
68
- try {
69
- parsed = parseYaml(fmText);
67
+ catch (err) {
68
+ if (err instanceof FrontMatterError) {
69
+ throw new TrackerError('local_issue_parse_error', err.code === 'not_a_map' ? 'issue front matter must be a map' : `failed to parse front matter: ${err.message}`);
70
70
  }
71
- catch (err) {
72
- throw new TrackerError('local_issue_parse_error', `failed to parse front matter: ${err.message}`);
73
- }
74
- }
75
- if (parsed === null || parsed === undefined)
76
- parsed = {};
77
- if (typeof parsed !== 'object' || Array.isArray(parsed)) {
78
- throw new TrackerError('local_issue_parse_error', 'issue front matter must be a map');
71
+ throw err;
79
72
  }
80
- return { config: parsed, body };
73
+ return { config: fm.fields, body: fm.body };
81
74
  }
82
75
  export class LocalMarkdownTracker {
83
76
  cfg;
@@ -91,17 +84,34 @@ export class LocalMarkdownTracker {
91
84
  throw new TrackerError('local_no_root', 'tracker.root is required');
92
85
  this.cfg = cfg;
93
86
  }
87
+ /**
88
+ * Eagerly create the directory for every declared state under `tracker.root`.
89
+ * Called from the orchestrator boot path so the operator-facing tree (and the
90
+ * dashboard) sees every column the workflow declared, even before any issue
91
+ * file lands in it. Lazy creation in writeIssueFile / moveIssueToState is left
92
+ * in place as a belt-and-suspenders fallback for code paths that target a
93
+ * state directory directly.
94
+ */
95
+ async start() {
96
+ if (!this.cfg.root)
97
+ throw new TrackerError('local_no_root', 'tracker.root is required');
98
+ // `states` is canonical (the workflow parser refuses configs without it);
99
+ // mkdir each declared state directory so the dashboard sees every column
100
+ // even before issues land.
101
+ for (const name of Object.keys(this.cfg.states)) {
102
+ await mkdir(path.join(this.cfg.root, name), { recursive: true });
103
+ }
104
+ }
94
105
  get root() {
95
106
  return this.cfg.root;
96
107
  }
97
108
  async fetchCandidateIssues() {
98
- // Capture root + terminal_states atomically at method entry. A workflow
99
- // reload during the fetch I/O cannot make the returned issues and the
100
- // returned snapshot disagree — both come from this single view of cfg.
109
+ // Capture root atomically at method entry. A workflow reload during the
110
+ // fetch I/O cannot make the returned issues and the returned snapshot
111
+ // disagree — both come from this single view of cfg.
101
112
  const root = this.cfg.root;
102
- const terminalStates = [...this.cfg.terminal_states];
103
- const active = new Set(this.cfg.active_states.map((s) => s.toLowerCase()));
104
- const terminal = new Set(terminalStates.map((s) => s.toLowerCase()));
113
+ const active = new Set(activeStateNames(this.cfg.states).map((s) => s.toLowerCase()));
114
+ const terminal = new Set(terminalStateNames(this.cfg.states).map((s) => s.toLowerCase()));
105
115
  const all = await this.scanAllAt(root);
106
116
  const filtered = all.filter((raw) => {
107
117
  const s = raw.state.toLowerCase();
@@ -110,11 +120,10 @@ export class LocalMarkdownTracker {
110
120
  return {
111
121
  issues: this.normalize(filtered, all),
112
122
  root,
113
- terminalStates,
114
123
  };
115
124
  }
116
125
  async fetchIssuesByStates(stateNames) {
117
- // §17.3: empty input returns empty without an API call.
126
+ // Empty input returns empty without an API call.
118
127
  if (stateNames.length === 0)
119
128
  return [];
120
129
  const want = new Set(stateNames.map((s) => s.toLowerCase()));
@@ -136,79 +145,146 @@ export class LocalMarkdownTracker {
136
145
  }
137
146
  /**
138
147
  * Move an issue's .md file from its current state directory to `toState`. Used by the
139
- * MCP mark_done tool. Atomic on the same filesystem (fs.rename); throws TrackerError
148
+ * MCP transition tool. Atomic on the same filesystem (fs.rename); throws TrackerError
140
149
  * with a stable code on common failure modes so the MCP layer can surface them.
150
+ *
151
+ * When `opts.notes` is a non-empty string, a notes block is appended to the issue body
152
+ * BEFORE the cross-directory rename: the new body is written to `<id>.md.tmp` in the
153
+ * source state directory, fsync'd, then atomically renamed onto `<id>.md` so the file
154
+ * is still in the source state directory but now carries the notes. The
155
+ * cross-directory rename then moves the updated file into the target state. This
156
+ * sequencing means a crash between the two renames leaves the notes persisted in the
157
+ * source directory — the next dispatch sees them on the live issue and the operator
158
+ * can finish the move by hand.
141
159
  */
142
160
  async moveIssueToState(issueId, toState, opts) {
143
161
  // When the caller pins a root (snapshot from dispatch time), scan there.
144
162
  // Otherwise use whatever the live config says. This protects in-flight
145
- // mark_done from a WORKFLOW.md reload that mutates tracker.root.
146
- const root = opts?.fromRoot ?? this.root;
163
+ // transition calls from a WORKFLOW.md reload that mutates tracker.root.
164
+ const { fromRoot, fromState, notes: rawNotes, actor } = opts ?? {};
165
+ const root = fromRoot ?? this.root;
166
+ const notes = typeof rawNotes === 'string' ? rawNotes : '';
147
167
  const all = await this.scanAllAt(root);
148
168
  const candidates = all.filter((raw) => this.idOf(raw) === issueId);
149
169
  if (candidates.length === 0) {
150
170
  throw new TrackerError('local_issue_not_found', `no issue file matches id ${issueId}`);
151
171
  }
152
- // Multiple files can share the same id when a stale terminal copy (e.g. an old
153
- // Done/ABC-1.md from a prior cycle) survives alongside a live In Progress/ABC-1.md.
154
- // `readdir` ordering is filesystem-dependent, so a blind `.find(...)` can pick the
155
- // stale copy and — if its state already equals `toState` — silently no-op via the
156
- // identity short-circuit below, leaving the active file stranded. Prefer the copy
157
- // whose state matches the caller-supplied `fromState`; if that still doesn't
158
- // resolve to a single file, refuse to guess.
159
- let match;
160
- if (candidates.length === 1) {
161
- match = candidates[0];
162
- }
163
- else {
164
- const fromState = opts?.fromState;
165
- const preferred = fromState
166
- ? candidates.filter((raw) => raw.state.toLowerCase() === fromState.toLowerCase())
167
- : [];
168
- if (preferred.length === 1) {
169
- match = preferred[0];
170
- }
171
- else {
172
- const states = candidates.map((raw) => raw.state).join(', ');
173
- throw new TrackerError('local_issue_ambiguous', `multiple issue files match id ${issueId} across states [${states}]; pass fromState to disambiguate`);
174
- }
175
- }
172
+ const match = this.resolveMatch(candidates, issueId, fromState);
176
173
  if (match.state.toLowerCase() === toState.toLowerCase()) {
177
174
  return { fromState: match.state, toState: match.state, newPath: match.filePath };
178
175
  }
176
+ if (notes.length > 0) {
177
+ await this.appendNotesBlock(match, toState, notes, actor);
178
+ }
179
179
  const targetDir = path.join(root, toState);
180
180
  await mkdir(targetDir, { recursive: true });
181
- const basename = path.basename(match.filePath);
182
- const newPath = path.join(targetDir, basename);
183
- // POSIX `rename` overwrites the destination silently. Refuse to clobber a stale
184
- // terminal file with the same basename (e.g. an old Done/ABC-1.md left from a prior
185
- // run before this issue was recreated in In Progress). A small TOCTOU race remains
186
- // — another writer can create the target between this check and rename — but the
187
- // realistic failure mode is operator-leftover files, not concurrent writes.
181
+ const newPath = path.join(targetDir, path.basename(match.filePath));
182
+ await this.assertTargetFree(newPath);
183
+ await this.crossDirRename(match.filePath, newPath);
184
+ log.info('issue transitioned', {
185
+ issue_id: issueId,
186
+ from_state: match.state,
187
+ to_state: toState,
188
+ path: newPath,
189
+ });
190
+ return { fromState: match.state, toState, newPath };
191
+ }
192
+ async crossDirRename(srcPath, dstPath) {
188
193
  try {
189
- await stat(newPath);
190
- throw new TrackerError('local_issue_target_exists', `refusing to overwrite existing file at ${newPath}`);
194
+ await rename(srcPath, dstPath);
191
195
  }
192
196
  catch (err) {
193
- if (err instanceof TrackerError)
194
- throw err;
195
- if (err.code !== 'ENOENT') {
196
- throw new TrackerError('local_issue_move_error', `failed to stat target ${newPath}: ${err.message}`);
197
+ throw new TrackerError('local_issue_move_error', `failed to move ${srcPath} -> ${dstPath}: ${err.message}`);
198
+ }
199
+ }
200
+ // Multiple files can share the same id when a stale terminal copy (e.g. an old
201
+ // Done/ABC-1.md from a prior cycle) survives alongside a live In Progress/ABC-1.md.
202
+ // `readdir` ordering is filesystem-dependent, so a blind `.find(...)` can pick the
203
+ // stale copy and — if its state already equals `toState` — silently no-op via the
204
+ // identity short-circuit in the caller, leaving the active file stranded. Prefer the
205
+ // copy whose state matches the caller-supplied `fromState`; if that still doesn't
206
+ // resolve to a single file, refuse to guess.
207
+ resolveMatch(candidates, issueId, fromState) {
208
+ if (candidates.length === 1)
209
+ return candidates[0];
210
+ const preferred = fromState
211
+ ? candidates.filter((raw) => raw.state.toLowerCase() === fromState.toLowerCase())
212
+ : [];
213
+ if (preferred.length === 1)
214
+ return preferred[0];
215
+ const states = candidates.map((raw) => raw.state).join(', ');
216
+ throw new TrackerError('local_issue_ambiguous', `multiple issue files match id ${issueId} across states [${states}]; pass fromState to disambiguate`);
217
+ }
218
+ // We re-read the file (the scan parsed front-matter + body but discarded the verbatim
219
+ // text) so the rewrite preserves operator-visible whitespace, comments, and any
220
+ // trailing newlines exactly. The append block format is fixed across the tracker so the
221
+ // dashboard / downstream tooling can recognise it.
222
+ async appendNotesBlock(match, toState, notes, actor) {
223
+ const original = await this.readForNotesAppend(match.filePath);
224
+ const appended = buildNotesAppendedBody(original, match.state, toState, notes, actor);
225
+ await this.durablyReplaceInPlace(match.filePath, appended);
226
+ }
227
+ async readForNotesAppend(filePath) {
228
+ try {
229
+ return await readFile(filePath, 'utf8');
230
+ }
231
+ catch (err) {
232
+ throw new TrackerError('local_issue_notes_read_error', `failed to read ${filePath} for notes append: ${err.message}`);
233
+ }
234
+ }
235
+ // Write to <targetPath>.tmp in the SAME directory, fsync the file descriptor for
236
+ // durability, then atomic-rename onto targetPath. Same-directory rename is atomic on
237
+ // POSIX filesystems, so any subsequent cross-directory move operates on a single
238
+ // up-to-date file.
239
+ async durablyReplaceInPlace(targetPath, contents) {
240
+ const tmpPath = targetPath + '.tmp';
241
+ await this.writeAndFsync(tmpPath, contents);
242
+ try {
243
+ await rename(tmpPath, targetPath);
244
+ }
245
+ catch (err) {
246
+ throw new TrackerError('local_issue_notes_rename_error', `failed to atomic-rename ${tmpPath} -> ${targetPath}: ${err.message}`);
247
+ }
248
+ }
249
+ async writeAndFsync(tmpPath, contents) {
250
+ let fh;
251
+ try {
252
+ fh = await open(tmpPath, 'w', 0o644);
253
+ await fh.writeFile(contents, 'utf8');
254
+ await fh.sync();
255
+ }
256
+ catch (err) {
257
+ try {
258
+ if (fh)
259
+ await fh.close();
197
260
  }
261
+ catch {
262
+ // best-effort close — surfacing the original error is more useful.
263
+ }
264
+ throw new TrackerError('local_issue_notes_write_error', `failed to write notes tmp file ${tmpPath}: ${err.message}`);
198
265
  }
199
266
  try {
200
- await rename(match.filePath, newPath);
267
+ await fh.close();
268
+ }
269
+ catch {
270
+ // The file is on disk and fsync'd; close failures are not load-bearing.
271
+ }
272
+ }
273
+ // POSIX `rename` overwrites the destination silently. Refuse to clobber a stale
274
+ // terminal file with the same basename (e.g. an old Done/ABC-1.md left from a prior
275
+ // run before this issue was recreated in In Progress). A small TOCTOU race remains
276
+ // — another writer can create the target between this check and the subsequent rename
277
+ // — but the realistic failure mode is operator-leftover files, not concurrent writes.
278
+ async assertTargetFree(newPath) {
279
+ try {
280
+ await stat(newPath);
201
281
  }
202
282
  catch (err) {
203
- throw new TrackerError('local_issue_move_error', `failed to move ${match.filePath} -> ${newPath}: ${err.message}`);
283
+ if (err.code === 'ENOENT')
284
+ return;
285
+ throw new TrackerError('local_issue_move_error', `failed to stat target ${newPath}: ${err.message}`);
204
286
  }
205
- log.info('issue transitioned', {
206
- issue_id: issueId,
207
- from_state: match.state,
208
- to_state: toState,
209
- path: newPath,
210
- });
211
- return { fromState: match.state, toState, newPath };
287
+ throw new TrackerError('local_issue_target_exists', `refusing to overwrite existing file at ${newPath}`);
212
288
  }
213
289
  idOf(raw) {
214
290
  const fmId = asString(raw.frontMatter['id']);
@@ -217,7 +293,7 @@ export class LocalMarkdownTracker {
217
293
  async scanAll() {
218
294
  return this.scanAllAt(this.root);
219
295
  }
220
- /** Variant that scans an explicit root, used by mark_done with a pinned snapshot. */
296
+ /** Variant that scans an explicit root, used by `transition` with a pinned snapshot. */
221
297
  async scanAllAt(root) {
222
298
  let entries;
223
299
  try {
@@ -226,6 +302,15 @@ export class LocalMarkdownTracker {
226
302
  catch (err) {
227
303
  throw new TrackerError('local_root_read_error', `cannot read tracker.root ${root}: ${err.message}`);
228
304
  }
305
+ // Match directories against the declared state map case-insensitively, the
306
+ // same comparison the orchestrator uses for role-based classification.
307
+ // Unknown directories (operator-left scratch, a state that was removed from
308
+ // `states:`) are ignored with a warning so a stale tree doesn't crash the
309
+ // dispatch loop.
310
+ const declared = new Map();
311
+ for (const name of Object.keys(this.cfg.states)) {
312
+ declared.set(name.toLowerCase(), name);
313
+ }
229
314
  const out = [];
230
315
  for (const dirEntry of entries) {
231
316
  const dirPath = path.join(root, dirEntry);
@@ -238,54 +323,70 @@ export class LocalMarkdownTracker {
238
323
  }
239
324
  if (!stats.isDirectory())
240
325
  continue;
241
- const state = dirEntry;
242
- let files;
243
- try {
244
- files = await readdir(dirPath);
245
- }
246
- catch {
326
+ if (!declared.has(dirEntry.toLowerCase())) {
327
+ log.warn('skipping undeclared state directory', { dir: dirPath });
247
328
  continue;
248
329
  }
249
- for (const fileName of files) {
250
- if (!fileName.endsWith('.md'))
251
- continue;
252
- const filePath = path.join(dirPath, fileName);
253
- let st;
254
- try {
255
- st = await stat(filePath);
256
- }
257
- catch {
258
- continue;
259
- }
260
- if (!st.isFile())
261
- continue;
262
- let text;
263
- try {
264
- text = await readFile(filePath, 'utf8');
265
- }
266
- catch (err) {
267
- log.warn('skipping unreadable issue file', { file: filePath, error: err.message });
268
- continue;
269
- }
270
- let parsed;
271
- try {
272
- parsed = splitFrontMatter(text);
273
- }
274
- catch (err) {
275
- log.warn('skipping malformed issue file', { file: filePath, error: err.message });
276
- continue;
277
- }
278
- out.push({
279
- filePath,
280
- identifier: fileName.slice(0, -3),
281
- state,
282
- frontMatter: parsed.config,
283
- description: parsed.body,
284
- });
285
- }
330
+ out.push(...(await this.scanStateDir(dirPath, dirEntry)));
331
+ }
332
+ return out;
333
+ }
334
+ // Read every .md file in a single state directory. Per-file failures (unreadable,
335
+ // malformed front matter) are skipped with a warning so one bad file doesn't poison
336
+ // the whole scan; a readdir failure on the directory itself silently yields nothing
337
+ // for the same reason.
338
+ async scanStateDir(dirPath, state) {
339
+ let files;
340
+ try {
341
+ files = await readdir(dirPath);
342
+ }
343
+ catch {
344
+ return [];
345
+ }
346
+ const out = [];
347
+ for (const fileName of files) {
348
+ if (!fileName.endsWith('.md'))
349
+ continue;
350
+ const raw = await this.readIssueFile(path.join(dirPath, fileName), fileName, state);
351
+ if (raw)
352
+ out.push(raw);
286
353
  }
287
354
  return out;
288
355
  }
356
+ async readIssueFile(filePath, fileName, state) {
357
+ let st;
358
+ try {
359
+ st = await stat(filePath);
360
+ }
361
+ catch {
362
+ return null;
363
+ }
364
+ if (!st.isFile())
365
+ return null;
366
+ let text;
367
+ try {
368
+ text = await readFile(filePath, 'utf8');
369
+ }
370
+ catch (err) {
371
+ log.warn('skipping unreadable issue file', { file: filePath, error: err.message });
372
+ return null;
373
+ }
374
+ let parsed;
375
+ try {
376
+ parsed = splitFrontMatter(text);
377
+ }
378
+ catch (err) {
379
+ log.warn('skipping malformed issue file', { file: filePath, error: err.message });
380
+ return null;
381
+ }
382
+ return {
383
+ filePath,
384
+ identifier: fileName.slice(0, -3),
385
+ state,
386
+ frontMatter: parsed.config,
387
+ description: parsed.body,
388
+ };
389
+ }
289
390
  // Build normalized Issue objects. `all` is used to resolve blocker states.
290
391
  normalize(target, all) {
291
392
  // Resolve blockers by normalized identifier (front-matter `identifier` if set, else basename)
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/trackers/local.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/trackers/local.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- // Tracker adapter contract (SPEC §11.1).
1
+ // Tracker adapter contract (SPEC §7.1).
2
2
  export class TrackerError extends Error {
3
3
  code;
4
4
  constructor(code, message) {
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/trackers/types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAwDzC,MAAM,OAAO,YAAa,SAAQ,KAAK;IAClB;IAAnB,YAAmB,IAAY,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAQ;QAE7B,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/trackers/types.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAyExC,MAAM,OAAO,YAAa,SAAQ,KAAK;IAClB;IAAnB,YAAmB,IAAY,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAQ;QAE7B,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
package/dist/types.js CHANGED
@@ -1,3 +1,3 @@
1
- // Domain model per SPEC.md §4.
1
+ // Domain model per SPEC.md §3.
2
2
  export {};
3
3
  //# sourceMappingURL=types.js.map
@@ -0,0 +1,12 @@
1
+ // Wall-clock helpers. Lives outside the functional-core lint group (see
2
+ // eslint.config.js) so core modules can import these instead of touching
3
+ // `Date.now()` / `new Date()` directly. Production defaults flow through
4
+ // `realClock` / `isoFromClock`; tests pin time by passing a stub `now()` to
5
+ // whatever core resource exposes the injection seam.
6
+ /** Production default: real wall clock. Adapter-layer, by design. */
7
+ export const realClock = () => Date.now();
8
+ /** Format an injected clock's reading as an ISO 8601 string. */
9
+ export function isoFromClock(now) {
10
+ return new Date(now()).toISOString();
11
+ }
12
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/util/clock.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,qDAAqD;AAKrD,qEAAqE;AACrE,MAAM,CAAC,MAAM,SAAS,GAAa,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;AAEpD,gEAAgE;AAChE,MAAM,UAAU,YAAY,CAAC,GAAa;IACxC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,25 @@
1
+ // Crypto port + production adapter (issue 96). `McpRegistry` reaches
2
+ // `randomBytes` / `timingSafeEqual` through this seam so its core stays free
3
+ // of `node:crypto` and `node:buffer` direct imports; tests pin a
4
+ // deterministic `CryptoEnv` to assert against fixed token values.
5
+ import { randomBytes, timingSafeEqual } from 'node:crypto';
6
+ import { Buffer } from 'node:buffer';
7
+ /**
8
+ * Production adapter. We compare BYTE lengths after UTF-8 encoding, not JS
9
+ * string `.length` (which counts UTF-16 code units). An attacker-supplied
10
+ * non-ASCII token can match the real token's code-unit count while encoding
11
+ * to a different byte length; passing those buffers to `timingSafeEqual`
12
+ * would throw `Input buffers must have the same byte length`, surfacing as
13
+ * an HTTP 500 instead of a clean wrong-token rejection.
14
+ */
15
+ export const realCrypto = {
16
+ newToken: () => randomBytes(24).toString('base64url'),
17
+ constantTimeEqual: (a, b) => {
18
+ const aBuf = Buffer.from(a, 'utf8');
19
+ const bBuf = Buffer.from(b, 'utf8');
20
+ if (aBuf.length !== bBuf.length)
21
+ return false;
22
+ return timingSafeEqual(aBuf, bBuf);
23
+ },
24
+ };
25
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/util/crypto.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,6EAA6E;AAC7E,iEAAiE;AACjE,kEAAkE;AAElE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAmBrC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAc;IACnC,QAAQ,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;IACrD,iBAAiB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC9C,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;CACF,CAAC"}