@smartmemory/compose 0.3.7 → 0.3.8
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.
- package/.compose-deps.json +1 -13
- package/README.md +72 -5
- package/bin/compose.js +470 -351
- package/bin/judgment-migrate.js +387 -0
- package/contracts/comp-obs-contract.schema.json +9 -3
- package/contracts/fluid-record.schema.json +209 -0
- package/contracts/lifecycle-backfill.schema.json +322 -0
- package/dist/assets/App-Z4MU-H_F.js +916 -0
- package/dist/assets/{_baseUniq-Bo837sRJ.js → _baseUniq-ClWoCPFl.js} +1 -1
- package/dist/assets/{arc-BafGpyqE.js → arc-DY26UIVo.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-BOBfUsqL.js → architectureDiagram-Q4EWVU46-6Ggq4DqJ.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-Dwodev1a.js → blockDiagram-DXYQGD6D-CH3Ked0l.js} +1 -1
- package/dist/assets/{browser-1ntj1-x_.js → browser-BWkrenen.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-CU_bhYag.js → c4Diagram-AHTNJAMY-Bk8dYilu.js} +1 -1
- package/dist/assets/channel-SnZzzh7k.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-p8WsDwnO.js → chunk-4BX2VUAB-BMR0XaAQ.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-B8h7-eR0.js → chunk-4TB4RGXK-JytR14a9.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DxeEr98s.js → chunk-55IACEB6-B4Q97BCP.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-BYt8F151.js → chunk-EDXVE4YY-R_qarkSf.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DGSOVeie.js → chunk-FMBD7UC4-C9s7KR9m.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-B-QdgYR2.js → chunk-OYMX7WX6-BySQzVxc.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-Du5UAZLs.js → chunk-QZHKN3VN-DdpSYZsW.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-C8JbNBSk.js → chunk-YZCP3GAM-iE_tzriw.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-CBu92dSH.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-CBu92dSH.js +1 -0
- package/dist/assets/clone-DgklGjHm.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-O1ESaqge.js → cose-bilkent-S5V4N54A-BdlU6ZX_.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-CPTmFPHw.js → dagre-KV5264BT-Cp3F5KTn.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-B3PNrWs5.js → diagram-5BDNPKRD-DiR6_2q_.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-Cscfr6vc.js → diagram-G4DWMVQ6-w0i-p5HX.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-CSfqZ-TM.js → diagram-MMDJMWI5-tIHhwUv3.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-Cg4aYS7W.js → diagram-TYMM5635-BAeY3B19.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-_ZqwG5pl.js → erDiagram-SMLLAGMA-Ckx_Knko.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-C83boxFT.js → flowDiagram-DWJPFMVM-DeoNka6J.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-CWnIjuEi.js → ganttDiagram-T4ZO3ILL-BmGnFbEg.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-DrMdxZfH.js → gitGraphDiagram-UUTBAWPF-Dk48IHsx.js} +1 -1
- package/dist/assets/{graph-RE4I7Ty7.js → graph-BNzKGvoy.js} +1 -1
- package/dist/assets/{graph-Bi99_6Yf.js → graph-CI_1htl0.js} +1 -1
- package/dist/assets/{index-Rm2RE-c0.js → index-BEfrNBp8.js} +3 -3
- package/dist/assets/index-yyrA5OZd.css +1 -0
- package/dist/assets/{infoDiagram-42DDH7IO-BLmP4Epr.js → infoDiagram-42DDH7IO-BRf827i0.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-yuWWshKN.js → ishikawaDiagram-UXIWVN3A-0kCZaeCM.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-BOfhaJov.js → journeyDiagram-VCZTEJTY-rvU7ayRt.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-Bbolde15.js → kanban-definition-6JOO6SKY-DpQwX1C5.js} +1 -1
- package/dist/assets/{layout-BSf33zm8.js → layout-BI8cXFPI.js} +1 -1
- package/dist/assets/{linear-AvSTWMqx.js → linear-a0glcDiw.js} +1 -1
- package/dist/assets/{min-QBM8H4xN.js → min-vPHfnXcC.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-BuvgtqIc.js → mindmap-definition-QFDTVHPH-D14eF-7C.js} +1 -1
- package/dist/assets/mobile-B7m9EO9D.js +17 -0
- package/dist/assets/{pieDiagram-DEJITSTG-DIzF16vh.js → pieDiagram-DEJITSTG-Cno-gETh.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-D-mbUIjS.js → quadrantDiagram-34T5L4WZ-BUQM1Hfm.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-CEs4kCLd.js → requirementDiagram-MS252O5E-pOXlN2-q.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-DFsnCr9n.js → sankeyDiagram-XADWPNL6-Crynd3_b.js} +1 -1
- package/dist/assets/{sequenceDiagram-FGHM5R23-BEJYdTjQ.js → sequenceDiagram-FGHM5R23-D9fZdCM8.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-BBXs57uY.js → stateDiagram-FHFEXIEX-CW9qVec8.js} +1 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-DkVLzHbY.js +1 -0
- package/dist/assets/{timeline-definition-GMOUNBTQ-BGvLoVAY.js → timeline-definition-GMOUNBTQ-BcHzhm_8.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-9LaBTMe0.js → vennDiagram-DHZGUBPP-BfytJcWk.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-P4MEqMTP.js → wardley-RL74JXVD-DLj-IjyB.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-o-tmxnlC.js → wardleyDiagram-NUSXRM2D-Ds0Ue68c.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-Dpn7V6qk.js → xychartDiagram-5P7HB3ND-vjWDXFL6.js} +1 -1
- package/dist/index.html +3 -3
- package/lib/agent-string.js +7 -5
- package/lib/append-integrity.js +81 -0
- package/lib/backfill-evidence.js +109 -0
- package/lib/bug-escalation.js +9 -0
- package/lib/build-stream-schema.js +3 -1
- package/lib/build-stream-writer.js +25 -0
- package/lib/build.js +874 -170
- package/lib/canon-guard.js +28 -6
- package/lib/canon-override.js +196 -0
- package/lib/canon-registry.js +104 -0
- package/lib/cli-commands.js +144 -0
- package/lib/codex-preflight.js +26 -13
- package/lib/colleague/context.js +215 -0
- package/lib/colleague/writeback.js +95 -0
- package/lib/completion-gate.js +1421 -0
- package/lib/completion-writer.js +47 -47
- package/lib/consumer-fanout.js +105 -11
- package/lib/coverage-gate.js +200 -0
- package/lib/dir-lock.js +170 -0
- package/lib/dispatch-ledger.js +3 -3
- package/lib/feature-json.js +1 -1
- package/lib/feature-reconciler.js +8 -0
- package/lib/feature-validator.js +64 -1
- package/lib/feature-writer.js +57 -2
- package/lib/fluid/factory.js +167 -0
- package/lib/fluid/ideabox-dates.js +73 -0
- package/lib/fluid/ideabox-migrate.js +154 -0
- package/lib/fluid/ideabox-ops.js +585 -0
- package/lib/fluid/ideabox-view.js +146 -0
- package/lib/fluid/import-ideabox.js +186 -0
- package/lib/fluid/local-provider.js +606 -0
- package/lib/fluid/provider.js +684 -0
- package/lib/fluid/record-shape.js +214 -0
- package/lib/fluid/record-store.js +328 -0
- package/lib/fluid/render-ideabox.js +261 -0
- package/lib/fluid/schema.js +40 -0
- package/lib/fluid/smartmemory-provider.js +1695 -0
- package/lib/gsd.js +63 -23
- package/lib/guard-cli.js +175 -0
- package/lib/guard-custody.js +141 -0
- package/lib/guard-descriptors.js +530 -0
- package/lib/guard-enrol.js +254 -0
- package/lib/health-score.js +1 -1
- package/lib/ideabox-cli.js +315 -0
- package/lib/ideabox.js +121 -21
- package/lib/judgment/store/index.js +9 -1
- package/lib/judgment/store/records.js +1 -1
- package/lib/judgment/trace.js +380 -0
- package/lib/judgment-decision-write.js +277 -0
- package/lib/judgment-decisions.js +466 -0
- package/lib/judgment-gen.js +5 -1
- package/lib/judgment-writer.js +56 -2
- package/lib/lifecycle-modes.js +4 -4
- package/lib/lineage.js +400 -0
- package/lib/local-claude-connector.js +52 -1
- package/lib/maya-client.js +302 -0
- package/lib/maya-config.js +53 -0
- package/lib/maya-identity.js +283 -0
- package/lib/migrate-anon.js +5 -0
- package/lib/migrate-roadmap.js +15 -0
- package/lib/new.js +13 -1
- package/lib/pipeline-compat.js +104 -0
- package/lib/policy-catalog.js +295 -0
- package/lib/policy-check.js +0 -0
- package/lib/process-termination.js +98 -0
- package/lib/resolve-workspace.js +5 -1
- package/lib/result-normalizer.js +396 -199
- package/lib/roadmap-errors.js +65 -0
- package/lib/roadmap-preservers.js +24 -4
- package/lib/roadmap-residue.js +299 -0
- package/lib/smartmemory-client.js +614 -78
- package/lib/smartmemory-config.js +54 -0
- package/lib/smartmemory-ingest.js +19 -2
- package/lib/step-prompt.js +7 -6
- package/lib/stratum-engine.js +53 -4
- package/lib/stratum-mcp-client.js +271 -36
- package/lib/test-bootstrap.js +31 -0
- package/lib/tool-inventory.js +122 -0
- package/lib/version-check.js +91 -19
- package/lib/vision-writer.js +88 -1
- package/package.json +7 -6
- package/pipelines/bug-fix.stratum.yaml +205 -211
- package/pipelines/build-quick.profiles.json +12 -0
- package/pipelines/build-quick.stratum.yaml +263 -350
- package/pipelines/content.stratum.yaml +81 -77
- package/pipelines/coverage-sweep.stratum.yaml +49 -30
- package/pipelines/plan.stratum.yaml +76 -86
- package/pipelines/refactor.stratum.yaml +125 -125
- package/pipelines/research.stratum.yaml +56 -58
- package/pipelines/review-fix.profiles.json +6 -0
- package/pipelines/review-fix.stratum.yaml +110 -83
- package/presets/team-feature.profiles.json +6 -0
- package/presets/team-feature.stratum.yaml +93 -66
- package/presets/team-research.profiles.json +6 -0
- package/presets/team-research.stratum.yaml +89 -80
- package/presets/team-review.profiles.json +8 -0
- package/presets/team-review.stratum.yaml +98 -80
- package/scripts/cost-census.mjs +70 -0
- package/scripts/guard-sign/compose-guard-sign.sh +62 -0
- package/server/agent-health.js +22 -0
- package/server/agent-hooks.js +14 -1
- package/server/agent-server.js +5 -248
- package/server/agent-spawn.js +3 -4
- package/server/agent-workspace.js +294 -0
- package/server/build-routes.js +6 -5
- package/server/build-stream-bridge.js +53 -0
- package/server/cc-session-watcher.js +4 -1
- package/server/coalescing-buffer.js +7 -1
- package/server/completion-projection.js +228 -0
- package/server/compose-mcp-tools.js +109 -23
- package/server/compose-mcp.js +88 -882
- package/server/decision-event-emit.js +41 -2
- package/server/decision-event-id.js +17 -0
- package/server/decision-events-snapshot.js +3 -0
- package/server/design-routes.js +14 -8
- package/server/feature-scan.js +76 -2
- package/server/file-watcher.js +170 -21
- package/server/ideabox-routes.js +166 -224
- package/server/index.js +70 -100
- package/server/lifecycle-guard.js +240 -10
- package/server/lifecycle-phase-history.js +276 -0
- package/server/maya-routes.js +507 -0
- package/server/mcp-tool-defs.js +940 -0
- package/server/mcp-tool-policy.js +34 -2
- package/server/model-tiers.js +22 -5
- package/server/pipeline-routes.js +21 -11
- package/server/project-root.js +58 -19
- package/server/remote-utils.js +3 -1
- package/server/schema-validator.js +7 -1
- package/server/session-manager.js +5 -6
- package/server/session-routes.js +3 -1
- package/server/stratum-client.js +57 -10
- package/server/stratum-sync.js +6 -3
- package/server/summarizer.js +3 -4
- package/server/supervisor.js +0 -1
- package/server/vision-routes.js +208 -98
- package/server/vision-server.js +86 -23
- package/server/vision-store.js +60 -6
- package/server/vision-utils.js +3 -4
- package/server/workspace-activity.js +18 -0
- package/server/workspace-middleware.js +2 -2
- package/server/workspace-runtime.js +243 -0
- package/server/worktree-gc.js +1 -0
- package/dist/assets/App-PkZzHeMj.js +0 -894
- package/dist/assets/channel-qVK_qn4E.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-B8UcfC1q.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-B8UcfC1q.js +0 -1
- package/dist/assets/clone-Pu3RyLUh.js +0 -1
- package/dist/assets/index-LIwREYgH.css +0 -1
- package/dist/assets/mobile-BnXEOE3U.js +0 -17
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-BqKuX4rj.js +0 -1
- package/lib/staleness.js +0 -87
- package/server/ideabox-cache.js +0 -77
package/server/compose-mcp.js
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
toolGetFeatureLifecycle,
|
|
38
38
|
toolKillFeature,
|
|
39
39
|
toolCompleteFeature,
|
|
40
|
+
toolBackfillCompletion,
|
|
40
41
|
toolAssessFeatureArtifacts,
|
|
41
42
|
toolScaffoldFeature,
|
|
42
43
|
toolApproveGate,
|
|
@@ -54,6 +55,7 @@ import {
|
|
|
54
55
|
toolGetFeatureLinks,
|
|
55
56
|
toolProposeFollowup,
|
|
56
57
|
toolAddChangelogEntry,
|
|
58
|
+
toolCanonOverrideGrant,
|
|
57
59
|
toolGetChangelogEntries,
|
|
58
60
|
toolWriteJournalEntry,
|
|
59
61
|
toolGetJournalEntries,
|
|
@@ -77,6 +79,7 @@ import {
|
|
|
77
79
|
toolJudgmentSituationWrite,
|
|
78
80
|
toolJudgmentGoalWrite,
|
|
79
81
|
toolGetJudgmentState,
|
|
82
|
+
toolGetJudgmentTrace,
|
|
80
83
|
_getBinding,
|
|
81
84
|
assertToolPhaseAllowed,
|
|
82
85
|
_getSessionProfile,
|
|
@@ -85,814 +88,14 @@ import {
|
|
|
85
88
|
EAGER_PRELOAD_MODULES,
|
|
86
89
|
} from './compose-mcp-tools.js';
|
|
87
90
|
import { isToolAllowed } from './mcp-tool-policy.js';
|
|
88
|
-
import {
|
|
91
|
+
import { prepareProject, withProjectContext, getTargetRoot, loadProjectConfig } from './project-root.js';
|
|
89
92
|
import { resolveWorkspace } from '../lib/resolve-workspace.js';
|
|
90
93
|
|
|
91
94
|
// ---------------------------------------------------------------------------
|
|
92
95
|
// Tool definitions
|
|
93
96
|
// ---------------------------------------------------------------------------
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
name: 'get_vision_items',
|
|
98
|
-
description: 'Query Compose tracker items. Filter by phase, status, type, or keyword. Returns id, title, type, phase, status, confidence, description.',
|
|
99
|
-
inputSchema: {
|
|
100
|
-
type: 'object',
|
|
101
|
-
properties: {
|
|
102
|
-
phase: {
|
|
103
|
-
type: 'string',
|
|
104
|
-
description: 'Filter by phase: vision, requirements, design, planning, implementation, verification, release',
|
|
105
|
-
},
|
|
106
|
-
status: {
|
|
107
|
-
type: 'string',
|
|
108
|
-
description: 'Filter by status (comma-separated for multiple): planned, in_progress, complete, blocked, parked, killed',
|
|
109
|
-
},
|
|
110
|
-
type: {
|
|
111
|
-
type: 'string',
|
|
112
|
-
description: 'Filter by type: task, decision, evaluation, idea, spec, thread, artifact, question, feature, track',
|
|
113
|
-
},
|
|
114
|
-
keyword: {
|
|
115
|
-
type: 'string',
|
|
116
|
-
description: 'Search keyword matched against title and description',
|
|
117
|
-
},
|
|
118
|
-
limit: {
|
|
119
|
-
type: 'number',
|
|
120
|
-
description: 'Max results to return (default 30)',
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
name: 'get_item_detail',
|
|
127
|
-
description: 'Get full detail for a single tracker item including all its connections.',
|
|
128
|
-
inputSchema: {
|
|
129
|
-
type: 'object',
|
|
130
|
-
properties: {
|
|
131
|
-
id: {
|
|
132
|
-
type: 'string',
|
|
133
|
-
description: 'Item ID (UUID) or semanticId/slug',
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
required: ['id'],
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
name: 'get_phase_summary',
|
|
141
|
-
description: 'Get status and type distribution for a phase (or all phases). Useful for understanding overall project health.',
|
|
142
|
-
inputSchema: {
|
|
143
|
-
type: 'object',
|
|
144
|
-
properties: {
|
|
145
|
-
phase: {
|
|
146
|
-
type: 'string',
|
|
147
|
-
description: 'Phase to summarize: vision, requirements, design, planning, implementation, verification, release. Omit for all phases.',
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
name: 'get_blocked_items',
|
|
154
|
-
description: 'List all tracker items that are blocked by non-complete items.',
|
|
155
|
-
inputSchema: {
|
|
156
|
-
type: 'object',
|
|
157
|
-
properties: {},
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
name: 'get_current_session',
|
|
162
|
-
description: 'Get the most recent session: tool count, items touched, error count, and recent Haiku summaries of what was accomplished.',
|
|
163
|
-
inputSchema: {
|
|
164
|
-
type: 'object',
|
|
165
|
-
properties: {
|
|
166
|
-
featureCode: { type: 'string', description: 'Optional: get context for a specific feature' },
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
name: 'bind_session',
|
|
172
|
-
description: 'Bind the current agent session to a lifecycle feature. Call once per session after creating/identifying the feature. Binding is one-shot — calling again on a bound session returns already_bound.',
|
|
173
|
-
inputSchema: {
|
|
174
|
-
type: 'object',
|
|
175
|
-
properties: {
|
|
176
|
-
featureCode: { type: 'string', description: 'The feature code (e.g., "gate-ui")' },
|
|
177
|
-
},
|
|
178
|
-
required: ['featureCode'],
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
name: 'set_workspace',
|
|
183
|
-
description: 'Bind this MCP session to a workspace. Required when cwd contains multiple workspaces. Lives in process memory; lost on MCP restart.',
|
|
184
|
-
inputSchema: {
|
|
185
|
-
type: 'object',
|
|
186
|
-
required: ['workspaceId'],
|
|
187
|
-
properties: { workspaceId: { type: 'string', description: 'Workspace ID (kebab-case)' } },
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
name: 'get_workspace',
|
|
192
|
-
description: 'Get the current MCP workspace binding plus all candidates discovered from cwd.',
|
|
193
|
-
inputSchema: { type: 'object', properties: {} },
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
name: 'get_feature_lifecycle',
|
|
197
|
-
description: 'Get the lifecycle state of a feature: current phase, phase history, artifacts, warnings.',
|
|
198
|
-
inputSchema: {
|
|
199
|
-
type: 'object',
|
|
200
|
-
properties: {
|
|
201
|
-
id: { type: 'string', description: 'Item ID (UUID) or slug' },
|
|
202
|
-
},
|
|
203
|
-
required: ['id'],
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
name: 'kill_feature',
|
|
208
|
-
description: 'Kill a feature from any phase. Records reason and sets status to killed.',
|
|
209
|
-
inputSchema: {
|
|
210
|
-
type: 'object',
|
|
211
|
-
properties: {
|
|
212
|
-
id: { type: 'string', description: 'Item ID' },
|
|
213
|
-
reason: { type: 'string', description: 'Why the feature is being killed' },
|
|
214
|
-
},
|
|
215
|
-
required: ['id', 'reason'],
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
name: 'complete_feature',
|
|
220
|
-
description: 'Mark a feature as complete. Only callable from the ship phase. When commit_sha is provided, the lifecycle endpoint also writes a commit-bound completion record via record_completion (which atomically flips feature.status to COMPLETE and regenerates ROADMAP.md). Without commit_sha, the lifecycle transitions but no completion record is written; a `cockpit_completion_skipped` decision event explains the skip.',
|
|
221
|
-
inputSchema: {
|
|
222
|
-
type: 'object',
|
|
223
|
-
properties: {
|
|
224
|
-
id: { type: 'string', description: 'Item ID' },
|
|
225
|
-
commit_sha: { type: 'string', description: 'Full 40-char commit SHA. Required to write a completion record.' },
|
|
226
|
-
tests_pass: { type: 'boolean', description: 'Defaults to true when commit_sha is provided.' },
|
|
227
|
-
files_changed: { type: 'array', items: { type: 'string' }, description: 'Repo-relative paths committed in the SHA.' },
|
|
228
|
-
notes: { type: 'string', description: 'One-line note for the completion record.' },
|
|
229
|
-
},
|
|
230
|
-
required: ['id'],
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
name: 'start_iteration_loop',
|
|
235
|
-
description: 'Start a review or coverage iteration loop on a feature. Returns loop state.',
|
|
236
|
-
inputSchema: {
|
|
237
|
-
type: 'object',
|
|
238
|
-
properties: {
|
|
239
|
-
id: { type: 'string', description: 'Item ID or semanticId' },
|
|
240
|
-
loopType: { type: 'string', enum: ['review', 'coverage'], description: 'Type of iteration loop' },
|
|
241
|
-
maxIterations: { type: 'number', description: 'Override max iterations (optional, defaults from settings)' },
|
|
242
|
-
},
|
|
243
|
-
required: ['id', 'loopType'],
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
name: 'report_iteration_result',
|
|
248
|
-
description: 'Report one iteration result. Compose evaluates exit criteria and returns whether to continue.',
|
|
249
|
-
inputSchema: {
|
|
250
|
-
type: 'object',
|
|
251
|
-
properties: {
|
|
252
|
-
id: { type: 'string', description: 'Item ID or semanticId' },
|
|
253
|
-
result: { type: 'object', description: 'Iteration result. Review: {clean: bool, findings: []}, Coverage: {passing: bool, failures: []}' },
|
|
254
|
-
},
|
|
255
|
-
required: ['id', 'result'],
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
name: 'abort_iteration_loop',
|
|
260
|
-
description: 'Abort the current iteration loop early.',
|
|
261
|
-
inputSchema: {
|
|
262
|
-
type: 'object',
|
|
263
|
-
properties: {
|
|
264
|
-
id: { type: 'string', description: 'Item ID or semanticId' },
|
|
265
|
-
reason: { type: 'string', description: 'Why the loop was aborted' },
|
|
266
|
-
},
|
|
267
|
-
required: ['id'],
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
name: 'assess_feature_artifacts',
|
|
272
|
-
description: 'Assess quality signals for all artifacts of a feature: section completeness, word count, last modified.',
|
|
273
|
-
inputSchema: {
|
|
274
|
-
type: 'object',
|
|
275
|
-
properties: {
|
|
276
|
-
featureCode: { type: 'string', description: 'Feature folder name (e.g. "artifact-awareness")' },
|
|
277
|
-
},
|
|
278
|
-
required: ['featureCode'],
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
name: 'scaffold_feature',
|
|
283
|
-
description: 'Create feature folder with template stubs for all phase artifacts. Existing files are never overwritten.',
|
|
284
|
-
inputSchema: {
|
|
285
|
-
type: 'object',
|
|
286
|
-
properties: {
|
|
287
|
-
featureCode: { type: 'string', description: 'Feature folder name' },
|
|
288
|
-
only: {
|
|
289
|
-
type: 'array',
|
|
290
|
-
items: { type: 'string' },
|
|
291
|
-
description: 'Limit to specific artifacts (e.g. ["design.md", "blueprint.md"]). Omit for all.',
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
required: ['featureCode'],
|
|
295
|
-
},
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
name: 'approve_gate',
|
|
299
|
-
description: 'Resolve a pending policy gate. Outcomes: approved (proceed), revised (stay in phase), killed (abandon feature).',
|
|
300
|
-
inputSchema: {
|
|
301
|
-
type: 'object',
|
|
302
|
-
properties: {
|
|
303
|
-
gateId: { type: 'string', description: 'Gate ID' },
|
|
304
|
-
outcome: { type: 'string', enum: ['approved', 'revised', 'killed'], description: 'Resolution outcome' },
|
|
305
|
-
comment: { type: 'string', description: 'Optional human feedback' },
|
|
306
|
-
},
|
|
307
|
-
required: ['gateId', 'outcome'],
|
|
308
|
-
},
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
name: 'get_pending_gates',
|
|
312
|
-
description: 'List pending policy gates. Optionally filter by item ID.',
|
|
313
|
-
inputSchema: {
|
|
314
|
-
type: 'object',
|
|
315
|
-
properties: {
|
|
316
|
-
itemId: { type: 'string', description: 'Filter to gates for a specific item (optional)' },
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
// `agent_run` tool removed 2026-04-18 (STRAT-DEDUP-AGENTRUN v1); LLM-facing
|
|
321
|
-
// dispatch goes through `mcp__stratum__stratum_agent_run`.
|
|
322
|
-
|
|
323
|
-
// -------------------------------------------------------------------------
|
|
324
|
-
// Roadmap writers — COMP-MCP-ROADMAP-WRITER
|
|
325
|
-
// -------------------------------------------------------------------------
|
|
326
|
-
{
|
|
327
|
-
name: 'add_roadmap_entry',
|
|
328
|
-
description: 'Register a new feature in the project. Writes feature.json and regenerates ROADMAP.md (audit-log append is best-effort). Use this instead of editing ROADMAP.md by hand.',
|
|
329
|
-
inputSchema: {
|
|
330
|
-
type: 'object',
|
|
331
|
-
required: ['code', 'description', 'phase'],
|
|
332
|
-
properties: {
|
|
333
|
-
code: { type: 'string', description: 'Unique feature code (e.g. "COMP-FOO-1"). Must be uppercase A-Z, digits, dashes; cannot start or end with a dash.' },
|
|
334
|
-
description: { type: 'string', description: 'One-line description for the ROADMAP cell' },
|
|
335
|
-
phase: { type: 'string', description: 'Phase heading (e.g. "Phase 6: MCP Writers"). Required.' },
|
|
336
|
-
complexity: { type: 'string', enum: ['S', 'M', 'L', 'XL'] },
|
|
337
|
-
status: { type: 'string', enum: ['PLANNED', 'IN_PROGRESS', 'PARTIAL', 'COMPLETE', 'BLOCKED', 'KILLED', 'PARKED', 'SUPERSEDED'], description: 'Initial status (default PLANNED)' },
|
|
338
|
-
position: { type: 'number', description: 'Sort order within phase' },
|
|
339
|
-
parent: { type: 'string', description: 'Parent feature code, for cross-references' },
|
|
340
|
-
tags: { type: 'array', items: { type: 'string' } },
|
|
341
|
-
profile: { type: 'object', description: 'Triage build profile (needs_prd/needs_architecture/etc.). Set by the plan lifecycle so build can skip fresh triage.' },
|
|
342
|
-
triageTimestamp: { type: 'string', description: 'Triage cache stamp (ISO 8601). Set AFTER design.md is written so build treats triage as a cached no-op.' },
|
|
343
|
-
plannedBy: { type: 'string', description: 'Originating plan session code (e.g. "PLAN-WIDGET"). Marks a plan-authored, build-ready feature.' },
|
|
344
|
-
impact: { type: 'string', enum: ['low', 'medium', 'high'], description: 'Estimated impact, carried from the plan/ideabox estimation step.' },
|
|
345
|
-
force: { type: 'boolean', description: 'Bypass the pre-commit roundtrip guard (commit even if ROADMAP.md would not be a generation fixed point).' },
|
|
346
|
-
idempotency_key: { type: 'string', description: 'Optional caller-provided key. Same key replays return the cached result without re-mutating.' },
|
|
347
|
-
},
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
name: 'set_feature_status',
|
|
352
|
-
description: 'Flip a feature status. Updates feature.json and regenerates ROADMAP.md. Enforces a transition policy (use force: true to bypass). Appends an audit event (best-effort).',
|
|
353
|
-
inputSchema: {
|
|
354
|
-
type: 'object',
|
|
355
|
-
required: ['code', 'status'],
|
|
356
|
-
properties: {
|
|
357
|
-
code: { type: 'string' },
|
|
358
|
-
status: { type: 'string', enum: ['PLANNED', 'IN_PROGRESS', 'PARTIAL', 'COMPLETE', 'BLOCKED', 'KILLED', 'PARKED', 'SUPERSEDED'] },
|
|
359
|
-
reason: { type: 'string', description: 'Free-form reason persisted in the audit event' },
|
|
360
|
-
commit_sha: { type: 'string', description: 'Optional commit binding' },
|
|
361
|
-
force: { type: 'boolean', description: 'Bypass the transition policy AND the roundtrip fixed-point guard (commits even if ROADMAP.md would not be a generation fixed point). Recorded in audit.' },
|
|
362
|
-
idempotency_key: { type: 'string' },
|
|
363
|
-
},
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
name: 'roadmap_diff',
|
|
368
|
-
description: 'Read the feature-management audit log for a window. Returns events plus derived added[] and status_changed[] arrays.',
|
|
369
|
-
inputSchema: {
|
|
370
|
-
type: 'object',
|
|
371
|
-
properties: {
|
|
372
|
-
since: { type: 'string', description: 'Window: shorthand like "24h"/"7d"/"30m", or an ISO date. Default 24h.' },
|
|
373
|
-
feature_code: { type: 'string' },
|
|
374
|
-
tool: { type: 'string', description: 'Filter to one tool name, e.g. "set_feature_status"' },
|
|
375
|
-
},
|
|
376
|
-
},
|
|
377
|
-
},
|
|
378
|
-
{
|
|
379
|
-
name: 'get_roadmap',
|
|
380
|
-
description: 'Read the current roadmap rendered from canon (feature.json) WITHOUT writing. Returns a status summary, the active/blocked convenience lists, and a staleness flag vs on-disk ROADMAP.md. Pass a status/phase filter or a limit to also get a general `rows` list (e.g. {status:"PLANNED", limit:10} for "what to work on next") — structured rows so callers never re-parse the markdown. Narrative-owned workspaces return the hand-authored file verbatim. Read-only — prefer this over reading ROADMAP.md directly.',
|
|
381
|
-
inputSchema: {
|
|
382
|
-
type: 'object',
|
|
383
|
-
properties: {
|
|
384
|
-
status: { type: 'string', description: 'Filter active/blocked + rows by status (comma-separated): PLANNED, IN_PROGRESS, PARTIAL, BLOCKED, COMPLETE, …' },
|
|
385
|
-
phase: { type: 'string', description: 'Filter active/blocked + rows to a single phase (matched against phaseId)' },
|
|
386
|
-
format: { type: 'string', description: '"summary" (default — counts + lists, token-safe) or "markdown" (full rendered text)' },
|
|
387
|
-
check_drift: { type: 'boolean', description: 'Compare the render against on-disk ROADMAP.md and set stale/drift (default true)' },
|
|
388
|
-
limit: { type: 'integer', minimum: 0, description: 'Cap on the general `rows` list (default 50). Supplying status/phase/limit emits rows[]/rowsTotal/rowsTruncated; without any of them rows is omitted (token-safe summary). A finite value is floored and clamped to ≥ 0.' },
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
name: 'validate_feature',
|
|
394
|
-
description: 'Cross-check a single feature against ROADMAP, vision-state, feature.json, folder contents, linked artifacts, and cross-references. Returns structured findings with severity (error/warning/info). FEATURE_NOT_FOUND emitted as a finding (not thrown) when the code matches strict regex but exists in no source.',
|
|
395
|
-
inputSchema: {
|
|
396
|
-
type: 'object',
|
|
397
|
-
required: ['feature_code'],
|
|
398
|
-
properties: {
|
|
399
|
-
feature_code: { type: 'string', description: 'Strict feature code, e.g. "COMP-MCP-VALIDATE"' },
|
|
400
|
-
external_prefixes: { type: 'array', items: { type: 'string' }, description: 'Code prefixes (e.g. ["STRAT-"]) treated as external; downgrades ORPHAN_FOLDER to info' },
|
|
401
|
-
feature_json_mode: { type: 'boolean', description: 'Default true. Set false to skip feature.json comparisons in legacy projects.' },
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
},
|
|
405
|
-
{
|
|
406
|
-
name: 'validate_project',
|
|
407
|
-
description: 'Run validate_feature for every code in vision-state, ROADMAP, and folders, plus cross-cutting checks (orphan folders, dangling cross-refs, CHANGELOG references, journal index drift) and read-only external-reference staleness (kind:"external" links + xref: roadmap citations). external:true enables network resolution of github refs (off by default — github refs then emit XREF_RESOLUTION_SKIPPED). Returns the union of all findings.',
|
|
408
|
-
inputSchema: {
|
|
409
|
-
type: 'object',
|
|
410
|
-
properties: {
|
|
411
|
-
external_prefixes: { type: 'array', items: { type: 'string' } },
|
|
412
|
-
feature_json_mode: { type: 'boolean' },
|
|
413
|
-
external: { type: 'boolean', description: 'Resolve github external refs over the network (read-only). Default false: github refs degrade to XREF_RESOLUTION_SKIPPED.' },
|
|
414
|
-
fix: { type: 'boolean', description: 'COMP-MCP-VALIDATE-2: reconcile mechanical drift. Returns a fix plan under `reconcile` (dry-run unless apply:true). Local-provider only.' },
|
|
415
|
-
apply: { type: 'boolean', description: 'With fix:true, write the fixes and re-validate. Default false (dry-run plan only).' },
|
|
416
|
-
fix_classes: { type: 'array', items: { type: 'string' }, description: 'Override the enabled fix classes: dangling_link, invalid_link_kind, status_fj_vision, partial_age, roadmap_status_rewrite, invalid_link_kind_repair. Default: the non-destructive set.' },
|
|
417
|
-
},
|
|
418
|
-
},
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
name: 'roadmap_graph',
|
|
422
|
-
description: 'COMP-ROADMAP-GRAPH-1: generate a self-contained roadmap dependency-graph HTML from feature.json status/phase + per-feature deps.yaml edges + display frontmatter. Drops COMPLETE/SUPERSEDED/KILLED nodes; refuses (DANGLING_EDGE) when any edge points at an unknown feature. Deterministic/idempotent. Returns a small summary (path + counts + warnings), never the HTML body.',
|
|
423
|
-
inputSchema: {
|
|
424
|
-
type: 'object',
|
|
425
|
-
properties: {
|
|
426
|
-
project: { type: 'string', description: 'Project root path. Default: current workspace.' },
|
|
427
|
-
out: { type: 'string', description: 'Output HTML path (relative to project root unless absolute). Default: compose.json#roadmap_graph.out or roadmap-graph.html.' },
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
name: 'roadmap_graph_check',
|
|
433
|
-
description: 'COMP-ROADMAP-GRAPH-1: render the roadmap graph in-memory and diff against the on-disk HTML without writing. Returns { matches, exists, diffSummary, counts, warnings }. matches:false means the file is stale/missing — run roadmap_graph. Raises DANGLING_EDGE on a bad edge.',
|
|
434
|
-
inputSchema: {
|
|
435
|
-
type: 'object',
|
|
436
|
-
properties: {
|
|
437
|
-
project: { type: 'string', description: 'Project root path. Default: current workspace.' },
|
|
438
|
-
out: { type: 'string', description: 'Output HTML path to compare against. Default: compose.json#roadmap_graph.out or roadmap-graph.html.' },
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
name: 'roadmap_xref_push',
|
|
444
|
-
description: 'COMP-ROADMAP-XREF-PUSH: write external trackers to match feature.json `expect=`/`expect_labels` declared intent (the write-side counterpart to roadmap xref-sync Pull). DRY-RUN by default — returns {pushed, skipped, unchanged, scanned} describing what WOULD change. Only links with `push: true` are eligible. apply:true performs the writes: github issue open/closed + additive labels (never removes; PR-backed refs skipped), and local refs via the sibling repo\'s own setFeatureStatus. Degrades (skips, never guesses) on offline/no-token/404/non-2xx/disallowed-transition. Returns a small summary, never a large body.',
|
|
445
|
-
inputSchema: {
|
|
446
|
-
type: 'object',
|
|
447
|
-
properties: {
|
|
448
|
-
project: { type: 'string', description: 'Project root path. Default: current workspace.' },
|
|
449
|
-
apply: { type: 'boolean', description: 'Perform the writes. Default false (dry-run — report only).' },
|
|
450
|
-
},
|
|
451
|
-
},
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
name: 'propose_followup',
|
|
455
|
-
description: 'File a follow-up feature against a parent. Auto-numbers the next code in the parent\'s namespace (parent_code-N), adds the ROADMAP row, links surfaced_by from new → parent, and scaffolds design.md with a "## Why" rationale block. Idempotent on (parent_code, idempotency_key); resumes across partial failures via an inflight ledger.',
|
|
456
|
-
inputSchema: {
|
|
457
|
-
type: 'object',
|
|
458
|
-
required: ['parent_code', 'description', 'rationale'],
|
|
459
|
-
properties: {
|
|
460
|
-
parent_code: { type: 'string', description: 'Parent feature code (e.g. "COMP-MCP-MIGRATION"). Must exist; must not be KILLED/SUPERSEDED.' },
|
|
461
|
-
description: { type: 'string', description: 'One-line description for the ROADMAP cell.' },
|
|
462
|
-
rationale: { type: 'string', description: 'Why this follow-up exists. Persisted as a "## Why" block in the new design.md and in the audit event.' },
|
|
463
|
-
complexity: { type: 'string', enum: ['S', 'M', 'L', 'XL'] },
|
|
464
|
-
phase: { type: 'string', description: 'Phase heading. Defaults to the parent\'s phase if omitted.' },
|
|
465
|
-
status: { type: 'string', enum: ['PLANNED', 'IN_PROGRESS', 'PARTIAL', 'COMPLETE', 'BLOCKED', 'KILLED', 'PARKED', 'SUPERSEDED'] },
|
|
466
|
-
idempotency_key: { type: 'string', description: 'Optional retry-safety key. Without it, repeated calls allocate new codes.' },
|
|
467
|
-
},
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
|
|
471
|
-
// -------------------------------------------------------------------------
|
|
472
|
-
// Linker — COMP-MCP-ARTIFACT-LINKER
|
|
473
|
-
// -------------------------------------------------------------------------
|
|
474
|
-
{
|
|
475
|
-
name: 'link_artifact',
|
|
476
|
-
description: 'Register a non-canonical artifact (snapshot, journal entry, finding, etc.) on a feature. Canonical artifacts (design.md, plan.md, …) inside the feature folder are auto-discovered and rejected here. Stores in feature.json artifacts[]; dedups on (type, path); appends an audit event (best-effort).',
|
|
477
|
-
inputSchema: {
|
|
478
|
-
type: 'object',
|
|
479
|
-
required: ['feature_code', 'artifact_type', 'path'],
|
|
480
|
-
properties: {
|
|
481
|
-
feature_code: { type: 'string' },
|
|
482
|
-
artifact_type: { type: 'string', description: 'e.g. "journal", "snapshot", "finding", "report-supplement", "link", "external"' },
|
|
483
|
-
path: { type: 'string', description: 'Repo-relative path. Must exist; cannot contain ".." after normalization.' },
|
|
484
|
-
status: { type: 'string', enum: ['current', 'superseded', 'historical'] },
|
|
485
|
-
force: { type: 'boolean', description: 'Overwrite an existing entry with the same (type, path)' },
|
|
486
|
-
idempotency_key: { type: 'string' },
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
name: 'link_features',
|
|
492
|
-
description: 'Register a typed cross-feature relationship. Two shapes: (1) SAME-PROJECT — kind ∈ surfaced_by|blocks|depends_on|follow_up|supersedes|related, requires to_code; self-links rejected; dedups on (kind,to_code). (2) EXTERNAL (kind:"external") — a cross-project pointer, NOT a same-project link: requires provider; three resolvable sub-shapes — github (repo "owner/name" + integer issue), local (repo token + to_code), url (url); plus reserved url-class providers jira|linear|notion|obsidian (parse-valid, require url, NOT resolved in v1). External dedups on (kind=external, provider, repo, issue|to_code|url). Stores on the source feature; query inverse via get_feature_links(direction:"incoming").',
|
|
493
|
-
inputSchema: {
|
|
494
|
-
type: 'object',
|
|
495
|
-
required: ['from_code', 'kind'],
|
|
496
|
-
properties: {
|
|
497
|
-
from_code: { type: 'string' },
|
|
498
|
-
to_code: { type: 'string', description: 'Same-project: target feature code (required unless kind:"external"). External local: the cited feature code. Need not exist yet.' },
|
|
499
|
-
kind: { type: 'string', enum: ['surfaced_by', 'blocks', 'depends_on', 'follow_up', 'supersedes', 'related', 'external'] },
|
|
500
|
-
provider: { type: 'string', enum: ['github', 'local', 'url', 'jira', 'linear', 'notion', 'obsidian'], description: 'Required when kind:"external". Resolvable: github|local|url. Reserved url-class (require url, not resolved in v1): jira|linear|notion|obsidian.' },
|
|
501
|
-
repo: { type: 'string', description: 'External github: "owner/name". External local: workspace-relative repo token.' },
|
|
502
|
-
issue: { type: 'integer', minimum: 1, description: 'External github: issue/PR number.' },
|
|
503
|
-
url: { type: 'string', description: 'External url-class (url|jira|linear|notion|obsidian): the pointer URL.' },
|
|
504
|
-
expect: { type: 'string', description: 'Optional expected state. github: open|closed. local: a status token. url-class: recorded, never resolved.' },
|
|
505
|
-
note: { type: 'string' },
|
|
506
|
-
force: { type: 'boolean' },
|
|
507
|
-
idempotency_key: { type: 'string' },
|
|
508
|
-
},
|
|
509
|
-
},
|
|
510
|
-
},
|
|
511
|
-
{
|
|
512
|
-
name: 'get_feature_artifacts',
|
|
513
|
-
description: 'Read both canonical (auto-discovered: design.md, plan.md, …) and linked (snapshots, journals, findings) artifacts for a feature in one call. Each linked entry includes a current existence check.',
|
|
514
|
-
inputSchema: {
|
|
515
|
-
type: 'object',
|
|
516
|
-
required: ['feature_code'],
|
|
517
|
-
properties: {
|
|
518
|
-
feature_code: { type: 'string' },
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
},
|
|
522
|
-
{
|
|
523
|
-
name: 'get_feature_links',
|
|
524
|
-
description: 'Read outgoing and/or incoming feature links. Default returns both directions; filter by kind if needed.',
|
|
525
|
-
inputSchema: {
|
|
526
|
-
type: 'object',
|
|
527
|
-
required: ['feature_code'],
|
|
528
|
-
properties: {
|
|
529
|
-
feature_code: { type: 'string' },
|
|
530
|
-
direction: { type: 'string', enum: ['outgoing', 'incoming', 'both'] },
|
|
531
|
-
kind: { type: 'string' },
|
|
532
|
-
},
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
|
|
536
|
-
// -------------------------------------------------------------------------
|
|
537
|
-
// Changelog writer — COMP-MCP-CHANGELOG-WRITER
|
|
538
|
-
// -------------------------------------------------------------------------
|
|
539
|
-
{
|
|
540
|
-
name: 'add_changelog_entry',
|
|
541
|
-
description: 'Insert (or replace, with force: true) a typed entry in compose/CHANGELOG.md. Idempotent on (date_or_version, code) at storage level; optional caller-supplied idempotency_key for retry safety. Audit-log append is best-effort. Use this instead of editing CHANGELOG.md by hand.',
|
|
542
|
-
inputSchema: {
|
|
543
|
-
type: 'object',
|
|
544
|
-
required: ['date_or_version', 'code', 'summary'],
|
|
545
|
-
properties: {
|
|
546
|
-
date_or_version: { type: 'string', description: 'ISO date "YYYY-MM-DD" or semver "vX.Y.Z"' },
|
|
547
|
-
code: { type: 'string', description: 'Feature code (e.g. "COMP-FOO-1"). Uppercase A-Z, digits, dashes; cannot start or end with a dash.' },
|
|
548
|
-
summary: { type: 'string', description: 'One-line summary; renders as the "— summary" tail of the entry header.' },
|
|
549
|
-
body: { type: 'string', description: 'Free paragraphs between header and labeled subsections.' },
|
|
550
|
-
sections: {
|
|
551
|
-
type: 'object',
|
|
552
|
-
description: 'Optional labeled subsections; emitted in fixed order Added → Changed → Fixed → Snapshot.',
|
|
553
|
-
properties: {
|
|
554
|
-
added: { type: 'array', items: { type: 'string' } },
|
|
555
|
-
changed: { type: 'array', items: { type: 'string' } },
|
|
556
|
-
fixed: { type: 'array', items: { type: 'string' } },
|
|
557
|
-
snapshot: { type: 'array', items: { type: 'string' } },
|
|
558
|
-
},
|
|
559
|
-
additionalProperties: false,
|
|
560
|
-
},
|
|
561
|
-
force: { type: 'boolean', description: 'If true and an entry with the same (date_or_version, code) exists, replace it in place.' },
|
|
562
|
-
idempotency_key: { type: 'string', description: 'Optional caller-supplied key. Same key replays return the cached result without re-mutating.' },
|
|
563
|
-
},
|
|
564
|
-
},
|
|
565
|
-
},
|
|
566
|
-
{
|
|
567
|
-
name: 'get_changelog_entries',
|
|
568
|
-
description: 'Read parsed entries from compose/CHANGELOG.md. Filter by code (exact) or since (shorthand "24h"/"7d"/"30m" or ISO date — date-only; version surfaces always pass through).',
|
|
569
|
-
inputSchema: {
|
|
570
|
-
type: 'object',
|
|
571
|
-
properties: {
|
|
572
|
-
since: { type: 'string', description: 'Window: shorthand like "24h"/"7d"/"30m" or ISO date. Date-only filter; version surfaces are always returned.' },
|
|
573
|
-
code: { type: 'string' },
|
|
574
|
-
limit: { type: 'number', description: 'Default 50; capped at 500.' },
|
|
575
|
-
},
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
|
|
579
|
-
// -------------------------------------------------------------------------
|
|
580
|
-
// Journal writer — COMP-MCP-JOURNAL-WRITER
|
|
581
|
-
// -------------------------------------------------------------------------
|
|
582
|
-
{
|
|
583
|
-
name: 'write_journal_entry',
|
|
584
|
-
description: 'Write a typed entry to compose/docs/journal/ with auto-numbered global session and inserted index row. Idempotent on (date, slug) at storage level; optional caller idempotency_key for retry safety. Audit-log append is best-effort.',
|
|
585
|
-
inputSchema: {
|
|
586
|
-
type: 'object',
|
|
587
|
-
required: ['date', 'slug', 'sections', 'summary_for_index'],
|
|
588
|
-
properties: {
|
|
589
|
-
date: { type: 'string', description: 'ISO date "YYYY-MM-DD".' },
|
|
590
|
-
slug: { type: 'string', description: 'Kebab-case slug for the filename, e.g. "mcp-journal-writer".' },
|
|
591
|
-
sections: {
|
|
592
|
-
type: 'object',
|
|
593
|
-
required: ['what_happened', 'what_we_built', 'what_we_learned', 'open_threads'],
|
|
594
|
-
properties: {
|
|
595
|
-
what_happened: { type: 'string' },
|
|
596
|
-
what_we_built: { type: 'string' },
|
|
597
|
-
what_we_learned: { type: 'string' },
|
|
598
|
-
open_threads: { type: 'string' },
|
|
599
|
-
},
|
|
600
|
-
additionalProperties: false,
|
|
601
|
-
},
|
|
602
|
-
summary_for_index: { type: 'string', description: 'Single-line summary for the README index row. No newlines, no "|".' },
|
|
603
|
-
feature_code: { type: 'string', description: 'Optional feature code stamped in entry frontmatter.' },
|
|
604
|
-
closing_line: { type: 'string', description: 'Optional final italicized one-liner.' },
|
|
605
|
-
force: { type: 'boolean', description: 'If true and an entry with the same (date, slug) exists, overwrite in place.' },
|
|
606
|
-
idempotency_key: { type: 'string', description: 'Optional caller-supplied key. Same key replays return the cached result without re-mutating.' },
|
|
607
|
-
},
|
|
608
|
-
},
|
|
609
|
-
},
|
|
610
|
-
{
|
|
611
|
-
name: 'get_journal_entries',
|
|
612
|
-
description: 'Read parsed entries from compose/docs/journal/. Filter by feature_code (exact), session (exact), or since (shorthand "24h"/"7d"/"30m" or ISO date).',
|
|
613
|
-
inputSchema: {
|
|
614
|
-
type: 'object',
|
|
615
|
-
properties: {
|
|
616
|
-
since: { type: 'string' },
|
|
617
|
-
feature_code: { type: 'string' },
|
|
618
|
-
session: { type: 'number' },
|
|
619
|
-
limit: { type: 'number', description: 'Default 50; capped at 500.' },
|
|
620
|
-
},
|
|
621
|
-
},
|
|
622
|
-
},
|
|
623
|
-
// -------------------------------------------------------------------------
|
|
624
|
-
// Completion writer — COMP-MCP-COMPLETION
|
|
625
|
-
// -------------------------------------------------------------------------
|
|
626
|
-
{
|
|
627
|
-
name: 'record_completion',
|
|
628
|
-
description: 'Record a completion bound to a commit SHA. Stores in feature.json completions[]; idempotent on (feature_code, commit_sha); when set_status:true (default) also flips status to COMPLETE via set_feature_status. Audit append best-effort. Status-flip failure rethrows as STATUS_FLIP_AFTER_COMPLETION_RECORDED with err.cause; the completion record is still persisted.',
|
|
629
|
-
inputSchema: {
|
|
630
|
-
type: 'object',
|
|
631
|
-
required: ['feature_code', 'commit_sha', 'tests_pass', 'files_changed'],
|
|
632
|
-
properties: {
|
|
633
|
-
feature_code: { type: 'string' },
|
|
634
|
-
commit_sha: { type: 'string', description: 'Full 40-char hex SHA (Decision 9). Short prefixes are rejected on write. Stored verbatim; commit_sha_short is derived for display only.' },
|
|
635
|
-
tests_pass: { type: 'boolean' },
|
|
636
|
-
files_changed: { type: 'array', items: { type: 'string' } },
|
|
637
|
-
notes: { type: 'string' },
|
|
638
|
-
set_status: { type: 'boolean', description: 'Default true. When true, flips status to COMPLETE via set_feature_status.' },
|
|
639
|
-
force: { type: 'boolean', description: 'If true and a record with the same (feature_code, commit_sha) exists, replace it in place.' },
|
|
640
|
-
idempotency_key: { type: 'string' },
|
|
641
|
-
},
|
|
642
|
-
},
|
|
643
|
-
},
|
|
644
|
-
{
|
|
645
|
-
name: 'get_completions',
|
|
646
|
-
description: 'Read completion records from feature.json files. Filter by feature_code (exact), commit_sha (short or full prefix), or since (shorthand or ISO date).',
|
|
647
|
-
inputSchema: {
|
|
648
|
-
type: 'object',
|
|
649
|
-
properties: {
|
|
650
|
-
feature_code: { type: 'string' },
|
|
651
|
-
commit_sha: { type: 'string' },
|
|
652
|
-
since: { type: 'string' },
|
|
653
|
-
limit: { type: 'number', description: 'Default 50; capped at 500.' },
|
|
654
|
-
},
|
|
655
|
-
},
|
|
656
|
-
},
|
|
657
|
-
{
|
|
658
|
-
name: 'write_checkpoint',
|
|
659
|
-
description: 'COMP-RESUME: write a durable build checkpoint anchored to a deterministic environment fingerprint. Omit `soft` for a cheap anchor checkpoint — the response then includes a `scribePrompt` you can answer (returning {goal,nextStep,risks} anchored to the fingerprint) and re-submit as `soft` for a narrative checkpoint. Pass `soft` directly to skip that. Returns {checkpoint, scribePrompt}. Direct-to-disk (works when the server is down).',
|
|
660
|
-
inputSchema: {
|
|
661
|
-
type: 'object',
|
|
662
|
-
required: ['featureCode', 'trigger'],
|
|
663
|
-
properties: {
|
|
664
|
-
featureCode: { type: 'string' },
|
|
665
|
-
trigger: { type: 'string', enum: ['phase-transition', 'pre-risky-action', 'iteration-complete', 'gate-resolution', 'manual', 'resume-sync'] },
|
|
666
|
-
phase: { type: 'string', description: 'Lifecycle phase label; falls back to feature.json then "unknown".' },
|
|
667
|
-
soft: {
|
|
668
|
-
type: 'object',
|
|
669
|
-
description: 'Narrative intent; omit for an anchor checkpoint. Every factual claim should reference a fingerprint anchor.',
|
|
670
|
-
required: ['goal', 'nextStep'],
|
|
671
|
-
properties: {
|
|
672
|
-
goal: { type: 'string' },
|
|
673
|
-
nextStep: { type: 'string' },
|
|
674
|
-
risks: { type: 'array', items: { type: 'string' } },
|
|
675
|
-
},
|
|
676
|
-
},
|
|
677
|
-
flowId: { type: 'string', description: 'Stratum flow id, if any.' },
|
|
678
|
-
confidence: { type: 'number', description: 'Only on resume-sync checkpoints (0..1).' },
|
|
679
|
-
},
|
|
680
|
-
},
|
|
681
|
-
},
|
|
682
|
-
{
|
|
683
|
-
name: 'compose_resume',
|
|
684
|
-
description: 'COMP-RESUME: reconcile a build against ground-truth environment state and return the resume decision. Rebuilds derived state, classifies drift (clean/advanced/diverged), and returns action resume|needs-sync|gate. On needs-sync the caller runs the reconciliation agent with the returned prompt. Requires the Compose server (reconciles live lifecycle state).',
|
|
685
|
-
inputSchema: {
|
|
686
|
-
type: 'object',
|
|
687
|
-
required: ['featureCode'],
|
|
688
|
-
properties: {
|
|
689
|
-
featureCode: { type: 'string' },
|
|
690
|
-
},
|
|
691
|
-
},
|
|
692
|
-
},
|
|
693
|
-
|
|
694
|
-
// -------------------------------------------------------------------------
|
|
695
|
-
// Judgment writer — COMP-JUDGMENT-WRITER (the only legitimate write path to
|
|
696
|
-
// docs/judgment canon; records canonical, markdown generated). Terse
|
|
697
|
-
// schemas by design (token budget); the writer self-validates against
|
|
698
|
-
// contracts/judgment-record.schema.json — inputSchema is advisory.
|
|
699
|
-
// -------------------------------------------------------------------------
|
|
700
|
-
{
|
|
701
|
-
name: 'judgment_position_create',
|
|
702
|
-
description: 'Create a judgment position revision (new chain, update, supersession via supersedes, or tombstone via retracted). ASSERT grounding requires an elicitation block. Provenance is writer-stamped.',
|
|
703
|
-
inputSchema: {
|
|
704
|
-
type: 'object',
|
|
705
|
-
required: ['slug', 'claims', 'conviction'],
|
|
706
|
-
properties: {
|
|
707
|
-
slug: { type: 'string' },
|
|
708
|
-
claims: { type: 'array', description: 'Claims: {id, text, grounding EXT|INT|ASSERT|DERIVED|AGENT, supports[], elicitation?}.' },
|
|
709
|
-
conviction: { type: 'object', description: '{level high|medium|low, source stated|inferred}' },
|
|
710
|
-
rejected_alternatives: { type: 'array', description: '{what, why}[]' },
|
|
711
|
-
supersedes: { type: 'string', description: '<slug>#r<N> being superseded.' },
|
|
712
|
-
retracted: { type: 'boolean', description: 'true → tombstone revision.' },
|
|
713
|
-
idempotency_key: { type: 'string' },
|
|
714
|
-
},
|
|
715
|
-
},
|
|
716
|
-
},
|
|
717
|
-
{
|
|
718
|
-
name: 'judgment_position_amend',
|
|
719
|
-
description: 'Scoped amendment (P6): new revision changing ONE claim\'s grounding and/or the conviction block. Anything else is supersession via judgment_position_create.',
|
|
720
|
-
inputSchema: {
|
|
721
|
-
type: 'object',
|
|
722
|
-
required: ['slug'],
|
|
723
|
-
properties: {
|
|
724
|
-
slug: { type: 'string' },
|
|
725
|
-
claim_id: { type: 'string' },
|
|
726
|
-
grounding: { type: 'string', description: 'New grounding for claim_id.' },
|
|
727
|
-
elicitation: { type: 'object', description: 'Required if new grounding is ASSERT.' },
|
|
728
|
-
conviction: { type: 'object' },
|
|
729
|
-
idempotency_key: { type: 'string' },
|
|
730
|
-
},
|
|
731
|
-
},
|
|
732
|
-
},
|
|
733
|
-
{
|
|
734
|
-
name: 'judgment_joint_add',
|
|
735
|
-
description: 'Add a judgment joint (born open). Both branches and a coarse cost bucket are required; EXT/STRADDLE method packages may be attached now or at dispose time.',
|
|
736
|
-
inputSchema: {
|
|
737
|
-
type: 'object',
|
|
738
|
-
required: ['slug', 'question', 'branch_true', 'branch_false', 'resolve_by', 'cost', 'rank'],
|
|
739
|
-
properties: {
|
|
740
|
-
slug: { type: 'string' },
|
|
741
|
-
question: { type: 'string' },
|
|
742
|
-
branch_true: { type: 'string' },
|
|
743
|
-
branch_false: { type: 'string' },
|
|
744
|
-
resolve_by: { type: 'string', description: 'EXT|INT|CONSTRUCT|ASSERT|STRADDLE' },
|
|
745
|
-
cost: { type: 'string', description: 'hours|days|weeks|months' },
|
|
746
|
-
rank: { type: 'string', description: 'high|medium' },
|
|
747
|
-
ext: { type: 'object', description: 'EXT package: {sharpened_question, bar, falsifier} or {judgment_dispatch: true, reason}.' },
|
|
748
|
-
straddle: { type: 'object', description: '{discriminating_signal, kill_criteria}' },
|
|
749
|
-
flags: { type: 'array' },
|
|
750
|
-
idempotency_key: { type: 'string' },
|
|
751
|
-
},
|
|
752
|
-
},
|
|
753
|
-
},
|
|
754
|
-
{
|
|
755
|
-
name: 'judgment_transition',
|
|
756
|
-
description: 'Joint state machine (edge→artifact table enforced; Stratum-guarded where capabilities.guard). Provide the target state plus its required artifact (resolution/dissolution/reopen/redispose), and/or a rank change (atomic rank ledger event).',
|
|
757
|
-
inputSchema: {
|
|
758
|
-
type: 'object',
|
|
759
|
-
required: ['slug'],
|
|
760
|
-
properties: {
|
|
761
|
-
slug: { type: 'string' },
|
|
762
|
-
to: { type: 'string', description: 'open|under_test|resolved|inconclusive|superseded|dissolved' },
|
|
763
|
-
resolution: { type: 'object', description: '{outcome resolved|inconclusive|failed_to_run|superseded, …outcome-specific fields, ext_result?, elicitation?}' },
|
|
764
|
-
dissolution: { type: 'object', description: '{decomposed_into[]}' },
|
|
765
|
-
reopen: { type: 'object', description: '{shaken_evidence_ref} (P6)' },
|
|
766
|
-
redispose: { type: 'object', description: '{new_resolve_by, ext?, straddle?} (retry inconclusive with a different method)' },
|
|
767
|
-
ext: { type: 'object', description: 'EXT package attached at dispose time.' },
|
|
768
|
-
straddle: { type: 'object' },
|
|
769
|
-
rank: { type: 'object', description: '{to: high|medium}' },
|
|
770
|
-
idempotency_key: { type: 'string' },
|
|
771
|
-
},
|
|
772
|
-
},
|
|
773
|
-
},
|
|
774
|
-
{
|
|
775
|
-
name: 'judgment_ledger_append',
|
|
776
|
-
description: 'Append a judgment ledger event (kind-specific required fields enforced: commit-decide needs trigger+open_joints+prediction; postmortem needs recall_verdict+attribution and grades prediction_ref; override needs reason). Commit/CONSTRUCT events spawn prediction records.',
|
|
777
|
-
inputSchema: {
|
|
778
|
-
type: 'object',
|
|
779
|
-
required: ['kind', 'title'],
|
|
780
|
-
properties: {
|
|
781
|
-
kind: { type: 'string', description: 'decide|kill|override|escalate|calibrate|postmortem|rank|note|correct|open' },
|
|
782
|
-
title: { type: 'string' },
|
|
783
|
-
body: { type: 'string' },
|
|
784
|
-
refs: { type: 'array' },
|
|
785
|
-
rejected: { type: 'array' },
|
|
786
|
-
conviction: { type: 'object' },
|
|
787
|
-
trigger: { type: 'string', description: 'On decide: earned|forced|exhausted (marks a commit-moment decide).' },
|
|
788
|
-
open_joints: { type: 'array' },
|
|
789
|
-
prediction: { type: 'object', description: '{text, outcome_criteria}' },
|
|
790
|
-
disposition: { type: 'string', description: 'Method disposed with; CONSTRUCT requires prediction.' },
|
|
791
|
-
recall_verdict: { type: 'string' },
|
|
792
|
-
attribution: { type: 'string' },
|
|
793
|
-
prediction_ref: { type: 'string' },
|
|
794
|
-
prediction_grade: { type: 'string', description: 'right|right-wrong-reason|wrong' },
|
|
795
|
-
reason: { type: 'string' },
|
|
796
|
-
rests_on: { type: 'array', description: 'On commit-moment decide: goal clause refs (goal:v<N>#c<N>) the commit rests on; resolved through the effective goal chain.' },
|
|
797
|
-
anchor: { type: 'string', description: 'On note: projection anchor (register-header, joint:<slug>, …).' },
|
|
798
|
-
idempotency_key: { type: 'string' },
|
|
799
|
-
},
|
|
800
|
-
},
|
|
801
|
-
},
|
|
802
|
-
{
|
|
803
|
-
name: 'judgment_person_write',
|
|
804
|
-
description: 'Write person canon by op. create adds a person; open_field supports create, fill, and reopen; edge/load_link support create and remove; correct supports divergence pair/clear. Provenance is writer-stamped.',
|
|
805
|
-
inputSchema: {
|
|
806
|
-
type: 'object',
|
|
807
|
-
required: ['op'],
|
|
808
|
-
properties: {
|
|
809
|
-
op: { type: 'string', enum: ['create', 'add_fact', 'correct', 'open_field', 'edge', 'load_link'] },
|
|
810
|
-
slug: { type: 'string' },
|
|
811
|
-
display_name: { type: 'string' },
|
|
812
|
-
section: { type: 'string', description: 'role|life|stated|revealed' },
|
|
813
|
-
text: { type: 'string' },
|
|
814
|
-
channel: { type: 'string', description: 'said|observed|secondhand|inferred' },
|
|
815
|
-
via: { type: 'string', description: 'Source attribution for a secondhand fact; not provenance.' },
|
|
816
|
-
at: { type: 'string', description: 'ISO date (YYYY-MM-DD).' },
|
|
817
|
-
fact_id: { type: 'string' },
|
|
818
|
-
pair_with: { type: 'string', description: 'Pair stated↔revealed divergence on correct.' },
|
|
819
|
-
clear: { type: 'array', description: 'On correct: exactly ["diverges_with"].', items: { type: 'string' } },
|
|
820
|
-
name: { type: 'string', description: 'open_field create branch.' },
|
|
821
|
-
open_field_id: { type: 'string' },
|
|
822
|
-
filled_by: { type: 'string' },
|
|
823
|
-
reopen: { type: 'boolean' },
|
|
824
|
-
reason: { type: 'string' },
|
|
825
|
-
to: { type: 'string', description: 'edge create branch target person slug.' },
|
|
826
|
-
kind: { type: 'string', description: 'edge create branch kind.' },
|
|
827
|
-
edge_id: { type: 'string' },
|
|
828
|
-
remove: { type: 'boolean' },
|
|
829
|
-
fact: { type: 'string', description: 'load_link create branch fact ID.' },
|
|
830
|
-
carries: { type: 'string' },
|
|
831
|
-
load_link_id: { type: 'string' },
|
|
832
|
-
idempotency_key: { type: 'string' },
|
|
833
|
-
},
|
|
834
|
-
},
|
|
835
|
-
},
|
|
836
|
-
{
|
|
837
|
-
name: 'judgment_situation_write',
|
|
838
|
-
description: 'Write situation-entity canon by op. create adds an entity; owed supports create, give, and reopen; load_link supports create and remove. Provenance is writer-stamped.',
|
|
839
|
-
inputSchema: {
|
|
840
|
-
type: 'object',
|
|
841
|
-
required: ['op'],
|
|
842
|
-
properties: {
|
|
843
|
-
op: { type: 'string', enum: ['create', 'add_fact', 'correct', 'owed', 'load_link'] },
|
|
844
|
-
slug: { type: 'string' },
|
|
845
|
-
display_name: { type: 'string' },
|
|
846
|
-
text: { type: 'string' },
|
|
847
|
-
channel: { type: 'string', description: 'said|observed|secondhand|inferred' },
|
|
848
|
-
via: { type: 'string', description: 'Source attribution for a secondhand fact; not provenance.' },
|
|
849
|
-
at: { type: 'string', description: 'ISO date (YYYY-MM-DD).' },
|
|
850
|
-
fact_id: { type: 'string' },
|
|
851
|
-
name: { type: 'string', description: 'owed create branch.' },
|
|
852
|
-
why_load_bearing: { type: 'string' },
|
|
853
|
-
owed_id: { type: 'string' },
|
|
854
|
-
filled_by: { type: 'string' },
|
|
855
|
-
reopen: { type: 'boolean' },
|
|
856
|
-
reason: { type: 'string' },
|
|
857
|
-
remove: { type: 'boolean' },
|
|
858
|
-
fact: { type: 'string', description: 'load_link create branch fact ID.' },
|
|
859
|
-
carries: { type: 'string' },
|
|
860
|
-
load_link_id: { type: 'string' },
|
|
861
|
-
idempotency_key: { type: 'string' },
|
|
862
|
-
},
|
|
863
|
-
},
|
|
864
|
-
},
|
|
865
|
-
{
|
|
866
|
-
name: 'judgment_goal_write',
|
|
867
|
-
description: 'Write goal canon by op. Ordinary cuts require elicited clauses, provocation, and owner ratification. Every non-migrate op is migration-locked while a live legacy objective requires migration; migrate is the one-shot, fail-closed cutover that lifts the lock and takes no payload. joint_link/load_link support create and remove. Provenance and intents are writer-owned.',
|
|
868
|
-
inputSchema: {
|
|
869
|
-
type: 'object',
|
|
870
|
-
required: ['op'],
|
|
871
|
-
properties: {
|
|
872
|
-
op: { type: 'string', enum: ['cut', 'correct', 'joint_link', 'load_link', 'migrate'] },
|
|
873
|
-
clauses: { type: 'array', description: 'cut: {text, channel, elicitation, secondhand source attribution?}[]' },
|
|
874
|
-
provocation: { type: 'object', description: 'cut: {quote, at}' },
|
|
875
|
-
ratification: { type: 'object', description: 'cut: {asked, answered_at, answer_ref, quote}' },
|
|
876
|
-
diff_note: { type: 'string' },
|
|
877
|
-
clause_id: { type: 'string', description: 'correct branch clause ID.' },
|
|
878
|
-
text: { type: 'string', description: 'correct branch replacement wording.' },
|
|
879
|
-
joint: { type: 'string', description: 'joint_link create branch joint slug.' },
|
|
880
|
-
joint_link_id: { type: 'string' },
|
|
881
|
-
remove: { type: 'boolean' },
|
|
882
|
-
reason: { type: 'string' },
|
|
883
|
-
clause: { type: 'string', description: 'load_link create branch v<N>#c<N> reference.' },
|
|
884
|
-
carries: { type: 'string' },
|
|
885
|
-
load_link_id: { type: 'string' },
|
|
886
|
-
idempotency_key: { type: 'string' },
|
|
887
|
-
},
|
|
888
|
-
},
|
|
889
|
-
},
|
|
890
|
-
{
|
|
891
|
-
name: 'get_judgment_state',
|
|
892
|
-
description: 'Judgment canon snapshot: positions (derived status), joints, under-test, open predictions, recent ledger. Replays pending judgment intents first.',
|
|
893
|
-
inputSchema: { type: 'object', properties: {} },
|
|
894
|
-
},
|
|
895
|
-
];
|
|
98
|
+
import { TOOLS } from './mcp-tool-defs.js';
|
|
896
99
|
|
|
897
100
|
// ---------------------------------------------------------------------------
|
|
898
101
|
// MCP Server setup
|
|
@@ -903,20 +106,28 @@ const server = new Server(
|
|
|
903
106
|
{ capabilities: { tools: {} } }
|
|
904
107
|
);
|
|
905
108
|
|
|
109
|
+
// COMP-COVERAGE-GATE: `effect`/`writes` are LOCAL declarations consumed by
|
|
110
|
+
// lib/tool-inventory.js — they are not part of the MCP tool schema and must not
|
|
111
|
+
// reach the wire. Strip them at this one boundary rather than keeping a parallel
|
|
112
|
+
// wire-shaped copy of the array, which would be the drift this feature exists
|
|
113
|
+
// to stop.
|
|
114
|
+
const WIRE_TOOL = ({ name, description, inputSchema }) => ({ name, description, inputSchema });
|
|
115
|
+
const toWire = (tools) => tools.map(WIRE_TOOL);
|
|
116
|
+
|
|
906
117
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
907
118
|
// COMP-MCP-ENFORCE-1: best-effort surface filter by the session's profile×phase.
|
|
908
119
|
// The hard guarantee is the CallTool gate below; ListTools just hides what the
|
|
909
120
|
// current context can't use (no tools/list_changed dependency).
|
|
910
121
|
const enabled = loadProjectConfig()?.capabilities?.phaseScopedTools === true;
|
|
911
|
-
if (!enabled) return { tools: TOOLS };
|
|
122
|
+
if (!enabled) return { tools: toWire(TOOLS) };
|
|
912
123
|
const profile = _getSessionProfile();
|
|
913
|
-
if (profile === 'orchestrator') return { tools: TOOLS };
|
|
124
|
+
if (profile === 'orchestrator') return { tools: toWire(TOOLS) };
|
|
914
125
|
const phase = resolveBoundPhase();
|
|
915
126
|
// target match is unknowable at list time → list a tool if its profile base
|
|
916
127
|
// (ignoring the feature-scoped re-permit) would ever permit it in this phase.
|
|
917
128
|
const tools = TOOLS.filter((t) =>
|
|
918
129
|
isToolAllowed({ tool: t.name, profile, phase, targetMatchesBoundFeature: true }).allowed);
|
|
919
|
-
return { tools };
|
|
130
|
+
return { tools: toWire(tools) };
|
|
920
131
|
});
|
|
921
132
|
|
|
922
133
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -924,86 +135,81 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
924
135
|
|
|
925
136
|
const WORKSPACE_EXEMPT = new Set(['set_workspace', 'get_workspace']);
|
|
926
137
|
|
|
927
|
-
// COMP-MCP-ENFORCE-1: phase-scoped tool gate (hard guarantee). No-op when the
|
|
928
|
-
// capability is off, on a valid override token, or when context is unresolved.
|
|
929
|
-
try {
|
|
930
|
-
assertToolPhaseAllowed(name, args);
|
|
931
|
-
} catch (err) {
|
|
932
|
-
if (err && err.code === 'PHASE_TOOL_DENIED') {
|
|
933
|
-
return {
|
|
934
|
-
content: [{ type: 'text', text: `Error [PHASE_TOOL_DENIED]: ${err.message}` }],
|
|
935
|
-
isError: true,
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
throw err;
|
|
939
|
-
}
|
|
940
|
-
|
|
941
138
|
try {
|
|
139
|
+
// set_workspace changes the session default. Every other operation pins its
|
|
140
|
+
// resolved root before awaiting, so a concurrent rebind cannot retarget it.
|
|
141
|
+
let binding = null;
|
|
942
142
|
if (!WORKSPACE_EXEMPT.has(name)) {
|
|
943
|
-
const ws = resolveWorkspace({
|
|
944
|
-
|
|
945
|
-
}
|
|
946
|
-
let result;
|
|
947
|
-
switch (name) {
|
|
948
|
-
case 'get_vision_items': result = toolGetVisionItems(args); break;
|
|
949
|
-
case 'get_item_detail': result = toolGetItemDetail(args); break;
|
|
950
|
-
case 'get_phase_summary': result = toolGetPhasesSummary(args); break;
|
|
951
|
-
case 'get_blocked_items': result = toolGetBlockedItems(); break;
|
|
952
|
-
case 'get_current_session': result = await toolGetCurrentSession(args); break;
|
|
953
|
-
case 'bind_session': result = await toolBindSession(args); break;
|
|
954
|
-
case 'set_workspace': result = toolSetWorkspace(args); break;
|
|
955
|
-
case 'get_workspace': result = toolGetWorkspace(); break;
|
|
956
|
-
case 'get_feature_lifecycle': result = toolGetFeatureLifecycle(args); break;
|
|
957
|
-
case 'kill_feature': result = await toolKillFeature(args); break;
|
|
958
|
-
case 'complete_feature': result = await toolCompleteFeature(args); break;
|
|
959
|
-
case 'start_iteration_loop': result = await toolIterationStart(args); break;
|
|
960
|
-
case 'report_iteration_result': result = await toolIterationReport(args); break;
|
|
961
|
-
case 'abort_iteration_loop': result = await toolIterationAbort(args); break;
|
|
962
|
-
case 'assess_feature_artifacts': result = toolAssessFeatureArtifacts(args); break;
|
|
963
|
-
case 'scaffold_feature': result = toolScaffoldFeature(args); break;
|
|
964
|
-
case 'approve_gate': result = await toolApproveGate(args); break;
|
|
965
|
-
case 'get_pending_gates': result = toolGetPendingGates(args); break;
|
|
966
|
-
case 'add_roadmap_entry': result = await toolAddRoadmapEntry(args); break;
|
|
967
|
-
case 'set_feature_status': result = await toolSetFeatureStatus(args); break;
|
|
968
|
-
case 'roadmap_diff': result = await toolRoadmapDiff(args); break;
|
|
969
|
-
case 'get_roadmap': result = toolGetRoadmap(args); break;
|
|
970
|
-
case 'link_artifact': result = await toolLinkArtifact(args); break;
|
|
971
|
-
case 'link_features': result = await toolLinkFeatures(args); break;
|
|
972
|
-
case 'get_feature_artifacts': result = await toolGetFeatureArtifacts(args); break;
|
|
973
|
-
case 'get_feature_links': result = await toolGetFeatureLinks(args); break;
|
|
974
|
-
case 'add_changelog_entry': result = await toolAddChangelogEntry(args); break;
|
|
975
|
-
case 'get_changelog_entries': result = await toolGetChangelogEntries(args); break;
|
|
976
|
-
case 'write_journal_entry': result = await toolWriteJournalEntry(args); break;
|
|
977
|
-
case 'get_journal_entries': result = await toolGetJournalEntries(args); break;
|
|
978
|
-
case 'record_completion': result = await toolRecordCompletion(args); break;
|
|
979
|
-
case 'get_completions': result = await toolGetCompletions(args); break;
|
|
980
|
-
case 'validate_feature': result = await toolValidateFeature(args); break;
|
|
981
|
-
case 'validate_project': result = await toolValidateProject(args); break;
|
|
982
|
-
case 'roadmap_graph': result = await toolRoadmapGraph(args); break;
|
|
983
|
-
case 'roadmap_graph_check': result = await toolRoadmapGraphCheck(args); break;
|
|
984
|
-
case 'roadmap_xref_push': result = await toolRoadmapXrefPush(args); break;
|
|
985
|
-
case 'propose_followup': result = await toolProposeFollowup(args); break;
|
|
986
|
-
case 'write_checkpoint': result = await toolWriteCheckpoint(args); break;
|
|
987
|
-
case 'compose_resume': result = await toolComposeResume(args); break;
|
|
988
|
-
case 'judgment_position_create': result = await toolJudgmentPositionCreate(args); break;
|
|
989
|
-
case 'judgment_position_amend': result = await toolJudgmentPositionAmend(args); break;
|
|
990
|
-
case 'judgment_joint_add': result = await toolJudgmentJointAdd(args); break;
|
|
991
|
-
case 'judgment_transition': result = await toolJudgmentTransition(args); break;
|
|
992
|
-
case 'judgment_ledger_append': result = await toolJudgmentLedgerAppend(args); break;
|
|
993
|
-
case 'judgment_person_write': result = await toolJudgmentPersonWrite(args); break;
|
|
994
|
-
case 'judgment_situation_write': result = await toolJudgmentSituationWrite(args); break;
|
|
995
|
-
case 'judgment_goal_write': result = await toolJudgmentGoalWrite(args); break;
|
|
996
|
-
case 'get_judgment_state': result = await toolGetJudgmentState(args); break;
|
|
997
|
-
// agent_run removed — STRAT-DEDUP-AGENTRUN v1. Use mcp__stratum__stratum_agent_run.
|
|
998
|
-
default:
|
|
999
|
-
return {
|
|
1000
|
-
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
1001
|
-
isError: true,
|
|
1002
|
-
};
|
|
143
|
+
const ws = resolveWorkspace({ workspaceId: _getBinding(), cwd: getTargetRoot() });
|
|
144
|
+
binding = { ...prepareProject(ws.root), workspaceId: ws.id };
|
|
1003
145
|
}
|
|
1004
|
-
return {
|
|
1005
|
-
|
|
1006
|
-
|
|
146
|
+
return await withProjectContext(binding, async () => {
|
|
147
|
+
assertToolPhaseAllowed(name, args);
|
|
148
|
+
let result;
|
|
149
|
+
switch (name) {
|
|
150
|
+
case 'get_vision_items': result = toolGetVisionItems(args); break;
|
|
151
|
+
case 'get_item_detail': result = toolGetItemDetail(args); break;
|
|
152
|
+
case 'get_phase_summary': result = toolGetPhasesSummary(args); break;
|
|
153
|
+
case 'get_blocked_items': result = toolGetBlockedItems(); break;
|
|
154
|
+
case 'get_current_session': result = await toolGetCurrentSession(args); break;
|
|
155
|
+
case 'bind_session': result = await toolBindSession(args); break;
|
|
156
|
+
case 'set_workspace': result = toolSetWorkspace(args); break;
|
|
157
|
+
case 'get_workspace': result = toolGetWorkspace(); break;
|
|
158
|
+
case 'get_feature_lifecycle': result = toolGetFeatureLifecycle(args); break;
|
|
159
|
+
case 'kill_feature': result = await toolKillFeature(args); break;
|
|
160
|
+
case 'complete_feature': result = await toolCompleteFeature(args); break;
|
|
161
|
+
case 'backfill_completion': result = await toolBackfillCompletion(args); break;
|
|
162
|
+
case 'start_iteration_loop': result = await toolIterationStart(args); break;
|
|
163
|
+
case 'report_iteration_result': result = await toolIterationReport(args); break;
|
|
164
|
+
case 'abort_iteration_loop': result = await toolIterationAbort(args); break;
|
|
165
|
+
case 'assess_feature_artifacts': result = toolAssessFeatureArtifacts(args); break;
|
|
166
|
+
case 'scaffold_feature': result = toolScaffoldFeature(args); break;
|
|
167
|
+
case 'approve_gate': result = await toolApproveGate(args); break;
|
|
168
|
+
case 'get_pending_gates': result = toolGetPendingGates(args); break;
|
|
169
|
+
case 'add_roadmap_entry': result = await toolAddRoadmapEntry(args); break;
|
|
170
|
+
case 'set_feature_status': result = await toolSetFeatureStatus(args); break;
|
|
171
|
+
case 'roadmap_diff': result = await toolRoadmapDiff(args); break;
|
|
172
|
+
case 'get_roadmap': result = toolGetRoadmap(args); break;
|
|
173
|
+
case 'link_artifact': result = await toolLinkArtifact(args); break;
|
|
174
|
+
case 'link_features': result = await toolLinkFeatures(args); break;
|
|
175
|
+
case 'get_feature_artifacts': result = await toolGetFeatureArtifacts(args); break;
|
|
176
|
+
case 'get_feature_links': result = await toolGetFeatureLinks(args); break;
|
|
177
|
+
case 'add_changelog_entry': result = await toolAddChangelogEntry(args); break;
|
|
178
|
+
case 'canon_override_grant': result = await toolCanonOverrideGrant(args); break;
|
|
179
|
+
case 'get_changelog_entries': result = await toolGetChangelogEntries(args); break;
|
|
180
|
+
case 'write_journal_entry': result = await toolWriteJournalEntry(args); break;
|
|
181
|
+
case 'get_journal_entries': result = await toolGetJournalEntries(args); break;
|
|
182
|
+
case 'record_completion': result = await toolRecordCompletion(args); break;
|
|
183
|
+
case 'get_completions': result = await toolGetCompletions(args); break;
|
|
184
|
+
case 'validate_feature': result = await toolValidateFeature(args); break;
|
|
185
|
+
case 'validate_project': result = await toolValidateProject(args); break;
|
|
186
|
+
case 'roadmap_graph': result = await toolRoadmapGraph(args); break;
|
|
187
|
+
case 'roadmap_graph_check': result = await toolRoadmapGraphCheck(args); break;
|
|
188
|
+
case 'roadmap_xref_push': result = await toolRoadmapXrefPush(args); break;
|
|
189
|
+
case 'propose_followup': result = await toolProposeFollowup(args); break;
|
|
190
|
+
case 'write_checkpoint': result = await toolWriteCheckpoint(args); break;
|
|
191
|
+
case 'compose_resume': result = await toolComposeResume(args); break;
|
|
192
|
+
case 'judgment_position_create': result = await toolJudgmentPositionCreate(args); break;
|
|
193
|
+
case 'judgment_position_amend': result = await toolJudgmentPositionAmend(args); break;
|
|
194
|
+
case 'judgment_joint_add': result = await toolJudgmentJointAdd(args); break;
|
|
195
|
+
case 'judgment_transition': result = await toolJudgmentTransition(args); break;
|
|
196
|
+
case 'judgment_ledger_append': result = await toolJudgmentLedgerAppend(args); break;
|
|
197
|
+
case 'judgment_person_write': result = await toolJudgmentPersonWrite(args); break;
|
|
198
|
+
case 'judgment_situation_write': result = await toolJudgmentSituationWrite(args); break;
|
|
199
|
+
case 'judgment_goal_write': result = await toolJudgmentGoalWrite(args); break;
|
|
200
|
+
case 'get_judgment_state': result = await toolGetJudgmentState(args); break;
|
|
201
|
+
case 'get_judgment_trace': result = await toolGetJudgmentTrace(args); break;
|
|
202
|
+
// agent_run removed — STRAT-DEDUP-AGENTRUN v1. Use mcp__stratum__stratum_agent_run.
|
|
203
|
+
default:
|
|
204
|
+
return {
|
|
205
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
206
|
+
isError: true,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
211
|
+
};
|
|
212
|
+
});
|
|
1007
213
|
} catch (err) {
|
|
1008
214
|
// Surface typed error codes (e.g. INVALID_INPUT, CHANGELOG_FORMAT) when
|
|
1009
215
|
// tools attach them, so MCP callers can branch deterministically. Plain
|