@smartmemory/compose 0.2.58-beta → 0.3.1-beta

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 (100) hide show
  1. package/README.md +2 -2
  2. package/bin/compose.js +55 -54
  3. package/dist/assets/{App-s4CulNkO.js → App-DR9pCiNE.js} +290 -290
  4. package/dist/assets/{abnfDiagram-VRR7QNED-CDwzQ5wr.js → abnfDiagram-VRR7QNED-CZ6p2bRe.js} +1 -1
  5. package/dist/assets/{arc-kIU8DDth.js → arc-6j04LBqn.js} +1 -1
  6. package/dist/assets/{architectureDiagram-ZJ3FMSHR-CleorO_0.js → architectureDiagram-ZJ3FMSHR-00QM3pmc.js} +1 -1
  7. package/dist/assets/{blockDiagram-677ZJIJ3-NvEFfoMk.js → blockDiagram-677ZJIJ3-BUb9Kjfd.js} +1 -1
  8. package/dist/assets/{c4Diagram-LMCZKHZV-BcDQdTVB.js → c4Diagram-LMCZKHZV-D1PkhmSm.js} +1 -1
  9. package/dist/assets/channel-BcWZM2KA.js +1 -0
  10. package/dist/assets/{chunk-2Q5K7J3B-BseRkpm4.js → chunk-2Q5K7J3B-CduDdMf4.js} +1 -1
  11. package/dist/assets/{chunk-32BRIVSS-DCHhvgFV.js → chunk-32BRIVSS-CH8Kj5rh.js} +1 -1
  12. package/dist/assets/{chunk-5VM5RSS4-DcTpMdJ4.js → chunk-5VM5RSS4-Cfts6Lix.js} +1 -1
  13. package/dist/assets/{chunk-EX3LRPZG-BdN8fvWs.js → chunk-EX3LRPZG-Dguk4yKZ.js} +1 -1
  14. package/dist/assets/{chunk-JWPE2WC7-DmZJP-8E.js → chunk-JWPE2WC7-DbCJp6t9.js} +1 -1
  15. package/dist/assets/{chunk-MOJQB5TN-V74uYM17.js → chunk-MOJQB5TN-CNjM_9_U.js} +1 -1
  16. package/dist/assets/{chunk-RYQCIY6F-CoXUXbn_.js → chunk-RYQCIY6F-D4k-BUbh.js} +1 -1
  17. package/dist/assets/{chunk-V7JOEXUC-DUscIydR.js → chunk-V7JOEXUC-O1sFoHf1.js} +1 -1
  18. package/dist/assets/{chunk-VR4S4FIN-C4UDHq_a.js → chunk-VR4S4FIN-CGbSXVPL.js} +1 -1
  19. package/dist/assets/{chunk-XXDRQBXY-DIH9i8mZ.js → chunk-XXDRQBXY-iIelV7SO.js} +1 -1
  20. package/dist/assets/classDiagram-OUVF2IWQ-Ce7YjlIK.js +1 -0
  21. package/dist/assets/classDiagram-v2-EOCWNBFH-Ce7YjlIK.js +1 -0
  22. package/dist/assets/{cose-bilkent-JH36ORCC-Dn6Gy6l1.js → cose-bilkent-JH36ORCC-BKmPLgw2.js} +1 -1
  23. package/dist/assets/{cynefin-VYW2F7L2-C2LW5fzB.js → cynefin-VYW2F7L2-CmT6ieC5.js} +1 -1
  24. package/dist/assets/{cynefinDiagram-TSTJHNR4-CGoAq7C9.js → cynefinDiagram-TSTJHNR4-Hn2vSVOw.js} +1 -1
  25. package/dist/assets/{dagre-VKFMJZFB-BaOKtuBE.js → dagre-VKFMJZFB-B0ifIwlU.js} +1 -1
  26. package/dist/assets/{diagram-FQU43EPY-BdQwqt4x.js → diagram-FQU43EPY-BuCDB-JG.js} +1 -1
  27. package/dist/assets/{diagram-G47NLZAW-Dkcf0o5z.js → diagram-G47NLZAW-D5avTZAQ.js} +1 -1
  28. package/dist/assets/{diagram-NH7WQ7WH-C_fDi59r.js → diagram-NH7WQ7WH-24QCIgpj.js} +1 -1
  29. package/dist/assets/{diagram-OA4YK3LP-jaTQcOxt.js → diagram-OA4YK3LP-A-bbUTK3.js} +1 -1
  30. package/dist/assets/{diagram-WEI45ONY-dEtqVj3s.js → diagram-WEI45ONY-BIMDm-Kj.js} +1 -1
  31. package/dist/assets/{ebnfDiagram-CCIWWBDH-s8ImqsSs.js → ebnfDiagram-CCIWWBDH-DCXMfG-M.js} +1 -1
  32. package/dist/assets/{erDiagram-Q63AITRT-5Zy29-SA.js → erDiagram-Q63AITRT-BlDrG0Ev.js} +1 -1
  33. package/dist/assets/{flowDiagram-23GEKE2U-DV74V9he.js → flowDiagram-23GEKE2U-aTyazY6P.js} +1 -1
  34. package/dist/assets/{ganttDiagram-NO4QXBWP-BND-CiLO.js → ganttDiagram-NO4QXBWP-Bxo-a80f.js} +1 -1
  35. package/dist/assets/{gitGraphDiagram-IHSO6WYX-B_-Mf9Jo.js → gitGraphDiagram-IHSO6WYX-COhKb9wR.js} +1 -1
  36. package/dist/assets/index-BcmsQZX-.js +119 -0
  37. package/dist/assets/{infoDiagram-FWYZ7A6U-Duyz8rZM.js → infoDiagram-FWYZ7A6U-DLCbpinV.js} +1 -1
  38. package/dist/assets/{ishikawaDiagram-FXEZZL3T-D2Qft0e5.js → ishikawaDiagram-FXEZZL3T-eyHF7GIj.js} +1 -1
  39. package/dist/assets/{journeyDiagram-5HDEW3XC-q6rG4Rig.js → journeyDiagram-5HDEW3XC-BsVocmlw.js} +1 -1
  40. package/dist/assets/{kanban-definition-HUTT4EX6-CsPX7gBL.js → kanban-definition-HUTT4EX6-CaFPSZxY.js} +1 -1
  41. package/dist/assets/{linear-CiccpAAd.js → linear-cqnI_wgW.js} +1 -1
  42. package/dist/assets/{mindmap-definition-LN4V7U3C-DRW2njpA.js → mindmap-definition-LN4V7U3C-B66BGqKn.js} +1 -1
  43. package/dist/assets/{pegDiagram-2B236MQR-DoDgm2S_.js → pegDiagram-2B236MQR-F6IN0_L5.js} +1 -1
  44. package/dist/assets/{pieDiagram-ENE6RG2P-CNSYLVAF.js → pieDiagram-ENE6RG2P-D5nOQxpo.js} +1 -1
  45. package/dist/assets/{quadrantDiagram-ABIIQ3AL-8-Nd6ony.js → quadrantDiagram-ABIIQ3AL-DwUAYbMO.js} +1 -1
  46. package/dist/assets/{railroadDiagram-RFXS5EU6-bfdg6Bo4.js → railroadDiagram-RFXS5EU6-Cvmlah5P.js} +1 -1
  47. package/dist/assets/{requirementDiagram-TGXJPOKE-slDkxCQy.js → requirementDiagram-TGXJPOKE-DoUtsFnL.js} +1 -1
  48. package/dist/assets/{sankeyDiagram-HTMAVEWB-CR3CboiK.js → sankeyDiagram-HTMAVEWB-D4XTwiKp.js} +1 -1
  49. package/dist/assets/{sequenceDiagram-DBY2YBRQ-BIXw1JS1.js → sequenceDiagram-DBY2YBRQ-CiG9yRIR.js} +1 -1
  50. package/dist/assets/{sizeCapture-X5ZJPWSS-BdKI7JyF.js → sizeCapture-X5ZJPWSS-zd7ydQ_Y.js} +1 -1
  51. package/dist/assets/{stateDiagram-2N3HPSRC-ktVgpBZS.js → stateDiagram-2N3HPSRC-BZesBHQ4.js} +1 -1
  52. package/dist/assets/stateDiagram-v2-6OUMAXLB-BnlLOJzB.js +1 -0
  53. package/dist/assets/{swimlanes-5IMT3BWC-CaXpC3FM.js → swimlanes-5IMT3BWC-Bg8exSE7.js} +2 -2
  54. package/dist/assets/swimlanesDiagram-G3AALYLV-DZMVxqbs.js +8 -0
  55. package/dist/assets/{timeline-definition-FHXFAJF6-CKWSlRUl.js → timeline-definition-FHXFAJF6-TKj_HY9k.js} +1 -1
  56. package/dist/assets/{vennDiagram-L72KCM5P-CwOhxDyv.js → vennDiagram-L72KCM5P-CJf-bqn0.js} +1 -1
  57. package/dist/assets/{wardleyDiagram-EHGQE667-DGavMpEB.js → wardleyDiagram-EHGQE667-CqizSfCL.js} +1 -1
  58. package/dist/assets/{xychartDiagram-FW5EYKEG-CWmnmLZz.js → xychartDiagram-FW5EYKEG-CK-OErMM.js} +1 -1
  59. package/dist/index.html +1 -1
  60. package/lib/build-all.js +0 -5
  61. package/lib/build-stream-schema.js +1 -1
  62. package/lib/build.js +1762 -2614
  63. package/lib/consumer-fanout.js +1317 -0
  64. package/lib/feature-validator.js +6 -4
  65. package/lib/flow-state.js +15 -14
  66. package/lib/gsd-budget.js +48 -10
  67. package/lib/gsd-prompt.js +3 -4
  68. package/lib/gsd-stuck.js +1 -1
  69. package/lib/gsd.js +303 -149
  70. package/lib/local-claude-connector.js +149 -0
  71. package/lib/new.js +162 -307
  72. package/lib/result-normalizer.js +233 -18
  73. package/lib/review-lenses.js +1 -1
  74. package/lib/step-prompt.js +41 -119
  75. package/lib/stratum-engine.js +297 -0
  76. package/lib/stratum-mcp-client.js +224 -213
  77. package/lib/vocabulary-compliance.js +268 -0
  78. package/lib/vocabulary-inject.js +1 -36
  79. package/package.json +6 -2
  80. package/pipelines/build-quick.stratum.yaml +5 -17
  81. package/pipelines/build.profiles.json +11 -0
  82. package/pipelines/build.stratum.yaml +288 -467
  83. package/pipelines/gsd.stratum.yaml +73 -125
  84. package/pipelines/new.stratum.yaml +68 -149
  85. package/server/build-routes.js +4 -1
  86. package/server/design-routes.js +37 -21
  87. package/server/index.js +13 -21
  88. package/server/lifecycle-guard.js +1 -1
  89. package/server/pipeline-routes.js +113 -31
  90. package/server/stratum-client.js +33 -47
  91. package/server/stratum-sync.js +3 -4
  92. package/server/vision-server.js +1 -1
  93. package/dist/assets/channel-DiJkE9og.js +0 -1
  94. package/dist/assets/classDiagram-OUVF2IWQ-DS76VBEL.js +0 -1
  95. package/dist/assets/classDiagram-v2-EOCWNBFH-DS76VBEL.js +0 -1
  96. package/dist/assets/index-CBWbmG7W.js +0 -119
  97. package/dist/assets/stateDiagram-v2-6OUMAXLB-CzPQnlan.js +0 -1
  98. package/dist/assets/swimlanesDiagram-G3AALYLV-rIDv6EuQ.js +0 -8
  99. package/lib/connector-factory-shim.js +0 -167
  100. package/server/agent-mcp.js +0 -10
@@ -0,0 +1,149 @@
1
+ /**
2
+ * local-claude-connector.js — V2/V3 (STRAT-TS-FANOUT-CONSUMER).
3
+ *
4
+ * The TS `stratum_agent_run` surface is a SYNCHRONOUS black box: it returns no
5
+ * runId (no pre-completion cancel handle), streams no progress notifications,
6
+ * and its `sandboxMode` binds only the codex connector. The engine's background
7
+ * agent mode (surface 8) is codex-only AND read-only-only. So there is NO engine
8
+ * seam that can, for a CLAUDE agent:
9
+ * - enforce tool restrictions (V3 — a read-only review fanout must not Edit/
10
+ * Write/Bash in the target workspace), or
11
+ * - be interrupted mid-run (V2 — per-item timeout / stuck / user interrupt).
12
+ *
13
+ * Compose owns consumer/review execution by design, and already depends on
14
+ * `@anthropic-ai/claude-agent-sdk`, so CONTROLLED claude executions run here.
15
+ * The connector enforces allowedTools/disallowedTools, aborts via an
16
+ * AbortController, streams tool_use events (for the stuck detector + narration),
17
+ * and reports usage. The SDK `query` is injectable for tests.
18
+ */
19
+
20
+ import { query as sdkQuery } from '@anthropic-ai/claude-agent-sdk';
21
+
22
+ const SENSITIVE_ENV_VARS = ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'CLAUDE_API_KEY', 'CLAUDECODE'];
23
+
24
+ function isRecord(value) {
25
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
26
+ }
27
+
28
+ function nonneg(value) {
29
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : 0;
30
+ }
31
+
32
+ /**
33
+ * Run a controlled claude agent locally.
34
+ *
35
+ * @param {string} prompt
36
+ * @param {object} [opts]
37
+ * @param {string} [opts.cwd]
38
+ * @param {string} [opts.model]
39
+ * @param {string[]} [opts.allowedTools] enforced tool allowlist (read-only review)
40
+ * @param {string[]} [opts.disallowedTools]
41
+ * @param {object} [opts.thinking]
42
+ * @param {AbortController} [opts.abortController] abort → interrupt the run
43
+ * @param {(ev:{tool:string,input:object})=>void} [opts.onToolUse] per tool_use block
44
+ * @param {NodeJS.ProcessEnv} [opts.env]
45
+ * @param {Function} [opts.query] SDK `query` seam for tests
46
+ * @returns {Promise<{text:string, usage:object, telemetry:object}>}
47
+ */
48
+ export async function runLocalClaudeAgent(prompt, opts = {}) {
49
+ const query = opts.query ?? sdkQuery;
50
+ const env = { ...(opts.env ?? process.env) };
51
+ for (const key of SENSITIVE_ENV_VARS) delete env[key];
52
+
53
+ const sdkOptions = {
54
+ cwd: opts.cwd ?? process.cwd(),
55
+ model: opts.model ?? process.env.CLAUDE_MODEL ?? 'claude-sonnet-4-6',
56
+ permissionMode: 'acceptEdits',
57
+ env,
58
+ ...(opts.abortController ? { abortController: opts.abortController } : {}),
59
+ ...(opts.thinking !== undefined ? { thinking: opts.thinking } : {}),
60
+ };
61
+ // A read-only profile passes an explicit allowlist; without one, the agent
62
+ // gets the full claude_code preset (unrestricted).
63
+ if (opts.allowedTools !== undefined) {
64
+ // `allowedTools` only auto-allows-without-prompting; on its own the agent
65
+ // still HAS every tool (minus the denylist) under permissionMode
66
+ // 'acceptEdits'. To actually restrict AVAILABILITY (a read-only reviewer must
67
+ // not be able to Edit/Write/Bash), the SDK requires `tools` set to the
68
+ // specific tool names. Set both: `tools` binds availability, `allowedTools`
69
+ // suppresses the prompt for those same tools.
70
+ sdkOptions.tools = [...opts.allowedTools];
71
+ sdkOptions.allowedTools = opts.allowedTools;
72
+ if (opts.disallowedTools !== undefined) sdkOptions.disallowedTools = opts.disallowedTools;
73
+ } else {
74
+ sdkOptions.tools = { type: 'preset', preset: 'claude_code' };
75
+ if (opts.disallowedTools !== undefined) sdkOptions.disallowedTools = opts.disallowedTools;
76
+ }
77
+
78
+ const startedAt = Date.now();
79
+ let resolvedModel = sdkOptions.model;
80
+ let finalText;
81
+ let assistantText = '';
82
+ let durationMs = 0;
83
+ let inputTokens = 0;
84
+ let outputTokens = 0;
85
+ let costUsd = 0;
86
+
87
+ for await (const raw of query({ prompt, options: sdkOptions })) {
88
+ if (!isRecord(raw)) continue;
89
+ if (raw.type === 'system' && raw.subtype === 'init' && typeof raw.model === 'string') {
90
+ resolvedModel = raw.model;
91
+ }
92
+ if (raw.type === 'assistant' && isRecord(raw.message) && Array.isArray(raw.message.content)) {
93
+ for (const block of raw.message.content) {
94
+ if (!isRecord(block)) continue;
95
+ if (block.type === 'text' && typeof block.text === 'string') assistantText += block.text;
96
+ if (block.type === 'tool_use' && typeof block.name === 'string' && typeof opts.onToolUse === 'function') {
97
+ opts.onToolUse({ tool: block.name, input: isRecord(block.input) ? block.input : {} });
98
+ }
99
+ }
100
+ }
101
+ if (raw.type !== 'result') continue;
102
+ durationMs = nonneg(raw.duration_ms);
103
+ if (raw.subtype !== 'success') {
104
+ // F3: a failed run still consumed billable tokens/cost. Capture them from
105
+ // the error result (SDKResultError carries usage + total_cost_usd) and
106
+ // attach to the thrown Error — same usage shape as the success return — so
107
+ // the consumer failure path can debit the engine/GSD ledgers. Without this,
108
+ // repeated failures evade budget exhaustion.
109
+ const failCost = nonneg(raw.total_cost_usd);
110
+ const failIn = isRecord(raw.usage) ? nonneg(raw.usage.input_tokens) : 0;
111
+ const failOut = isRecord(raw.usage) ? nonneg(raw.usage.output_tokens) : 0;
112
+ const errors = Array.isArray(raw.errors) ? raw.errors.filter((v) => typeof v === 'string') : [];
113
+ const err = new Error(errors.join('; ') || `claude query failed: ${String(raw.subtype)}`);
114
+ err.usage = {
115
+ input_tokens: failIn,
116
+ output_tokens: failOut,
117
+ tokens: failIn + failOut,
118
+ cost_usd: failCost,
119
+ usd: failCost,
120
+ duration_ms: durationMs,
121
+ ms: durationMs,
122
+ model: resolvedModel,
123
+ };
124
+ err.costUsd = failCost;
125
+ throw err;
126
+ }
127
+ if (typeof raw.result === 'string') finalText = raw.result;
128
+ costUsd = nonneg(raw.total_cost_usd);
129
+ if (isRecord(raw.usage)) {
130
+ inputTokens = nonneg(raw.usage.input_tokens);
131
+ outputTokens = nonneg(raw.usage.output_tokens);
132
+ }
133
+ }
134
+
135
+ return {
136
+ text: finalText ?? assistantText,
137
+ usage: {
138
+ input_tokens: inputTokens,
139
+ output_tokens: outputTokens,
140
+ tokens: inputTokens + outputTokens,
141
+ cost_usd: costUsd,
142
+ usd: costUsd,
143
+ duration_ms: durationMs,
144
+ ms: durationMs,
145
+ model: resolvedModel,
146
+ },
147
+ telemetry: { durationMs, model: resolvedModel },
148
+ };
149
+ }