simt-dev 0.7.1 → 0.8.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 (186) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/README.md +169 -80
  3. package/docs/decisions/ADR-014-workspace-is-configuration.md +1 -1
  4. package/docs/decisions/ADR-025-a-baseline-is-a-region-in-a-file-the-repo-owns.md +1 -1
  5. package/docs/decisions/ADR-026-a-config-without-a-region-is-a-file-the-repo-owns.md +1 -1
  6. package/docs/decisions/ADR-027-the-one-gitattributes-line-that-is-neither-dangerous-nor-empty.md +1 -1
  7. package/docs/decisions/ADR-028-a-base-file-is-a-floor-so-the-disagreement-it-cannot-repair-becomes-a-check.md +1 -1
  8. package/docs/decisions/ADR-029-the-pins-a-repository-declares-are-its-own.md +1 -1
  9. package/docs/decisions/ADR-030-what-a-plan-does-not-ship-is-a-decision-with-a-record.md +1 -1
  10. package/docs/decisions/ADR-048-a-baseline-carries-only-keys-a-reader-honours.md +1 -1
  11. package/docs/decisions/ADR-082-the-tracker-override-is-a-manifest-key.md +1 -1
  12. package/docs/decisions/ADR-126-the-mcp-surface-stays-a-reader-so-there-is-no-write-path-to-build.md +68 -0
  13. package/docs/decisions/ADR-127-the-mcp-tool-list-is-written-by-hand-and-roots-is-not-asked-for.md +65 -0
  14. package/docs/decisions/ADR-128-a-research-plan-is-a-plan-and-the-tracker-reads-it.md +42 -0
  15. package/ecosystems/bun.json +6 -0
  16. package/ecosystems/cargo.json +25 -0
  17. package/ecosystems/composer.json +6 -0
  18. package/ecosystems/dart.json +24 -0
  19. package/ecosystems/deno.json +21 -0
  20. package/ecosystems/devcontainers.json +6 -0
  21. package/ecosystems/docker-compose.json +6 -0
  22. package/ecosystems/docker.json +6 -0
  23. package/ecosystems/dotnet.json +25 -0
  24. package/ecosystems/elixir.json +23 -0
  25. package/ecosystems/gitsubmodule.json +6 -0
  26. package/ecosystems/go.json +25 -0
  27. package/ecosystems/gradle.json +13 -0
  28. package/ecosystems/maven.json +23 -0
  29. package/ecosystems/node.json +25 -0
  30. package/ecosystems/python.json +20 -0
  31. package/ecosystems/ruby.json +23 -0
  32. package/ecosystems/swift.json +25 -0
  33. package/ecosystems/terraform.json +6 -0
  34. package/ecosystems/uv.json +6 -0
  35. package/harnesses/antigravity.json +162 -0
  36. package/harnesses/claude.json +206 -0
  37. package/harnesses/codex.json +136 -0
  38. package/harnesses/copilot.json +88 -0
  39. package/harnesses/cursor.json +140 -0
  40. package/harnesses/deepseek.json +99 -0
  41. package/harnesses/gemini.json +122 -0
  42. package/harnesses/opencode.json +173 -0
  43. package/package.json +3 -1
  44. package/rules/mdc/intake-questions.mdc +8 -0
  45. package/src/advice/advice.mjs +3 -2
  46. package/src/agenthooks/render.mjs +86 -180
  47. package/src/agents/render.mjs +15 -18
  48. package/src/api.mjs +7 -5
  49. package/src/argv.mjs +19 -0
  50. package/src/bench/ablate.mjs +3 -4
  51. package/src/bench/adapters.json +155 -113
  52. package/src/bench/adapters.mjs +466 -0
  53. package/src/bench/arms.mjs +333 -0
  54. package/src/bench/grade.mjs +12 -26
  55. package/src/bench/graders.mjs +42 -0
  56. package/src/bench/mine.mjs +17 -535
  57. package/src/bench/probe-ledger.mjs +149 -0
  58. package/src/bench/probes.catalog.mjs +918 -0
  59. package/src/bench/probes.mjs +15 -1037
  60. package/src/bench/render.mjs +111 -0
  61. package/src/bench/report.mjs +116 -971
  62. package/src/bench/run.mjs +164 -881
  63. package/src/bench/variants.mjs +4 -5
  64. package/src/bench/workspace.mjs +160 -0
  65. package/src/brief/assemble.mjs +11 -13
  66. package/src/ci/dependabot.mjs +25 -55
  67. package/src/commands/agent.mjs +1 -9
  68. package/src/commands/agenthook.mjs +66 -35
  69. package/src/commands/bench.mjs +2 -2
  70. package/src/commands/ci.mjs +11 -13
  71. package/src/commands/docs.mjs +88 -0
  72. package/src/commands/gate.mjs +10 -13
  73. package/src/commands/harness.mjs +3 -3
  74. package/src/commands/help.mjs +44 -3
  75. package/src/commands/hooks.mjs +20 -20
  76. package/src/commands/ignore.mjs +11 -7
  77. package/src/commands/impact.mjs +4 -8
  78. package/src/commands/index.mjs +49 -9
  79. package/src/commands/init-scan.mjs +90 -0
  80. package/src/commands/init.mjs +122 -104
  81. package/src/commands/lease.mjs +67 -18
  82. package/src/commands/map.mjs +10 -5
  83. package/src/commands/mcp.mjs +2 -17
  84. package/src/commands/repoindex.mjs +8 -8
  85. package/src/commands/rules.mjs +8 -4
  86. package/src/commands/shared.mjs +12 -16
  87. package/src/commands/skills.mjs +5 -6
  88. package/src/commands/skillscompile.mjs +3 -3
  89. package/src/commands/skillsinstall.mjs +5 -4
  90. package/src/commands/slice.mjs +199 -64
  91. package/src/commands/spec.mjs +78 -62
  92. package/src/commands/status.mjs +24 -12
  93. package/src/commands/sync.mjs +14 -14
  94. package/src/commands/tests.mjs +12 -12
  95. package/src/commands/tokens.mjs +19 -24
  96. package/src/commands/upgrade.mjs +8 -4
  97. package/src/commands/why.mjs +6 -13
  98. package/src/compare/hooksstate.mjs +2 -6
  99. package/src/compare/learn.mjs +3 -1
  100. package/src/decisions/index.mjs +3 -2
  101. package/src/docs/commands.mjs +65 -0
  102. package/src/ecosystem/records.mjs +219 -0
  103. package/src/explain.mjs +31 -0
  104. package/src/gates/index.mjs +385 -0
  105. package/src/graph/compile.mjs +8 -4
  106. package/src/graph/load.mjs +2 -1
  107. package/src/graph/spec.mjs +10 -8
  108. package/src/harness/records.mjs +143 -0
  109. package/src/hooks/capability.mjs +5 -3
  110. package/src/hooks/dispatcher.mjs +26 -32
  111. package/src/hooks/gates.mjs +12 -2
  112. package/src/hooks/resolve.mjs +2 -7
  113. package/src/hooks/where.mjs +2 -7
  114. package/src/identity.mjs +2 -11
  115. package/src/index/coverage.mjs +58 -0
  116. package/src/index/extract.mjs +6 -16
  117. package/src/index/gate.mjs +1 -1
  118. package/src/index/govern.mjs +26 -9
  119. package/src/index/impact.mjs +4 -8
  120. package/src/index/map.mjs +14 -15
  121. package/src/index/open.mjs +173 -0
  122. package/src/index/persist.mjs +224 -57
  123. package/src/index/store.mjs +82 -39
  124. package/src/index/tests.mjs +2 -6
  125. package/src/journal.mjs +16 -11
  126. package/src/kernel/card.mjs +37 -63
  127. package/src/kernel/checks.mjs +4 -10
  128. package/src/lease.mjs +102 -7
  129. package/src/ledger/index.mjs +124 -17
  130. package/src/mcp/paginate.mjs +33 -0
  131. package/src/mcp/schemas.mjs +512 -0
  132. package/src/mcp/server.mjs +49 -9
  133. package/src/mcp/tools-facts.mjs +326 -0
  134. package/src/mcp/tools-read.mjs +221 -0
  135. package/src/mcp/tools.mjs +4 -1005
  136. package/src/{bench → measure}/corpus.mjs +1 -1
  137. package/src/measure/metrics.mjs +236 -0
  138. package/src/measure/records.mjs +211 -0
  139. package/src/measure/stats.mjs +538 -0
  140. package/src/measure/task-schema.mjs +125 -0
  141. package/src/measure/tasks.mjs +69 -0
  142. package/src/memory/decide.mjs +6 -15
  143. package/src/memory/lesson-text.mjs +61 -0
  144. package/src/memory/lessons.mjs +29 -82
  145. package/src/name.mjs +7 -0
  146. package/src/output/index.mjs +122 -31
  147. package/src/packs/manage.mjs +15 -9
  148. package/src/plan/index.mjs +1 -1
  149. package/src/plugins.mjs +22 -16
  150. package/src/prbody.mjs +7 -11
  151. package/src/projection/loaders.mjs +7 -692
  152. package/src/projection/manifest.mjs +10 -435
  153. package/src/projection/mdc.mjs +7 -8
  154. package/src/projection/project.mjs +126 -221
  155. package/src/projection/region.mjs +561 -0
  156. package/src/projection/rules.mjs +16 -547
  157. package/src/projection/surfaces.mjs +43 -210
  158. package/src/projection/targets.mjs +5 -5
  159. package/src/repo-root.mjs +13 -1
  160. package/src/resolve/eval.mjs +2 -1
  161. package/src/resolve/fingerprint.mjs +0 -7
  162. package/src/resolve/resolve.mjs +1 -41
  163. package/src/review/critic.mjs +8 -12
  164. package/src/run.mjs +98 -0
  165. package/src/secrets.mjs +14 -22
  166. package/src/state/events.mjs +129 -0
  167. package/src/status-snapshot.mjs +233 -0
  168. package/src/status.mjs +2 -6
  169. package/src/sys/git.mjs +82 -0
  170. package/src/{bench/process.mjs → sys/proc.mjs} +28 -5
  171. package/src/testing/parsers.mjs +265 -0
  172. package/src/testing/patches.mjs +23 -0
  173. package/src/testing/paths.mjs +49 -0
  174. package/src/testing/runners.mjs +186 -0
  175. package/src/testing/vault.mjs +68 -0
  176. package/src/text/frontmatter.mjs +49 -0
  177. package/src/text/tokens.mjs +52 -0
  178. package/src/toolwords.mjs +1 -1
  179. package/src/util/fs.mjs +20 -0
  180. package/src/util/sort.mjs +12 -0
  181. package/src/workspace.mjs +3 -1
  182. package/src/write/plan.mjs +82 -0
  183. package/templates/plan/tracker.json +1 -0
  184. package/docs/decisions/ADR-033-three-plan-rows-closed-by-decision-not-by-authoring.md +0 -82
  185. package/docs/decisions/ADR-102-the-two-queued-review-rows-are-closed-by-ruling.md +0 -49
  186. package/src/bench/tasks.mjs +0 -36
@@ -0,0 +1,149 @@
1
+ // The probe ledger: the git and node commands a probe runs, and the JSONL it appends.
2
+ //
3
+ // A probe measures whether an agent follows a rule by running a workspace and reading
4
+ // the commands it issued. The catalogue references these helpers, and the runner writes
5
+ // the same ledger, so they live beside neither: one module both import (review 0003 Q80).
6
+ import { existsSync } from 'node:fs';
7
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
8
+ import { dirname, join, resolve } from 'node:path';
9
+
10
+ import { sanitizedEnv, spawnBounded } from '../sys/proc.mjs';
11
+ import { LOCAL_DIR } from '../state.mjs';
12
+
13
+ export const PROBE_AGENT_TIMEOUT_MS = 120_000;
14
+ export const PROBE_COMMAND_TIMEOUT_MS = 120_000;
15
+
16
+
17
+ export async function runGit(args, { cwd, env = {} } = {}) {
18
+ const outcome = await spawnBounded('git', args, {
19
+ cwd,
20
+ env: sanitizedEnv(env),
21
+ timeoutMs: PROBE_COMMAND_TIMEOUT_MS,
22
+ });
23
+ return {
24
+ code: outcome.code,
25
+ stdout: outcome.stdout.toString('utf8'),
26
+ stderr: outcome.stderr.toString('utf8'),
27
+ };
28
+ }
29
+
30
+
31
+ export async function runNode(args, { cwd, env = {} } = {}) {
32
+ const outcome = await spawnBounded(process.execPath, args, {
33
+ cwd,
34
+ env: sanitizedEnv(env),
35
+ timeoutMs: PROBE_COMMAND_TIMEOUT_MS,
36
+ });
37
+ return {
38
+ code: outcome.code,
39
+ stdout: outcome.stdout.toString('utf8'),
40
+ stderr: outcome.stderr.toString('utf8'),
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Read `.simt/local/ledger.jsonl` from `workDir` if present.
46
+ *
47
+ * @param {string} workDir
48
+ * @returns {Promise<Array<object>>}
49
+ */
50
+
51
+
52
+ /**
53
+ * Read `.simt/local/ledger.jsonl` from `workDir` if present.
54
+ *
55
+ * @param {string} workDir
56
+ * @returns {Promise<Array<object>>}
57
+ */
58
+ export async function readLedgerEntries(workDir) {
59
+ const ledgerPath = join(workDir, LOCAL_DIR, 'ledger.jsonl');
60
+ try {
61
+ const text = await readFile(ledgerPath, 'utf8');
62
+ const entries = [];
63
+ for (const line of text.split('\n')) {
64
+ const trimmed = line.trim();
65
+ if (!trimmed) continue;
66
+ try {
67
+ entries.push(JSON.parse(trimmed));
68
+ } catch {
69
+ // ignore malformed line
70
+ }
71
+ }
72
+ return entries;
73
+ } catch {
74
+ return [];
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Append a ledger entry to `.simt/local/ledger.jsonl` in `workDir`.
80
+ */
81
+
82
+
83
+ /**
84
+ * Append a ledger entry to `.simt/local/ledger.jsonl` in `workDir`.
85
+ */
86
+ export async function appendLedgerEntry(workDir, entry) {
87
+ const ledgerPath = join(workDir, LOCAL_DIR, 'ledger.jsonl');
88
+ await mkdir(dirname(ledgerPath), { recursive: true });
89
+ const treeRes = await runGit(['write-tree'], { cwd: workDir });
90
+ const record = {
91
+ v: 1,
92
+ ts: new Date().toISOString(),
93
+ tree: treeRes.stdout.trim(),
94
+ cmd: entry.cmd,
95
+ exit: entry.exit ?? 0,
96
+ ms: entry.ms ?? 10,
97
+ outputDigest: entry.outputDigest ?? 'sha256-0000000000000000',
98
+ summary: entry.summary ?? '1 pass, 0 fail',
99
+ };
100
+ const prev = await readFile(ledgerPath, 'utf8').catch(() => '');
101
+ await writeFile(ledgerPath, `${prev}${JSON.stringify(record)}\n`, 'utf8');
102
+ return record;
103
+ }
104
+
105
+ /**
106
+ * Extract shell commands from an agent transcript or command list.
107
+ *
108
+ * @param {{commands?: string[], stdout?: string, stderr?: string, ledger?: Array<{cmd?: string}>}} ctx
109
+ * @returns {string[]}
110
+ */
111
+
112
+
113
+ /** How long one agent-backed probe may run before its workspace is reclaimed. */
114
+
115
+ /** The deadline for one workspace-side git or node command inside a probe. */
116
+ export function extractTranscriptCommands(ctx = {}) {
117
+ const cmds = [];
118
+ if (Array.isArray(ctx.commands)) {
119
+ for (const c of ctx.commands) {
120
+ if (typeof c === 'string' && c.trim()) cmds.push(c.trim());
121
+ }
122
+ }
123
+ if (Array.isArray(ctx.ledger)) {
124
+ for (const entry of ctx.ledger) {
125
+ if (typeof entry?.cmd === 'string' && entry.cmd.trim()) cmds.push(entry.cmd.trim());
126
+ }
127
+ }
128
+ const text = `${ctx.stdout ?? ''}\n${ctx.stderr ?? ''}`;
129
+ for (const line of text.split('\n')) {
130
+ const trimmed = line.trim();
131
+ const dollarMatch = /^\$\s+(.+)$/.exec(trimmed);
132
+ if (dollarMatch) cmds.push(dollarMatch[1].trim());
133
+ }
134
+ return cmds;
135
+ }
136
+
137
+ /**
138
+ * The 12 synthetic compliance probes (R05).
139
+ */
140
+
141
+ /**
142
+ * Create an isolated git workspace for `probe`, materialise `armSpec` if supplied,
143
+ * commit the baseline `initialHead`, and run any post-commit setup (such as hooks,
144
+ * remotes, or dirty untracked files).
145
+ *
146
+ * @param {object} probe
147
+ * @param {{armSpec?: object, parentDir?: string}} [options]
148
+ * @returns {Promise<{slotDir: string, workDir: string, initialHead: string}>}
149
+ */