simt-dev 0.7.0 → 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 (235) hide show
  1. package/CHANGELOG.md +191 -870
  2. package/README.md +188 -213
  3. package/bin/simt.mjs +19 -55
  4. package/docs/decisions/ADR-014-workspace-is-configuration.md +2 -2
  5. package/docs/decisions/ADR-025-a-baseline-is-a-region-in-a-file-the-repo-owns.md +1 -1
  6. package/docs/decisions/ADR-026-a-config-without-a-region-is-a-file-the-repo-owns.md +1 -1
  7. package/docs/decisions/ADR-027-the-one-gitattributes-line-that-is-neither-dangerous-nor-empty.md +1 -1
  8. package/docs/decisions/ADR-028-a-base-file-is-a-floor-so-the-disagreement-it-cannot-repair-becomes-a-check.md +1 -1
  9. package/docs/decisions/ADR-029-the-pins-a-repository-declares-are-its-own.md +1 -1
  10. package/docs/decisions/ADR-030-what-a-plan-does-not-ship-is-a-decision-with-a-record.md +1 -1
  11. package/docs/decisions/ADR-048-a-baseline-carries-only-keys-a-reader-honours.md +1 -1
  12. package/docs/decisions/ADR-082-the-tracker-override-is-a-manifest-key.md +1 -1
  13. package/docs/decisions/ADR-099-the-release-verifies-served-bytes-and-the-formula-mirrors-them.md +1 -1
  14. package/docs/decisions/ADR-117-the-darwin-release-builds-on-supported-macos-15-runners-and-a-re-run-is-idempotent.md +81 -0
  15. package/docs/decisions/ADR-118-the-bench-corpus-is-keyed-on-history-is-append-only-and-is-portable-as-a-sealed-document.md +91 -0
  16. package/docs/decisions/ADR-119-the-environment-variable-points-into-a-workspace-the-repo-declared.md +90 -0
  17. package/docs/decisions/ADR-120-a-pre-push-whose-tree-is-already-proven-green-skips-the-test-gate-on-that-evidence.md +96 -0
  18. package/docs/decisions/ADR-122-the-shims-move-into-the-state-directory-and-the-legacy-directory-removes-itself.md +94 -0
  19. package/docs/decisions/ADR-123-a-surplus-positional-is-not-refused-because-arity-is-not-in-the-source.md +57 -0
  20. package/docs/decisions/ADR-124-the-manifest-has-a-schema-in-the-tool-and-its-unknown-keys-stay-the-repositorys.md +64 -0
  21. package/docs/decisions/ADR-125-a-shared-context-belongs-to-a-read-and-a-writer-reads-directly.md +65 -0
  22. package/docs/decisions/ADR-126-the-mcp-surface-stays-a-reader-so-there-is-no-write-path-to-build.md +68 -0
  23. package/docs/decisions/ADR-127-the-mcp-tool-list-is-written-by-hand-and-roots-is-not-asked-for.md +65 -0
  24. package/docs/decisions/ADR-128-a-research-plan-is-a-plan-and-the-tracker-reads-it.md +42 -0
  25. package/ecosystems/bun.json +6 -0
  26. package/ecosystems/cargo.json +25 -0
  27. package/ecosystems/composer.json +6 -0
  28. package/ecosystems/dart.json +24 -0
  29. package/ecosystems/deno.json +21 -0
  30. package/ecosystems/devcontainers.json +6 -0
  31. package/ecosystems/docker-compose.json +6 -0
  32. package/ecosystems/docker.json +6 -0
  33. package/ecosystems/dotnet.json +25 -0
  34. package/ecosystems/elixir.json +23 -0
  35. package/ecosystems/gitsubmodule.json +6 -0
  36. package/ecosystems/go.json +25 -0
  37. package/ecosystems/gradle.json +13 -0
  38. package/ecosystems/maven.json +23 -0
  39. package/ecosystems/node.json +25 -0
  40. package/ecosystems/python.json +20 -0
  41. package/ecosystems/ruby.json +23 -0
  42. package/ecosystems/swift.json +25 -0
  43. package/ecosystems/terraform.json +6 -0
  44. package/ecosystems/uv.json +6 -0
  45. package/harnesses/antigravity.json +162 -0
  46. package/harnesses/claude.json +206 -0
  47. package/harnesses/codex.json +136 -0
  48. package/harnesses/copilot.json +88 -0
  49. package/harnesses/cursor.json +140 -0
  50. package/harnesses/deepseek.json +99 -0
  51. package/harnesses/gemini.json +122 -0
  52. package/harnesses/opencode.json +173 -0
  53. package/package.json +12 -2
  54. package/rules/core.md +7 -0
  55. package/rules/mdc/intake-questions.mdc +8 -0
  56. package/rules/mdc/slice-commit.mdc +57 -4
  57. package/src/advice/advice.mjs +3 -2
  58. package/src/agenthooks/prompt.mjs +5 -2
  59. package/src/agenthooks/render.mjs +86 -180
  60. package/src/agenthooks/shim.mjs +1 -1
  61. package/src/agents/render.mjs +15 -18
  62. package/src/api.mjs +31 -0
  63. package/src/argv.mjs +48 -3
  64. package/src/bench/ablate.mjs +3 -4
  65. package/src/bench/adapters.json +163 -105
  66. package/src/bench/adapters.mjs +466 -0
  67. package/src/bench/arms.mjs +333 -0
  68. package/src/bench/grade.mjs +33 -73
  69. package/src/bench/graders.mjs +42 -0
  70. package/src/bench/mine.mjs +121 -475
  71. package/src/bench/probe-ledger.mjs +149 -0
  72. package/src/bench/probes.catalog.mjs +918 -0
  73. package/src/bench/probes.mjs +79 -1064
  74. package/src/bench/render.mjs +111 -0
  75. package/src/bench/report.mjs +120 -962
  76. package/src/bench/run.mjs +185 -802
  77. package/src/bench/variants.mjs +4 -5
  78. package/src/bench/workspace.mjs +160 -0
  79. package/src/brief/assemble.mjs +48 -15
  80. package/src/ci/dependabot.mjs +25 -55
  81. package/src/ci/workflow.mjs +30 -7
  82. package/src/cli.mjs +45 -0
  83. package/src/commands/agent.mjs +4 -13
  84. package/src/commands/agenthook.mjs +70 -40
  85. package/src/commands/bench.mjs +191 -18
  86. package/src/commands/brief.mjs +5 -4
  87. package/src/commands/ci.mjs +13 -14
  88. package/src/commands/compare.mjs +42 -42
  89. package/src/commands/completions.mjs +2 -6
  90. package/src/commands/decide.mjs +4 -4
  91. package/src/commands/distill.mjs +4 -3
  92. package/src/commands/docs.mjs +88 -0
  93. package/src/commands/doctor.mjs +11 -7
  94. package/src/commands/evidence.mjs +6 -9
  95. package/src/commands/explain.mjs +0 -1
  96. package/src/commands/gate.mjs +26 -25
  97. package/src/commands/graph.mjs +2 -3
  98. package/src/commands/harness.mjs +6 -5
  99. package/src/commands/help.mjs +168 -19
  100. package/src/commands/hooks.mjs +119 -49
  101. package/src/commands/ignore.mjs +13 -8
  102. package/src/commands/impact.mjs +8 -15
  103. package/src/commands/index.mjs +318 -193
  104. package/src/commands/init-scan.mjs +90 -0
  105. package/src/commands/init.mjs +124 -105
  106. package/src/commands/lease.mjs +73 -25
  107. package/src/commands/lessons.mjs +10 -9
  108. package/src/commands/local.mjs +3 -3
  109. package/src/commands/map.mjs +24 -14
  110. package/src/commands/mcp.mjs +2 -18
  111. package/src/commands/pack.mjs +9 -6
  112. package/src/commands/plan.mjs +6 -5
  113. package/src/commands/plugin.mjs +2 -2
  114. package/src/commands/prbody.mjs +3 -3
  115. package/src/commands/repoindex.mjs +12 -11
  116. package/src/commands/review.mjs +2 -2
  117. package/src/commands/rules.mjs +37 -16
  118. package/src/commands/shared.mjs +14 -19
  119. package/src/commands/skills.mjs +33 -32
  120. package/src/commands/skillscompile.mjs +7 -8
  121. package/src/commands/skillsinstall.mjs +7 -6
  122. package/src/commands/slice.mjs +220 -74
  123. package/src/commands/spec.mjs +167 -0
  124. package/src/commands/status.mjs +27 -18
  125. package/src/commands/sync.mjs +27 -25
  126. package/src/commands/tests.mjs +18 -21
  127. package/src/commands/tokens.mjs +21 -26
  128. package/src/commands/undo.mjs +5 -15
  129. package/src/commands/upgrade.mjs +15 -7
  130. package/src/commands/why.mjs +15 -21
  131. package/src/compare/hooksstate.mjs +2 -6
  132. package/src/compare/learn.mjs +3 -1
  133. package/src/compare/row.mjs +0 -2
  134. package/src/context.mjs +64 -0
  135. package/src/decisions/index-doc.mjs +46 -0
  136. package/src/decisions/index.mjs +3 -2
  137. package/src/diff.mjs +1 -1
  138. package/src/distill/distill.mjs +14 -1
  139. package/src/distill/engine.mjs +5 -1
  140. package/src/docs/commands.mjs +65 -0
  141. package/src/ecosystem/records.mjs +219 -0
  142. package/src/explain.mjs +31 -0
  143. package/src/gates/index.mjs +385 -0
  144. package/src/graph/compile.mjs +8 -4
  145. package/src/graph/load.mjs +6 -2
  146. package/src/graph/spec.mjs +10 -8
  147. package/src/harness/records.mjs +143 -0
  148. package/src/hooks/capability.mjs +7 -5
  149. package/src/hooks/dispatcher.mjs +209 -60
  150. package/src/hooks/gates.mjs +10 -43
  151. package/src/hooks/resolve.mjs +4 -14
  152. package/src/hooks/shim.mjs +5 -2
  153. package/src/hooks/where.mjs +2 -7
  154. package/src/identity.mjs +31 -12
  155. package/src/index/coverage.mjs +58 -0
  156. package/src/index/extract.mjs +6 -16
  157. package/src/index/gate.mjs +1 -1
  158. package/src/index/govern.mjs +26 -9
  159. package/src/index/impact.mjs +4 -8
  160. package/src/index/map.mjs +14 -15
  161. package/src/index/open.mjs +173 -0
  162. package/src/index/persist.mjs +224 -57
  163. package/src/index/store.mjs +82 -39
  164. package/src/index/tests.mjs +2 -6
  165. package/src/journal.mjs +94 -20
  166. package/src/kernel/card.mjs +37 -63
  167. package/src/kernel/checks.mjs +4 -10
  168. package/src/lease.mjs +102 -7
  169. package/src/ledger/index.mjs +150 -14
  170. package/src/local/client.mjs +4 -6
  171. package/src/locate.mjs +33 -9
  172. package/src/manifest/schema.mjs +213 -0
  173. package/src/mcp/paginate.mjs +33 -0
  174. package/src/mcp/resources.mjs +7 -10
  175. package/src/mcp/schemas.mjs +512 -0
  176. package/src/mcp/server.mjs +119 -25
  177. package/src/mcp/tools-facts.mjs +326 -0
  178. package/src/mcp/tools-read.mjs +221 -0
  179. package/src/mcp/tools.mjs +4 -967
  180. package/src/measure/corpus.mjs +150 -0
  181. package/src/measure/metrics.mjs +236 -0
  182. package/src/measure/records.mjs +211 -0
  183. package/src/measure/session.mjs +3 -2
  184. package/src/measure/stats.mjs +538 -0
  185. package/src/measure/task-schema.mjs +125 -0
  186. package/src/measure/tasks.mjs +69 -0
  187. package/src/memory/decide.mjs +6 -15
  188. package/src/memory/lesson-text.mjs +61 -0
  189. package/src/memory/lessons.mjs +29 -82
  190. package/src/name.mjs +7 -0
  191. package/src/node-version.mjs +37 -0
  192. package/src/output/index.mjs +209 -10
  193. package/src/packs/manage.mjs +32 -12
  194. package/src/packs.mjs +20 -2
  195. package/src/plan/index.mjs +1 -1
  196. package/src/plugins.mjs +22 -16
  197. package/src/prbody.mjs +7 -11
  198. package/src/projection/loaders.mjs +7 -692
  199. package/src/projection/lock.mjs +11 -1
  200. package/src/projection/manifest.mjs +29 -468
  201. package/src/projection/mdc.mjs +7 -8
  202. package/src/projection/project.mjs +126 -221
  203. package/src/projection/region.mjs +561 -0
  204. package/src/projection/rules.mjs +20 -550
  205. package/src/projection/surfaces.mjs +43 -210
  206. package/src/projection/targets.mjs +5 -5
  207. package/src/repo-root.mjs +31 -0
  208. package/src/resolve/eval.mjs +2 -1
  209. package/src/resolve/fingerprint.mjs +19 -22
  210. package/src/resolve/resolve.mjs +1 -41
  211. package/src/review/critic.mjs +10 -13
  212. package/src/run.mjs +98 -0
  213. package/src/secrets.mjs +14 -22
  214. package/src/state/events.mjs +129 -0
  215. package/src/status-snapshot.mjs +233 -0
  216. package/src/status.mjs +2 -6
  217. package/src/sys/git.mjs +82 -0
  218. package/src/sys/proc.mjs +151 -0
  219. package/src/testing/parsers.mjs +265 -0
  220. package/src/testing/patches.mjs +23 -0
  221. package/src/testing/paths.mjs +49 -0
  222. package/src/testing/runners.mjs +186 -0
  223. package/src/testing/vault.mjs +68 -0
  224. package/src/text/frontmatter.mjs +49 -0
  225. package/src/text/tokens.mjs +52 -0
  226. package/src/toolwords.mjs +3 -0
  227. package/src/util/fs.mjs +20 -0
  228. package/src/util/sort.mjs +12 -0
  229. package/src/workspace.mjs +58 -11
  230. package/src/write/plan.mjs +82 -0
  231. package/templates/plan/tracker.json +1 -0
  232. package/docs/decisions/ADR-033-three-plan-rows-closed-by-decision-not-by-authoring.md +0 -82
  233. package/docs/decisions/ADR-102-the-two-queued-review-rows-are-closed-by-ruling.md +0 -49
  234. package/docs/decisions/README.md +0 -600
  235. package/src/bench/tasks.mjs +0 -36
@@ -0,0 +1,221 @@
1
+ // Half of the MCP tool list. The tools are read-only and answer through the commands.
2
+
3
+ import { loadRegistry } from '../graph/load.mjs';
4
+ import { provenanceDigest } from '../projection/project.mjs';
5
+ import { discover } from '../compare/discover.mjs';
6
+ import { buildRows, resolveConcurrency, summarise } from '../compare/row.mjs';
7
+ import { GATES } from '../hooks/gates.mjs';
8
+ import { checkRepo } from '../commands/sync.mjs';
9
+ import { diagnose, serialisedFindings } from '../commands/doctor.mjs';
10
+ import { rulesCatalogue, rulesWhyFacts } from '../commands/rules.mjs';
11
+ import { skillsBriefFacts, skillsFindFacts, skillsShowFacts, skillsWhyFacts } from '../commands/skills.mjs';
12
+ import { assembleBrief } from '../brief/assemble.mjs';
13
+ import { DEFAULT_BRIEF_BYTES } from '../brief/packet.mjs';
14
+ import { federationAccess, readFederation } from '../federation/config.mjs';
15
+ import { consult } from '../federation/query.mjs';
16
+ import { planNext, planDone } from '../plan/index.mjs';
17
+ import { buildPrBody } from '../prbody.mjs';
18
+ import { configPaths, readUserConfig, resolveWorkspace } from '../workspace.mjs';
19
+ import { measureSkill } from '../graph/load.mjs';
20
+ import { CLI } from '../name.mjs';
21
+ import { ERROR_SHAPE, GATE_KINDS, noArgs, output, rootArg } from './schemas.mjs';
22
+ import { registry, rootOf } from './schemas.mjs';
23
+
24
+ export const TOOLS_READ = [
25
+ {
26
+ outputSchema: output.doctor,
27
+ name: 'doctor',
28
+ description:
29
+ 'Classify a repository: stack tags, the facts with the file that proved each, and manifest presence. Call this first when the repo is unknown. Read-only: `--fix` and `--diff` stay on the command.',
30
+ inputSchema: rootArg,
31
+ async run(args) {
32
+ const root = rootOf(args);
33
+ const { result, ws, shared, findings, failure } = await diagnose(root, args ?? {});
34
+ return {
35
+ root,
36
+ ...result,
37
+ workspace: { root: ws.root ?? null, source: ws.source, detail: ws.detail, error: ws.error ?? null },
38
+ shared,
39
+ findings: serialisedFindings(findings),
40
+ // Read-only here: the command applies fixes behind `--fix`, the tool only reports.
41
+ fix: { requested: false, applied: false, fixed: [], failed: [] },
42
+ ...(failure ?? {}),
43
+ };
44
+ },
45
+ },
46
+
47
+ {
48
+ outputSchema: output.skills_index,
49
+ name: 'skills_index',
50
+ description:
51
+ 'Full skill catalogue: every skill with summary, size, stack tags and deferred flag. The fallback when brief returns nothing useful.',
52
+ inputSchema: {
53
+ type: 'object',
54
+ properties: {
55
+ registry: { type: 'string', description: 'path to skills.graph.json; else --registry / SIMT_REGISTRY / default tiers' },
56
+ },
57
+ required: [],
58
+ },
59
+ async run(args) {
60
+ const { registry: reg, verified, workspace } = await registry(args);
61
+ return {
62
+ skills: reg.skills.length,
63
+ totalBytes: reg.skills.reduce((n, s) => n + s.bytes, 0),
64
+ deferred: reg.skills.filter((s) => s.deferred).map((s) => s.name),
65
+ workspace,
66
+ verified,
67
+ entries: [...reg.skills]
68
+ .sort((a, b) => a.name.localeCompare(b.name))
69
+ .map((s) => ({ name: s.name, summary: s.summary, bytes: s.bytes, stack: s.stack, deferred: Boolean(s.deferred) })),
70
+ };
71
+ },
72
+ },
73
+
74
+ {
75
+ outputSchema: output.skills_brief,
76
+ name: 'skills_brief',
77
+ description:
78
+ 'THE entry point. Resolve the skill set for a task: selected with why, deferred, and not selected with the reason to override.',
79
+ inputSchema: {
80
+ type: 'object',
81
+ properties: {
82
+ root: { type: 'string' },
83
+ task: { type: 'string', description: 'what you are about to do, in your own words' },
84
+ paths: { type: 'string', description: 'comma-separated globs; defaults to the git diff' },
85
+ budget: { type: 'number', description: 'context budget in bytes (default 20480)' },
86
+ skill: { type: 'string', description: 'force a skill in, comma-separated' },
87
+ all: { type: 'boolean', description: 'ignore the budget' },
88
+ registry: { type: 'string', description: 'path to skills.graph.json; else --registry / SIMT_REGISTRY / default tiers' },
89
+ },
90
+ required: [],
91
+ },
92
+ async run(args) {
93
+ const root = rootOf(args);
94
+ const facts = await skillsBriefFacts(root, args ?? {});
95
+ // No body is ever returned by this tool: a caller that wants one calls
96
+ // skills_show, which makes the cost visible before it is paid.
97
+ if (facts.kind === 'all') {
98
+ return {
99
+ all: true,
100
+ repoStack: facts.repoStack,
101
+ inline: facts.inline.map((s) => s.name),
102
+ deferred: facts.deferred.map((s) => s.name),
103
+ ...(facts.warning ? { warning: facts.warning } : {}),
104
+ };
105
+ }
106
+ const { shown, shownDeferred, shownUsed, pointerOnly, excludedEntries, workspaceRoot, kind, ...doc } = facts;
107
+ return doc;
108
+ },
109
+ },
110
+
111
+ {
112
+ outputSchema: output.skills_show,
113
+ name: 'skills_show',
114
+ description: 'One skill body and the metadata needed to judge it: source path, the location it was read from, and its cited decisions.',
115
+ inputSchema: {
116
+ type: 'object',
117
+ properties: {
118
+ name: { type: 'string' },
119
+ root: { type: 'string' },
120
+ maxBytes: { type: 'number', description: 'hard ceiling on the returned text' },
121
+ registry: { type: 'string', description: 'path to skills.graph.json; else --registry / SIMT_REGISTRY / default tiers' },
122
+ },
123
+ required: ['name'],
124
+ },
125
+ async run(args) {
126
+ const root = rootOf(args);
127
+ const facts = await skillsShowFacts(root, args?.name, args ?? {});
128
+ // The schema promises `body: null` when there is no body, and this used to hand the
129
+ // prose that says so to the field a client tests for null: a caller checking `body`
130
+ // for null read a paragraph as a body (Q56). The prose moves to `reason`, which is
131
+ // where a model looks for what to do about it.
132
+ const missing = typeof facts.bodyText === 'string' && facts.bodyText.startsWith('(body unavailable');
133
+ return {
134
+ ...facts.skill,
135
+ workspace: facts.workspace,
136
+ body: missing ? null : facts.body,
137
+ bodyFrom: facts.bodyFrom,
138
+ bodyText: missing ? null : facts.bodyText,
139
+ reason: missing ? facts.bodyText : null,
140
+ };
141
+ },
142
+ },
143
+
144
+ {
145
+ outputSchema: output.skills_find,
146
+ name: 'skills_find',
147
+ description: 'Raw search across capability, keyword and summary. Use when skills_brief has nothing and you suspect a skill exists.',
148
+ inputSchema: {
149
+ type: 'object',
150
+ properties: {
151
+ query: { type: 'string' },
152
+ root: { type: 'string' },
153
+ registry: { type: 'string', description: 'path to skills.graph.json; else --registry / SIMT_REGISTRY / default tiers' },
154
+ },
155
+ required: ['query'],
156
+ },
157
+ async run(args) {
158
+ const root = rootOf(args);
159
+ return skillsFindFacts(root, typeof args?.query === 'string' ? args.query : '', args ?? {});
160
+ },
161
+ },
162
+
163
+ {
164
+ outputSchema: output.skills_why,
165
+ name: 'skills_why',
166
+ description:
167
+ 'The signal chain for one skill in one repository: its score, the reasons, whether the stack gate admits it, and what would select it.',
168
+ inputSchema: {
169
+ type: 'object',
170
+ properties: {
171
+ name: { type: 'string' },
172
+ root: { type: 'string' },
173
+ task: { type: 'string' },
174
+ registry: { type: 'string', description: 'path to skills.graph.json; else --registry / SIMT_REGISTRY / default tiers' },
175
+ },
176
+ required: ['name'],
177
+ },
178
+ async run(args) {
179
+ const root = rootOf(args);
180
+ return skillsWhyFacts(root, args?.name, args ?? {});
181
+ },
182
+ },
183
+
184
+ {
185
+ outputSchema: output.rules_list,
186
+ name: 'rules_list',
187
+ description:
188
+ 'The rule catalogue, and which rules a repository actually receives. Pass root for the selection, not just the catalogue.',
189
+ inputSchema: {
190
+ type: 'object',
191
+ properties: { root: { type: 'string' } },
192
+ required: [],
193
+ },
194
+ async run(args) {
195
+ const root = typeof args?.root === 'string' && args.root ? args.root : null;
196
+ const { rules, notes } = await rulesCatalogue(root, { selectFor: root });
197
+ return {
198
+ sha: await provenanceDigest(),
199
+ notes,
200
+ rules,
201
+ };
202
+ },
203
+ },
204
+
205
+ {
206
+ outputSchema: output.rules_why,
207
+ name: 'rules_why',
208
+ description:
209
+ 'Why a rule exists: a rule id for the decisions that settled it, or an ADR id for the rules that repeat it. An uncited rule is a finding, reported so.',
210
+ inputSchema: {
211
+ type: 'object',
212
+ properties: { what: { type: 'string', description: 'a rule id or ADR-NNN' } },
213
+ required: ['what'],
214
+ },
215
+ async run(args) {
216
+ const what = typeof args?.what === 'string' ? args.what : '';
217
+ return rulesWhyFacts(null, what, {});
218
+ },
219
+ },
220
+
221
+ ];