@smartmemory/compose 0.1.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 (181) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1014 -0
  3. package/bin/compose.js +1515 -0
  4. package/dist/assets/_baseUniq-CQwX6VLz.js +1 -0
  5. package/dist/assets/arc-SxJ2J1sh.js +1 -0
  6. package/dist/assets/architectureDiagram-Q4EWVU46-BykunY1F.js +36 -0
  7. package/dist/assets/blockDiagram-DXYQGD6D-ohAKBOUw.js +132 -0
  8. package/dist/assets/c4Diagram-AHTNJAMY-DBDC3ENB.js +10 -0
  9. package/dist/assets/channel-DGElom1e.js +1 -0
  10. package/dist/assets/chunk-4BX2VUAB-Cv93Z7uM.js +1 -0
  11. package/dist/assets/chunk-4TB4RGXK-DE0WBDkj.js +206 -0
  12. package/dist/assets/chunk-55IACEB6-CE1EXenG.js +1 -0
  13. package/dist/assets/chunk-EDXVE4YY-DA7Ana6H.js +1 -0
  14. package/dist/assets/chunk-FMBD7UC4-CTDIPA3p.js +15 -0
  15. package/dist/assets/chunk-OYMX7WX6-uGBaPaTX.js +231 -0
  16. package/dist/assets/chunk-QZHKN3VN-CYlnXuUO.js +1 -0
  17. package/dist/assets/chunk-YZCP3GAM-ojGkzcZK.js +1 -0
  18. package/dist/assets/classDiagram-6PBFFD2Q-KqWP9wWZ.js +1 -0
  19. package/dist/assets/classDiagram-v2-HSJHXN6E-KqWP9wWZ.js +1 -0
  20. package/dist/assets/clone-DUJKJXd7.js +1 -0
  21. package/dist/assets/cose-bilkent-S5V4N54A-Bktn9hL-.js +1 -0
  22. package/dist/assets/dagre-KV5264BT-DFaSzuRF.js +4 -0
  23. package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  24. package/dist/assets/diagram-5BDNPKRD-DnfmDzEm.js +10 -0
  25. package/dist/assets/diagram-G4DWMVQ6-Bm8W9YnG.js +24 -0
  26. package/dist/assets/diagram-MMDJMWI5-B5-TSKvp.js +43 -0
  27. package/dist/assets/diagram-TYMM5635-ls4rqlky.js +24 -0
  28. package/dist/assets/erDiagram-SMLLAGMA-giG6WO-r.js +85 -0
  29. package/dist/assets/flowDiagram-DWJPFMVM-XvlUuz-7.js +162 -0
  30. package/dist/assets/ganttDiagram-T4ZO3ILL-hLBV57oV.js +292 -0
  31. package/dist/assets/gitGraphDiagram-UUTBAWPF-BHu3s_Gn.js +106 -0
  32. package/dist/assets/graph-D0Cfv00Y.js +1 -0
  33. package/dist/assets/index-CUd6pFGF.css +1 -0
  34. package/dist/assets/index-DReRlzZI.js +1144 -0
  35. package/dist/assets/infoDiagram-42DDH7IO-DbqRsOo3.js +2 -0
  36. package/dist/assets/init-Gi6I4Gst.js +1 -0
  37. package/dist/assets/ishikawaDiagram-UXIWVN3A-DnCdx7zb.js +70 -0
  38. package/dist/assets/journeyDiagram-VCZTEJTY-CfD7eNcP.js +139 -0
  39. package/dist/assets/kanban-definition-6JOO6SKY-BYaO9-mK.js +89 -0
  40. package/dist/assets/katex-DkKDou_j.js +257 -0
  41. package/dist/assets/layout-Bj72wOEB.js +1 -0
  42. package/dist/assets/linear-BRFo114D.js +1 -0
  43. package/dist/assets/min-GCHnKlJS.js +1 -0
  44. package/dist/assets/mindmap-definition-QFDTVHPH-n0PMebY4.js +96 -0
  45. package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  46. package/dist/assets/pieDiagram-DEJITSTG-pN4CljHF.js +30 -0
  47. package/dist/assets/quadrantDiagram-34T5L4WZ-DNoAy8-D.js +7 -0
  48. package/dist/assets/requirementDiagram-MS252O5E-BhtY05PT.js +84 -0
  49. package/dist/assets/sankeyDiagram-XADWPNL6-B6AD-16A.js +10 -0
  50. package/dist/assets/sequenceDiagram-FGHM5R23-DShHM-uk.js +157 -0
  51. package/dist/assets/stateDiagram-FHFEXIEX-DMxn7HTo.js +1 -0
  52. package/dist/assets/stateDiagram-v2-QKLJ7IA2-o6PnCs4e.js +1 -0
  53. package/dist/assets/timeline-definition-GMOUNBTQ-Cdu6uq52.js +120 -0
  54. package/dist/assets/vennDiagram-DHZGUBPP-CpK29iRe.js +34 -0
  55. package/dist/assets/wardley-RL74JXVD-BQgSkdcO.js +162 -0
  56. package/dist/assets/wardleyDiagram-NUSXRM2D-DJHYev6O.js +20 -0
  57. package/dist/assets/xychartDiagram-5P7HB3ND-1d75pbaO.js +7 -0
  58. package/dist/index.html +30 -0
  59. package/lib/agent-chains.js +65 -0
  60. package/lib/agent-string.js +86 -0
  61. package/lib/budget-ledger.js +86 -0
  62. package/lib/build-all.js +162 -0
  63. package/lib/build-dag.js +120 -0
  64. package/lib/build-stream-writer.js +190 -0
  65. package/lib/build.js +2997 -0
  66. package/lib/capability-checker.js +53 -0
  67. package/lib/cert-inject.js +38 -0
  68. package/lib/cli-progress.js +483 -0
  69. package/lib/constants.js +69 -0
  70. package/lib/cross-layer-audit.js +84 -0
  71. package/lib/debug-discipline.js +173 -0
  72. package/lib/feature-json.js +106 -0
  73. package/lib/gate-prompt.js +291 -0
  74. package/lib/gate-tiers.js +194 -0
  75. package/lib/health-history.js +119 -0
  76. package/lib/health-score.js +227 -0
  77. package/lib/ideabox.js +570 -0
  78. package/lib/import.js +244 -0
  79. package/lib/migrate-roadmap.js +94 -0
  80. package/lib/model-pricing.js +67 -0
  81. package/lib/new.js +413 -0
  82. package/lib/pipeline-cli.js +489 -0
  83. package/lib/plan-parser.js +103 -0
  84. package/lib/qa-scoping.js +474 -0
  85. package/lib/questionnaire.js +200 -0
  86. package/lib/resolve-port.js +7 -0
  87. package/lib/result-normalizer.js +349 -0
  88. package/lib/review-lenses.js +166 -0
  89. package/lib/roadmap-gen.js +210 -0
  90. package/lib/roadmap-parser.js +176 -0
  91. package/lib/server-probe.js +23 -0
  92. package/lib/staleness.js +87 -0
  93. package/lib/step-prompt.js +260 -0
  94. package/lib/step-validator.js +49 -0
  95. package/lib/stratum-mcp-client.js +365 -0
  96. package/lib/team-flag.js +46 -0
  97. package/lib/test-bootstrap.js +401 -0
  98. package/lib/triage.js +274 -0
  99. package/lib/vision-writer.js +391 -0
  100. package/package.json +111 -0
  101. package/pipelines/bug-fix.stratum.yaml +230 -0
  102. package/pipelines/build.stratum.yaml +498 -0
  103. package/pipelines/content.stratum.yaml +112 -0
  104. package/pipelines/coverage-sweep.stratum.yaml +52 -0
  105. package/pipelines/refactor.stratum.yaml +169 -0
  106. package/pipelines/research.stratum.yaml +88 -0
  107. package/pipelines/review-fix.stratum.yaml +109 -0
  108. package/presets/team-feature.stratum.yaml +105 -0
  109. package/presets/team-research.stratum.yaml +108 -0
  110. package/presets/team-review.stratum.yaml +106 -0
  111. package/scripts/agent-activity-hook.sh +31 -0
  112. package/scripts/agent-error-hook.sh +28 -0
  113. package/scripts/analyze-orphans.mjs +50 -0
  114. package/scripts/find-orphans.mjs +26 -0
  115. package/scripts/fix-phases.mjs +49 -0
  116. package/scripts/generate-stratum-spec.mjs +137 -0
  117. package/scripts/import-roadmap.mjs +116 -0
  118. package/scripts/phase-audit.mjs +33 -0
  119. package/scripts/run-pipeline.mjs +314 -0
  120. package/scripts/session-end-hook.sh +18 -0
  121. package/scripts/session-start-hook.sh +38 -0
  122. package/scripts/vision-hook.sh +104 -0
  123. package/scripts/vision-track.mjs +554 -0
  124. package/scripts/wire-all-orphans.mjs +108 -0
  125. package/scripts/wire-orphans.mjs +164 -0
  126. package/server/activity-routes.js +123 -0
  127. package/server/agent-health.js +197 -0
  128. package/server/agent-hooks.js +102 -0
  129. package/server/agent-mcp.js +10 -0
  130. package/server/agent-registry.js +95 -0
  131. package/server/agent-server.js +290 -0
  132. package/server/agent-spawn.js +251 -0
  133. package/server/agent-templates.js +77 -0
  134. package/server/artifact-manager.js +247 -0
  135. package/server/artifact-templates/architecture.md +28 -0
  136. package/server/artifact-templates/blueprint.md +21 -0
  137. package/server/artifact-templates/design.md +36 -0
  138. package/server/artifact-templates/plan.md +25 -0
  139. package/server/artifact-templates/prd.md +43 -0
  140. package/server/artifact-templates/report.md +40 -0
  141. package/server/block-tracker.js +90 -0
  142. package/server/build-stream-bridge.js +502 -0
  143. package/server/coalescing-buffer.js +46 -0
  144. package/server/compose-mcp-tools.js +479 -0
  145. package/server/compose-mcp.js +324 -0
  146. package/server/connectors/agent-connector.js +78 -0
  147. package/server/connectors/claude-sdk-connector.js +198 -0
  148. package/server/connectors/codex-connector.js +240 -0
  149. package/server/connectors/connector-discovery.js +18 -0
  150. package/server/connectors/connector-runtime.js +13 -0
  151. package/server/connectors/opencode-connector.js +200 -0
  152. package/server/design-routes.js +540 -0
  153. package/server/design-session.js +161 -0
  154. package/server/feature-scan.js +593 -0
  155. package/server/file-watcher.js +284 -0
  156. package/server/find-root.js +29 -0
  157. package/server/graph-export.js +343 -0
  158. package/server/ideabox-cache.js +77 -0
  159. package/server/ideabox-routes.js +294 -0
  160. package/server/index.js +156 -0
  161. package/server/model-tiers.js +49 -0
  162. package/server/pipeline-routes.js +288 -0
  163. package/server/policy-evaluator.js +36 -0
  164. package/server/project-root.js +122 -0
  165. package/server/security.js +23 -0
  166. package/server/session-manager.js +403 -0
  167. package/server/session-routes.js +190 -0
  168. package/server/session-store.js +107 -0
  169. package/server/settings-routes.js +35 -0
  170. package/server/settings-store.js +234 -0
  171. package/server/stratum-api.js +102 -0
  172. package/server/stratum-client.js +192 -0
  173. package/server/stratum-sync.js +193 -0
  174. package/server/summarizer.js +139 -0
  175. package/server/supervisor.js +196 -0
  176. package/server/vision-routes.js +668 -0
  177. package/server/vision-server.js +393 -0
  178. package/server/vision-store.js +360 -0
  179. package/server/vision-utils.js +179 -0
  180. package/server/worktree-gc.js +137 -0
  181. package/templates/ROADMAP.md +46 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * build-dag.js — Build a dependency DAG from roadmap feature entries.
3
+ *
4
+ * Dependencies are positional:
5
+ * - Items within the same phase depend on the previous item (sequential chain)
6
+ * - The first item of phase N depends on the last item of phase N-1 (cross-phase edge)
7
+ */
8
+
9
+ /**
10
+ * @typedef {{ code: string, deps: string[] }} DagNode
11
+ */
12
+
13
+ /**
14
+ * Build a DAG from roadmap entries.
15
+ *
16
+ * @param {import('./roadmap-parser.js').FeatureEntry[]} entries - Full ordered list from parseRoadmap()
17
+ * @returns {DagNode[]}
18
+ */
19
+ export function buildDag(entries) {
20
+ if (entries.length === 0) return [];
21
+
22
+ // Deduplicate by code — keep first occurrence only
23
+ const seen = new Set();
24
+ const unique = [];
25
+ for (const entry of entries) {
26
+ if (!seen.has(entry.code)) {
27
+ seen.add(entry.code);
28
+ unique.push(entry);
29
+ }
30
+ }
31
+
32
+ // Group by phaseId preserving encounter order
33
+ const phases = new Map();
34
+ for (const entry of unique) {
35
+ if (!phases.has(entry.phaseId)) {
36
+ phases.set(entry.phaseId, []);
37
+ }
38
+ phases.get(entry.phaseId).push(entry);
39
+ }
40
+
41
+ // Build adjacency: code → Set<depCode>
42
+ const deps = new Map();
43
+ for (const entry of unique) {
44
+ deps.set(entry.code, new Set());
45
+ }
46
+
47
+ let lastPhaseLastCode = null;
48
+
49
+ for (const [, phaseEntries] of phases) {
50
+ let prevCode = null;
51
+
52
+ for (const entry of phaseEntries) {
53
+ // Cross-phase edge: first item depends on last item of previous phase
54
+ if (prevCode === null && lastPhaseLastCode !== null) {
55
+ deps.get(entry.code).add(lastPhaseLastCode);
56
+ }
57
+
58
+ // Within-phase sequential chain
59
+ if (prevCode !== null) {
60
+ deps.get(entry.code).add(prevCode);
61
+ }
62
+
63
+ prevCode = entry.code;
64
+ }
65
+
66
+ lastPhaseLastCode = prevCode;
67
+ }
68
+
69
+ return unique.map(e => ({
70
+ code: e.code,
71
+ deps: [...deps.get(e.code)],
72
+ }));
73
+ }
74
+
75
+ /**
76
+ * Topological sort via Kahn's algorithm.
77
+ * Returns feature codes in build order (dependencies first).
78
+ *
79
+ * @param {DagNode[]} nodes
80
+ * @returns {string[]}
81
+ * @throws {Error} if a cycle is detected
82
+ */
83
+ export function topoSort(nodes) {
84
+ const inDegree = new Map();
85
+ const successors = new Map();
86
+
87
+ for (const node of nodes) {
88
+ if (!inDegree.has(node.code)) inDegree.set(node.code, 0);
89
+ if (!successors.has(node.code)) successors.set(node.code, []);
90
+
91
+ for (const dep of node.deps) {
92
+ if (!inDegree.has(dep)) inDegree.set(dep, 0);
93
+ if (!successors.has(dep)) successors.set(dep, []);
94
+ successors.get(dep).push(node.code);
95
+ inDegree.set(node.code, inDegree.get(node.code) + 1);
96
+ }
97
+ }
98
+
99
+ const queue = [];
100
+ for (const [code, degree] of inDegree) {
101
+ if (degree === 0) queue.push(code);
102
+ }
103
+
104
+ const order = [];
105
+ while (queue.length > 0) {
106
+ const code = queue.shift();
107
+ order.push(code);
108
+ for (const succ of successors.get(code) ?? []) {
109
+ const newDegree = inDegree.get(succ) - 1;
110
+ inDegree.set(succ, newDegree);
111
+ if (newDegree === 0) queue.push(succ);
112
+ }
113
+ }
114
+
115
+ if (order.length !== inDegree.size) {
116
+ throw new Error('Cycle detected in feature dependency graph');
117
+ }
118
+
119
+ return order;
120
+ }
@@ -0,0 +1,190 @@
1
+ /**
2
+ * BuildStreamWriter — appends JSONL events to .compose/build-stream.jsonl
3
+ *
4
+ * Used by build.js to emit build lifecycle events that the agent-server's
5
+ * BuildStreamBridge tails and rebroadcasts via SSE.
6
+ *
7
+ * Sync I/O is intentional — JSONL lines are small and the CLI is already
8
+ * I/O-bound on agent calls between writes.
9
+ */
10
+
11
+ import { mkdirSync, appendFileSync, unlinkSync, existsSync, readFileSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+
14
+ export class BuildStreamWriter {
15
+ #path;
16
+ #seq = 0;
17
+ #featureCode;
18
+ #closed = false;
19
+
20
+ /**
21
+ * @param {string} composeDir Path to .compose directory
22
+ * @param {string} featureCode Feature code (e.g. 'STRAT-COMP-7')
23
+ * @param {object} [opts]
24
+ * @param {boolean} [opts.truncate=false] Truncate existing stream (fresh builds only)
25
+ */
26
+ constructor(composeDir, featureCode, { truncate = false } = {}) {
27
+ mkdirSync(composeDir, { recursive: true });
28
+ this.#path = join(composeDir, 'build-stream.jsonl');
29
+ this.#featureCode = featureCode;
30
+
31
+ // Only truncate on fresh builds — resumed builds append to existing stream
32
+ if (truncate && existsSync(this.#path)) {
33
+ unlinkSync(this.#path);
34
+ }
35
+
36
+ // On resume: read the last _seq from the existing JSONL so new events
37
+ // have monotonically increasing _seq values. The SSE bridge deduplicates
38
+ // on _seq, so restarting from 0 would cause all resumed events to be dropped.
39
+ if (!truncate && existsSync(this.#path)) {
40
+ try {
41
+ const content = readFileSync(this.#path, 'utf-8').trimEnd();
42
+ if (content) {
43
+ const lastLine = content.slice(content.lastIndexOf('\n') + 1);
44
+ const lastEvent = JSON.parse(lastLine);
45
+ if (typeof lastEvent._seq === 'number') {
46
+ this.#seq = lastEvent._seq + 1;
47
+ }
48
+ }
49
+ } catch {
50
+ // Corrupt file — start from 0, bridge will handle duplicates
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Append a JSONL event with auto-incremented _seq and _ts fields.
57
+ * @param {object} event Event payload (must include `type`)
58
+ */
59
+ write(event) {
60
+ const line = JSON.stringify({
61
+ ...event,
62
+ _seq: this.#seq++,
63
+ _ts: Date.now(),
64
+ });
65
+ appendFileSync(this.#path, line + '\n');
66
+ }
67
+
68
+ /**
69
+ * Emit a capability_profile event noting the active template for a step.
70
+ * Informational only — never blocks or fails the build.
71
+ *
72
+ * @param {string} stepId Step ID
73
+ * @param {string} agent Full agent string, e.g. "claude:read-only-reviewer"
74
+ * @param {string|null} templateName Template name, or null if no template
75
+ * @param {string[]|null} allowedTools Allowed tools list from template
76
+ * @param {string[]|null} disallowedTools Disallowed tools list from template
77
+ */
78
+ writeCapabilityProfile(stepId, agent, templateName, allowedTools, disallowedTools) {
79
+ this.write({
80
+ type: 'capability_profile',
81
+ stepId,
82
+ agent,
83
+ template: templateName,
84
+ allowedTools,
85
+ disallowedTools,
86
+ });
87
+ }
88
+
89
+ /**
90
+ * Emit a capability_violation event for informational audit.
91
+ * Violations are never blocking in v1.
92
+ *
93
+ * @param {string} stepId Step ID where the violation was detected
94
+ * @param {string} agent Full agent string
95
+ * @param {string} templateName Active template name
96
+ * @param {string} detail Description of the violation
97
+ */
98
+ writeViolation(stepId, agent, templateName, detail) {
99
+ this.write({
100
+ type: 'capability_violation',
101
+ stepId,
102
+ agent,
103
+ template: templateName,
104
+ detail,
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Emit a per-step usage event with token and cost data (COMP-OBS-COST).
110
+ *
111
+ * @param {string} stepId Step ID this usage belongs to
112
+ * @param {object} usage Usage object from result-normalizer
113
+ * @param {number} usage.input_tokens
114
+ * @param {number} usage.output_tokens
115
+ * @param {number} [usage.cache_creation_input_tokens]
116
+ * @param {number} [usage.cache_read_input_tokens]
117
+ * @param {number} usage.cost_usd
118
+ * @param {string|null} [usage.model]
119
+ */
120
+ writeUsage(stepId, usage) {
121
+ this.write({
122
+ type: 'step_usage',
123
+ stepId,
124
+ input_tokens: usage.input_tokens ?? 0,
125
+ output_tokens: usage.output_tokens ?? 0,
126
+ cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0,
127
+ cache_read_input_tokens: usage.cache_read_input_tokens ?? 0,
128
+ cost_usd: usage.cost_usd ?? 0,
129
+ model: usage.model ?? null,
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Emit a gate_tier_result event for a step's tier classification result (COMP-OBS-GATES).
135
+ *
136
+ * @param {string} stepId Pipeline step ID (e.g. 'review', 'coverage_check')
137
+ * @param {string} tierId Tier ID (e.g. 'T3')
138
+ * @param {boolean} passed Whether this tier passed
139
+ * @param {string|null} details Optional summary / detail string
140
+ */
141
+ writeGateTier(stepId, tierId, passed, details = null) {
142
+ this.write({
143
+ type: 'gate_tier_result',
144
+ stepId,
145
+ tierId,
146
+ passed,
147
+ details,
148
+ });
149
+ }
150
+
151
+ /**
152
+ * Emit a health_score event with the composite score and dimension breakdown.
153
+ * COMP-HEALTH item 118: emitted after build_end so consumers can display it.
154
+ *
155
+ * @param {number} score Composite score 0-100
156
+ * @param {object} breakdown Per-dimension scores { dim: number }
157
+ * @param {string[]} [missing] Dimensions not scored (no signal available)
158
+ */
159
+ writeHealthScore(score, breakdown, missing = []) {
160
+ this.write({
161
+ type: 'health_score',
162
+ score,
163
+ breakdown,
164
+ missing,
165
+ });
166
+ }
167
+
168
+ /**
169
+ * Write a build_end sentinel and mark the writer as closed.
170
+ * Idempotent — calling multiple times writes exactly one build_end.
171
+ * @param {string} [status='complete'] Build exit status
172
+ * @param {object} [costTotals] Optional cumulative cost/token totals
173
+ */
174
+ close(status = 'complete', costTotals = null) {
175
+ if (this.#closed) return;
176
+ this.#closed = true;
177
+ const payload = { type: 'build_end', status, featureCode: this.#featureCode };
178
+ if (costTotals) {
179
+ payload.total_input_tokens = costTotals.input_tokens ?? 0;
180
+ payload.total_output_tokens = costTotals.output_tokens ?? 0;
181
+ payload.total_cost_usd = costTotals.cost_usd ?? 0;
182
+ }
183
+ this.write(payload);
184
+ }
185
+
186
+ /** @returns {string} Absolute path to the JSONL file */
187
+ get filePath() {
188
+ return this.#path;
189
+ }
190
+ }