@llm-dev-ops/agentics-cli 1.4.7 → 1.4.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/dist/cli/index.js +109 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/contracts/adr-006-claude-code-synthesis-runner.d.ts +196 -0
- package/dist/contracts/adr-006-claude-code-synthesis-runner.d.ts.map +1 -0
- package/dist/contracts/adr-006-claude-code-synthesis-runner.js +177 -0
- package/dist/contracts/adr-006-claude-code-synthesis-runner.js.map +1 -0
- package/dist/contracts/adr-007-subcommand-synthesis-router.d.ts +273 -0
- package/dist/contracts/adr-007-subcommand-synthesis-router.d.ts.map +1 -0
- package/dist/contracts/adr-007-subcommand-synthesis-router.js +226 -0
- package/dist/contracts/adr-007-subcommand-synthesis-router.js.map +1 -0
- package/dist/contracts/adr-008-synthesis-artifact-persistence.d.ts +323 -0
- package/dist/contracts/adr-008-synthesis-artifact-persistence.d.ts.map +1 -0
- package/dist/contracts/adr-008-synthesis-artifact-persistence.js +184 -0
- package/dist/contracts/adr-008-synthesis-artifact-persistence.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +35 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -0
- package/dist/mcp/mcp-server.js +692 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/runtime/claude-code-runner.d.ts +93 -0
- package/dist/runtime/claude-code-runner.d.ts.map +1 -0
- package/dist/runtime/claude-code-runner.js +588 -0
- package/dist/runtime/claude-code-runner.js.map +1 -0
- package/dist/runtime/index.d.ts +5 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +5 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/synthesis/artifact-writer.d.ts +62 -0
- package/dist/synthesis/artifact-writer.d.ts.map +1 -0
- package/dist/synthesis/artifact-writer.js +603 -0
- package/dist/synthesis/artifact-writer.js.map +1 -0
- package/dist/synthesis/index.d.ts +7 -0
- package/dist/synthesis/index.d.ts.map +1 -0
- package/dist/synthesis/index.js +7 -0
- package/dist/synthesis/index.js.map +1 -0
- package/dist/synthesis/prompts/index.d.ts +50 -0
- package/dist/synthesis/prompts/index.d.ts.map +1 -0
- package/dist/synthesis/prompts/index.js +502 -0
- package/dist/synthesis/prompts/index.js.map +1 -0
- package/dist/synthesis/router.d.ts +70 -0
- package/dist/synthesis/router.d.ts.map +1 -0
- package/dist/synthesis/router.js +346 -0
- package/dist/synthesis/router.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-006: Claude Code Synthesis Runner — Subprocess Invocation & Contract Binding
|
|
3
|
+
*
|
|
4
|
+
* STATUS: Proposed
|
|
5
|
+
* DATE: 2026-02-07
|
|
6
|
+
* AUTHORS: Platform Engineering
|
|
7
|
+
* DEPENDS-ON: ADR-001 (Command Semantics), ADR-002 (Operational Enforcement)
|
|
8
|
+
*
|
|
9
|
+
* ============================================================================
|
|
10
|
+
* CONTEXT
|
|
11
|
+
* ============================================================================
|
|
12
|
+
*
|
|
13
|
+
* The Agentics CLI needs to invoke Claude Code (the locally-installed Claude
|
|
14
|
+
* CLI binary) for decision-grade subcommands. This is modeled after how
|
|
15
|
+
* Claude Flow performs a single synthesis+plan step per command invocation.
|
|
16
|
+
*
|
|
17
|
+
* Currently, the CLI has an "executive synthesis" tool that runs as a detached
|
|
18
|
+
* fire-and-forget process (src/cli/index.ts:42-67). This is insufficient:
|
|
19
|
+
*
|
|
20
|
+
* - It does not capture Claude Code's output synchronously
|
|
21
|
+
* - It does not validate output against contract schemas
|
|
22
|
+
* - It is not subcommand-aware (fires on all commands that produce output)
|
|
23
|
+
* - It cannot feed structured JSON into the platform pipeline
|
|
24
|
+
*
|
|
25
|
+
* We need a focused module that:
|
|
26
|
+
* 1. Detects the Claude Code binary (claude, claude-code, or env-configured)
|
|
27
|
+
* 2. Invokes it synchronously via child_process.execFileSync or spawn+await
|
|
28
|
+
* 3. Sends a structured prompt via --print flag (non-interactive, JSON output)
|
|
29
|
+
* 4. Captures stdout, strips code fences, parses JSON
|
|
30
|
+
* 5. Validates against the agentics-contracts schema for that subcommand
|
|
31
|
+
* 6. Returns the typed object for downstream pipeline consumption
|
|
32
|
+
*
|
|
33
|
+
* ============================================================================
|
|
34
|
+
* DECISION
|
|
35
|
+
* ============================================================================
|
|
36
|
+
*
|
|
37
|
+
* 1. A new module `src/runtime/claude-code-runner.ts` will be created.
|
|
38
|
+
*
|
|
39
|
+
* 2. It will use Node.js `child_process.execFileSync` for synchronous
|
|
40
|
+
* single-invocation semantics (one call per decision command).
|
|
41
|
+
*
|
|
42
|
+
* 3. The binary is resolved in order:
|
|
43
|
+
* a. AGENTICS_CLAUDE_BIN environment variable (explicit path)
|
|
44
|
+
* b. `claude` on PATH (standard Claude Code CLI)
|
|
45
|
+
* c. `claude-code` on PATH (alternate binary name)
|
|
46
|
+
* If none found, throw a CLIError with code ECLI-SYNTH-001.
|
|
47
|
+
*
|
|
48
|
+
* 4. Invocation uses the `--print` flag for non-interactive JSON output:
|
|
49
|
+
* ```
|
|
50
|
+
* claude --print --output-format json --model <model> "<prompt>"
|
|
51
|
+
* ```
|
|
52
|
+
* The prompt is a single string constructed by the synthesis router.
|
|
53
|
+
*
|
|
54
|
+
* 5. Environment variables supported:
|
|
55
|
+
* - AGENTICS_CLAUDE_BIN: Override binary path
|
|
56
|
+
* - AGENTICS_CLAUDE_MODEL: Override model (default: claude-sonnet-4-20250514)
|
|
57
|
+
* - AGENTICS_CLAUDE_TIMEOUT_MS: Timeout (default: 120000)
|
|
58
|
+
* - AGENTICS_DEV: When set, enables verbose debug output to stderr
|
|
59
|
+
*
|
|
60
|
+
* 6. Output processing:
|
|
61
|
+
* a. Capture stdout as string
|
|
62
|
+
* b. Strip markdown code fences if present (```json ... ```)
|
|
63
|
+
* c. JSON.parse the result
|
|
64
|
+
* d. Validate against the contract schema for the given subcommand
|
|
65
|
+
* e. Return typed object or throw ContractValidationError
|
|
66
|
+
*
|
|
67
|
+
* 7. Each invocation includes a run-id and seed in the prompt for
|
|
68
|
+
* determinism and traceability.
|
|
69
|
+
*
|
|
70
|
+
* ============================================================================
|
|
71
|
+
* INTERFACE CONTRACT
|
|
72
|
+
* ============================================================================
|
|
73
|
+
*
|
|
74
|
+
* ```typescript
|
|
75
|
+
* interface ClaudeCodeRunnerOptions {
|
|
76
|
+
* model?: string;
|
|
77
|
+
* timeoutMs?: number;
|
|
78
|
+
* runId: string;
|
|
79
|
+
* seed?: number;
|
|
80
|
+
* verbose?: boolean;
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* interface ClaudeCodeRunnerResult<T> {
|
|
84
|
+
* data: T;
|
|
85
|
+
* runId: string;
|
|
86
|
+
* model: string;
|
|
87
|
+
* durationMs: number;
|
|
88
|
+
* rawOutput: string;
|
|
89
|
+
* }
|
|
90
|
+
*
|
|
91
|
+
* interface IClaudeCodeRunner {
|
|
92
|
+
* resolve(): string; // Returns binary path or throws
|
|
93
|
+
* invoke<T>(prompt: string, options: ClaudeCodeRunnerOptions): ClaudeCodeRunnerResult<T>;
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* ============================================================================
|
|
98
|
+
* ERROR CODES
|
|
99
|
+
* ============================================================================
|
|
100
|
+
*
|
|
101
|
+
* | Code | Meaning | Exit |
|
|
102
|
+
* |-------------------|---------------------------------------------|------|
|
|
103
|
+
* | ECLI-SYNTH-001 | Claude Code binary not found | 127 |
|
|
104
|
+
* | ECLI-SYNTH-002 | Claude Code invocation failed (non-zero) | 1 |
|
|
105
|
+
* | ECLI-SYNTH-003 | Output is not valid JSON | 140 |
|
|
106
|
+
* | ECLI-SYNTH-004 | Output failed contract validation | 140 |
|
|
107
|
+
* | ECLI-SYNTH-005 | Invocation timed out | 124 |
|
|
108
|
+
*
|
|
109
|
+
* ============================================================================
|
|
110
|
+
* ALTERNATIVES CONSIDERED
|
|
111
|
+
* ============================================================================
|
|
112
|
+
*
|
|
113
|
+
* A. Use the Anthropic API directly (HTTP client):
|
|
114
|
+
* Rejected — the requirement is to use the locally-installed Claude Code
|
|
115
|
+
* binary, matching Claude Flow's execution model. This also avoids
|
|
116
|
+
* managing API keys in the CLI when Claude Code already handles auth.
|
|
117
|
+
*
|
|
118
|
+
* B. Use the existing executive-synthesis detached process:
|
|
119
|
+
* Rejected — fire-and-forget cannot feed results into the platform
|
|
120
|
+
* pipeline. Synchronous capture is required.
|
|
121
|
+
*
|
|
122
|
+
* C. Use stdin piping instead of --print flag:
|
|
123
|
+
* Rejected — --print is the Claude Code standard for non-interactive
|
|
124
|
+
* programmatic use. Stdin piping is for interactive sessions.
|
|
125
|
+
*
|
|
126
|
+
* ============================================================================
|
|
127
|
+
* CONSEQUENCES
|
|
128
|
+
* ============================================================================
|
|
129
|
+
*
|
|
130
|
+
* - Claude Code must be installed locally for decision-grade commands
|
|
131
|
+
* - Commands that are SYNTHESIS_FORBIDDEN never invoke this module
|
|
132
|
+
* - Each decision-grade invocation has exactly one Claude Code call
|
|
133
|
+
* - All outputs are contract-validated before reaching the platform
|
|
134
|
+
* - Binary resolution is deterministic and debuggable via AGENTICS_DEV
|
|
135
|
+
*
|
|
136
|
+
* ============================================================================
|
|
137
|
+
* SECURITY CONSIDERATIONS
|
|
138
|
+
* ============================================================================
|
|
139
|
+
*
|
|
140
|
+
* - The prompt is constructed entirely from CLI arguments and templates;
|
|
141
|
+
* no user input is interpolated without sanitization.
|
|
142
|
+
* - The Claude Code binary inherits the user's environment but no
|
|
143
|
+
* additional secrets are passed beyond what's already in the shell.
|
|
144
|
+
* - Output is validated against a strict schema; malformed output is
|
|
145
|
+
* rejected with ECLI-SYNTH-003/004.
|
|
146
|
+
* - Timeout prevents runaway processes.
|
|
147
|
+
*/
|
|
148
|
+
/**
|
|
149
|
+
* Schema mapping: maps (command, subcommand) to the response schema name
|
|
150
|
+
* used for validating Claude Code output.
|
|
151
|
+
*
|
|
152
|
+
* This is the bridge between ADR-001 command semantics and the contract
|
|
153
|
+
* validator. Each decision-grade subcommand maps to exactly one schema.
|
|
154
|
+
*/
|
|
155
|
+
export const SYNTHESIS_SCHEMA_MAP = {
|
|
156
|
+
'simulate.create': 'simulation',
|
|
157
|
+
'simulate.run': 'simulation',
|
|
158
|
+
'plan.create': 'plan',
|
|
159
|
+
'plan.approve': 'plan',
|
|
160
|
+
'deploy.preview': 'intent',
|
|
161
|
+
'deploy.run': 'intent',
|
|
162
|
+
'deploy.rollback': 'intent',
|
|
163
|
+
'export.terraform': 'export',
|
|
164
|
+
'export.kubernetes': 'export',
|
|
165
|
+
'export.erp': 'export',
|
|
166
|
+
'policy.create': 'base',
|
|
167
|
+
'policy.edit': 'base',
|
|
168
|
+
'policy.enable': 'base',
|
|
169
|
+
'policy.disable': 'base',
|
|
170
|
+
'policy.dry-run': 'base',
|
|
171
|
+
'quantify.create': 'roiReport',
|
|
172
|
+
'quantify.compare': 'roiReport',
|
|
173
|
+
'erp.surface': 'base',
|
|
174
|
+
'erp.map': 'base',
|
|
175
|
+
'erp.export': 'export',
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=adr-006-claude-code-synthesis-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr-006-claude-code-synthesis-runner.js","sourceRoot":"","sources":["../../src/contracts/adr-006-claude-code-synthesis-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkJG;AAkDH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAqC;IACpE,iBAAiB,EAAE,YAAY;IAC/B,cAAc,EAAE,YAAY;IAC5B,aAAa,EAAE,MAAM;IACrB,cAAc,EAAE,MAAM;IACtB,gBAAgB,EAAE,QAAQ;IAC1B,YAAY,EAAE,QAAQ;IACtB,iBAAiB,EAAE,QAAQ;IAC3B,kBAAkB,EAAE,QAAQ;IAC5B,mBAAmB,EAAE,QAAQ;IAC7B,YAAY,EAAE,QAAQ;IACtB,eAAe,EAAE,MAAM;IACvB,aAAa,EAAE,MAAM;IACrB,eAAe,EAAE,MAAM;IACvB,gBAAgB,EAAE,MAAM;IACxB,gBAAgB,EAAE,MAAM;IACxB,iBAAiB,EAAE,WAAW;IAC9B,kBAAkB,EAAE,WAAW;IAC/B,aAAa,EAAE,MAAM;IACrB,SAAS,EAAE,MAAM;IACjB,YAAY,EAAE,QAAQ;CACd,CAAC"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-007: Subcommand-Aware Synthesis Router
|
|
3
|
+
*
|
|
4
|
+
* STATUS: Proposed
|
|
5
|
+
* DATE: 2026-02-07
|
|
6
|
+
* AUTHORS: Platform Engineering
|
|
7
|
+
* DEPENDS-ON: ADR-001 (Command Semantics), ADR-006 (Claude Code Runner)
|
|
8
|
+
*
|
|
9
|
+
* ============================================================================
|
|
10
|
+
* CONTEXT
|
|
11
|
+
* ============================================================================
|
|
12
|
+
*
|
|
13
|
+
* ADR-001 defines a COMMAND_REGISTRY with synthesis governance classifications:
|
|
14
|
+
* - SYNTHESIS_REQUIRED: LLM invocation expected
|
|
15
|
+
* - SYNTHESIS_FORBIDDEN: Must NEVER trigger synthesis
|
|
16
|
+
* - COMMITMENT_GRADE: Requires ID + confirmation + synthesis
|
|
17
|
+
*
|
|
18
|
+
* The current CLI dispatches commands via a monolithic switch statement in
|
|
19
|
+
* src/cli/index.ts. Decision-grade subcommands call their respective
|
|
20
|
+
* command executors (executePlanCreateCommand, executeSimulateRunCommand, etc.)
|
|
21
|
+
* which talk to the platform API. The executive synthesis tool fires as an
|
|
22
|
+
* afterthought (fire-and-forget detached process).
|
|
23
|
+
*
|
|
24
|
+
* What's missing is a routing layer that sits BETWEEN argument parsing and
|
|
25
|
+
* command execution, intercepting decision-grade subcommands to:
|
|
26
|
+
* 1. Construct a subcommand-specific prompt
|
|
27
|
+
* 2. Call Claude Code Runner (ADR-006)
|
|
28
|
+
* 3. Validate the output
|
|
29
|
+
* 4. Feed it into the platform pipeline
|
|
30
|
+
*
|
|
31
|
+
* ============================================================================
|
|
32
|
+
* DECISION
|
|
33
|
+
* ============================================================================
|
|
34
|
+
*
|
|
35
|
+
* 1. A new module `src/synthesis/router.ts` will implement the synthesis
|
|
36
|
+
* routing layer.
|
|
37
|
+
*
|
|
38
|
+
* 2. The router takes a SynthesisRequest:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* interface SynthesisRequest {
|
|
41
|
+
* command: string; // e.g. "simulate"
|
|
42
|
+
* subcommand: string; // e.g. "create"
|
|
43
|
+
* positionalArgs: string[]; // from parsed CLI args
|
|
44
|
+
* options: Record<string, string>;
|
|
45
|
+
* flags: Record<string, boolean>;
|
|
46
|
+
* userContext: {
|
|
47
|
+
* userId: string;
|
|
48
|
+
* orgId: string;
|
|
49
|
+
* traceId: string;
|
|
50
|
+
* };
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* 3. Routing logic:
|
|
55
|
+
* a. Look up (command, subcommand) in ADR-001 COMMAND_REGISTRY
|
|
56
|
+
* b. If synthesis === 'SYNTHESIS_FORBIDDEN', return null immediately
|
|
57
|
+
* c. If synthesis === 'SYNTHESIS_REQUIRED' or 'COMMITMENT_GRADE':
|
|
58
|
+
* i. Generate a run-id (UUID v4)
|
|
59
|
+
* ii. Load the prompt template for this (command, subcommand)
|
|
60
|
+
* iii. Inject arguments, context, run-id, and contract requirements
|
|
61
|
+
* iv. Call ClaudeCodeRunner.invoke()
|
|
62
|
+
* v. Return the validated SynthesisResult
|
|
63
|
+
*
|
|
64
|
+
* 4. SynthesisResult structure:
|
|
65
|
+
* ```typescript
|
|
66
|
+
* interface SynthesisResult<T> {
|
|
67
|
+
* data: T; // Contract-validated output
|
|
68
|
+
* runId: string; // UUID for this synthesis run
|
|
69
|
+
* command: string;
|
|
70
|
+
* subcommand: string;
|
|
71
|
+
* model: string; // Model used
|
|
72
|
+
* durationMs: number;
|
|
73
|
+
* contractSchema: string; // Schema name used for validation
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* 5. The router is a pure function with no side effects beyond calling
|
|
78
|
+
* ClaudeCodeRunner. It does NOT:
|
|
79
|
+
* - Write artifacts (that's ADR-008)
|
|
80
|
+
* - Call the platform API (that's the command executor)
|
|
81
|
+
* - Modify CLI state
|
|
82
|
+
*
|
|
83
|
+
* ============================================================================
|
|
84
|
+
* PROMPT TEMPLATE SYSTEM
|
|
85
|
+
* ============================================================================
|
|
86
|
+
*
|
|
87
|
+
* 1. Templates live in `src/synthesis/prompts/` as exported string constants
|
|
88
|
+
* (not .txt files — TypeScript provides compile-time safety and tree-shaking).
|
|
89
|
+
*
|
|
90
|
+
* 2. Each template is a function: (args: PromptArgs) => string
|
|
91
|
+
*
|
|
92
|
+
* 3. PromptArgs includes:
|
|
93
|
+
* - runId: string
|
|
94
|
+
* - seed: number
|
|
95
|
+
* - command: string
|
|
96
|
+
* - subcommand: string
|
|
97
|
+
* - positionalArgs: string[]
|
|
98
|
+
* - contractSchemaName: string
|
|
99
|
+
* - contractSchemaFields: string (human-readable field list)
|
|
100
|
+
*
|
|
101
|
+
* 4. Every template MUST include:
|
|
102
|
+
* - "Respond ONLY with a JSON object. No prose, no markdown, no explanation."
|
|
103
|
+
* - The exact contract schema name
|
|
104
|
+
* - The run-id and seed
|
|
105
|
+
* - The required fields for the output schema
|
|
106
|
+
*
|
|
107
|
+
* 5. Template naming: `{command}_{subcommand}` (e.g., simulate_create)
|
|
108
|
+
*
|
|
109
|
+
* ============================================================================
|
|
110
|
+
* DECISION-GRADE SUBCOMMAND MATRIX
|
|
111
|
+
* ============================================================================
|
|
112
|
+
*
|
|
113
|
+
* | Command | Subcommand | Synthesis Class | Contract Schema |
|
|
114
|
+
* |-----------|------------|----------------------|------------------|
|
|
115
|
+
* | simulate | create | SYNTHESIS_REQUIRED | simulation |
|
|
116
|
+
* | simulate | run | COMMITMENT_GRADE | simulation |
|
|
117
|
+
* | plan | create | SYNTHESIS_REQUIRED | plan |
|
|
118
|
+
* | plan | approve | COMMITMENT_GRADE | plan |
|
|
119
|
+
* | deploy | preview | SYNTHESIS_REQUIRED | intent |
|
|
120
|
+
* | deploy | run | COMMITMENT_GRADE | intent |
|
|
121
|
+
* | deploy | rollback | COMMITMENT_GRADE | intent |
|
|
122
|
+
* | export | terraform | SYNTHESIS_REQUIRED | export |
|
|
123
|
+
* | export | kubernetes | SYNTHESIS_REQUIRED | export |
|
|
124
|
+
* | export | erp | SYNTHESIS_REQUIRED | export |
|
|
125
|
+
* | policy | create | SYNTHESIS_REQUIRED | base |
|
|
126
|
+
* | policy | edit | SYNTHESIS_REQUIRED | base |
|
|
127
|
+
* | policy | enable | COMMITMENT_GRADE | base |
|
|
128
|
+
* | policy | disable | SYNTHESIS_REQUIRED | base |
|
|
129
|
+
* | policy | dry-run | SYNTHESIS_REQUIRED | base |
|
|
130
|
+
* | quantify | create | SYNTHESIS_REQUIRED | roiReport |
|
|
131
|
+
* | quantify | compare | COMMITMENT_GRADE | roiReport |
|
|
132
|
+
* | erp | surface | SYNTHESIS_REQUIRED | base |
|
|
133
|
+
* | erp | map | SYNTHESIS_REQUIRED | base |
|
|
134
|
+
* | erp | export | SYNTHESIS_REQUIRED | export |
|
|
135
|
+
*
|
|
136
|
+
* All other (command, subcommand) combinations return null from the router.
|
|
137
|
+
*
|
|
138
|
+
* ============================================================================
|
|
139
|
+
* INTEGRATION POINT
|
|
140
|
+
* ============================================================================
|
|
141
|
+
*
|
|
142
|
+
* The router is called from the CLI dispatch in src/cli/index.ts.
|
|
143
|
+
* The integration follows this pattern:
|
|
144
|
+
*
|
|
145
|
+
* ```typescript
|
|
146
|
+
* // In the command handler (e.g., simulate create)
|
|
147
|
+
* const synthesisResult = synthesisRouter.route({
|
|
148
|
+
* command: parsed.command,
|
|
149
|
+
* subcommand: parsed.subcommand,
|
|
150
|
+
* positionalArgs: parsed.positionalArgs,
|
|
151
|
+
* options: parsed.options,
|
|
152
|
+
* flags: parsed.flags,
|
|
153
|
+
* userContext: { userId, orgId, traceId },
|
|
154
|
+
* });
|
|
155
|
+
*
|
|
156
|
+
* if (synthesisResult) {
|
|
157
|
+
* // Decision-grade: use Claude Code output
|
|
158
|
+
* const platformResult = await executeWithSynthesis(synthesisResult);
|
|
159
|
+
* await persistArtifacts(synthesisResult, platformResult);
|
|
160
|
+
* } else {
|
|
161
|
+
* // Non-synthesis: proceed with existing command handler
|
|
162
|
+
* await executeExistingHandler(...);
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* ============================================================================
|
|
167
|
+
* ALTERNATIVES CONSIDERED
|
|
168
|
+
* ============================================================================
|
|
169
|
+
*
|
|
170
|
+
* A. Middleware-based routing (intercept all commands):
|
|
171
|
+
* Rejected — synthesis is the exception, not the rule. A middleware
|
|
172
|
+
* pattern would add overhead to every command, including the majority
|
|
173
|
+
* that are SYNTHESIS_FORBIDDEN.
|
|
174
|
+
*
|
|
175
|
+
* B. Prompt templates as external .txt files:
|
|
176
|
+
* Rejected — TypeScript functions provide compile-time safety,
|
|
177
|
+
* argument validation, and can reference contract types. External
|
|
178
|
+
* files would need a runtime loader and lose type safety.
|
|
179
|
+
*
|
|
180
|
+
* C. One giant prompt for all subcommands:
|
|
181
|
+
* Rejected — each subcommand has unique argument shapes, contract
|
|
182
|
+
* schemas, and domain-specific instructions. Specialized prompts
|
|
183
|
+
* produce better-structured output.
|
|
184
|
+
*
|
|
185
|
+
* ============================================================================
|
|
186
|
+
* CONSEQUENCES
|
|
187
|
+
* ============================================================================
|
|
188
|
+
*
|
|
189
|
+
* - Every decision-grade subcommand gets exactly one Claude Code call
|
|
190
|
+
* - Non-decision commands have zero synthesis overhead
|
|
191
|
+
* - Prompt templates are version-controlled and type-safe
|
|
192
|
+
* - New decision-grade subcommands require:
|
|
193
|
+
* a. ADR-001 COMMAND_REGISTRY entry with SYNTHESIS_REQUIRED/COMMITMENT_GRADE
|
|
194
|
+
* b. ADR-006 SYNTHESIS_SCHEMA_MAP entry
|
|
195
|
+
* c. A prompt template function in src/synthesis/prompts/
|
|
196
|
+
* d. CLI handler integration per the pattern above
|
|
197
|
+
* - The router is stateless and testable in isolation
|
|
198
|
+
*/
|
|
199
|
+
/**
|
|
200
|
+
* Narrowed synthesis governance class for decision-grade subcommands.
|
|
201
|
+
* SYNTHESIS_FORBIDDEN commands never reach the router — only these two are valid.
|
|
202
|
+
*/
|
|
203
|
+
export type SynthesisGovernanceClass = 'SYNTHESIS_REQUIRED' | 'COMMITMENT_GRADE';
|
|
204
|
+
export interface SynthesisRequest {
|
|
205
|
+
readonly command: string;
|
|
206
|
+
readonly subcommand: string;
|
|
207
|
+
readonly positionalArgs: readonly string[];
|
|
208
|
+
readonly options: Readonly<Record<string, string>>;
|
|
209
|
+
readonly flags: Readonly<Record<string, boolean>>;
|
|
210
|
+
readonly userContext: {
|
|
211
|
+
readonly userId: string;
|
|
212
|
+
readonly orgId: string;
|
|
213
|
+
readonly traceId: string;
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
export interface SynthesisResult<T = unknown> {
|
|
217
|
+
/** Contract-validated output from Claude Code */
|
|
218
|
+
readonly data: T;
|
|
219
|
+
/** UUID for this synthesis run */
|
|
220
|
+
readonly runId: string;
|
|
221
|
+
/** Primary command */
|
|
222
|
+
readonly command: string;
|
|
223
|
+
/** Subcommand */
|
|
224
|
+
readonly subcommand: string;
|
|
225
|
+
/** Model used for synthesis */
|
|
226
|
+
readonly model: string;
|
|
227
|
+
/** Duration of Claude Code invocation */
|
|
228
|
+
readonly durationMs: number;
|
|
229
|
+
/** Contract schema used for validation */
|
|
230
|
+
readonly contractSchema: string;
|
|
231
|
+
/** Raw Claude Code output (for artifact persistence) */
|
|
232
|
+
readonly rawOutput: string;
|
|
233
|
+
/** ADR-001 synthesis governance classification */
|
|
234
|
+
readonly synthesisClass: SynthesisGovernanceClass;
|
|
235
|
+
/** The prompt that was sent to Claude Code (for artifact persistence and debugging) */
|
|
236
|
+
readonly prompt: string;
|
|
237
|
+
}
|
|
238
|
+
export interface PromptArgs {
|
|
239
|
+
readonly runId: string;
|
|
240
|
+
readonly seed: number;
|
|
241
|
+
readonly command: string;
|
|
242
|
+
readonly subcommand: string;
|
|
243
|
+
readonly positionalArgs: readonly string[];
|
|
244
|
+
readonly options: Readonly<Record<string, string>>;
|
|
245
|
+
readonly contractSchemaName: string;
|
|
246
|
+
}
|
|
247
|
+
/** Type for prompt template functions */
|
|
248
|
+
export type PromptTemplate = (args: PromptArgs) => string;
|
|
249
|
+
/**
|
|
250
|
+
* Result of building a synthesis prompt without invoking Claude Code.
|
|
251
|
+
* Used for dry-run mode and testing.
|
|
252
|
+
*/
|
|
253
|
+
export interface SynthesisPromptResult {
|
|
254
|
+
/** The fully-constructed prompt string */
|
|
255
|
+
readonly prompt: string;
|
|
256
|
+
/** Generated run identifier */
|
|
257
|
+
readonly runId: string;
|
|
258
|
+
/** Generated seed for determinism */
|
|
259
|
+
readonly seed: number;
|
|
260
|
+
/** The (command.subcommand) routing key */
|
|
261
|
+
readonly key: string;
|
|
262
|
+
/** Contract schema name for validation */
|
|
263
|
+
readonly contractSchema: string;
|
|
264
|
+
/** ADR-001 synthesis governance classification */
|
|
265
|
+
readonly synthesisClass: SynthesisGovernanceClass;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The decision-grade subcommand set.
|
|
269
|
+
* This is the canonical list; any subcommand NOT in this set
|
|
270
|
+
* must NEVER trigger Claude Code invocation.
|
|
271
|
+
*/
|
|
272
|
+
export declare const DECISION_GRADE_SUBCOMMANDS: ReadonlySet<string>;
|
|
273
|
+
//# sourceMappingURL=adr-007-subcommand-synthesis-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr-007-subcommand-synthesis-router.d.ts","sourceRoot":"","sources":["../../src/contracts/adr-007-subcommand-synthesis-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-007: Subcommand-Aware Synthesis Router
|
|
3
|
+
*
|
|
4
|
+
* STATUS: Proposed
|
|
5
|
+
* DATE: 2026-02-07
|
|
6
|
+
* AUTHORS: Platform Engineering
|
|
7
|
+
* DEPENDS-ON: ADR-001 (Command Semantics), ADR-006 (Claude Code Runner)
|
|
8
|
+
*
|
|
9
|
+
* ============================================================================
|
|
10
|
+
* CONTEXT
|
|
11
|
+
* ============================================================================
|
|
12
|
+
*
|
|
13
|
+
* ADR-001 defines a COMMAND_REGISTRY with synthesis governance classifications:
|
|
14
|
+
* - SYNTHESIS_REQUIRED: LLM invocation expected
|
|
15
|
+
* - SYNTHESIS_FORBIDDEN: Must NEVER trigger synthesis
|
|
16
|
+
* - COMMITMENT_GRADE: Requires ID + confirmation + synthesis
|
|
17
|
+
*
|
|
18
|
+
* The current CLI dispatches commands via a monolithic switch statement in
|
|
19
|
+
* src/cli/index.ts. Decision-grade subcommands call their respective
|
|
20
|
+
* command executors (executePlanCreateCommand, executeSimulateRunCommand, etc.)
|
|
21
|
+
* which talk to the platform API. The executive synthesis tool fires as an
|
|
22
|
+
* afterthought (fire-and-forget detached process).
|
|
23
|
+
*
|
|
24
|
+
* What's missing is a routing layer that sits BETWEEN argument parsing and
|
|
25
|
+
* command execution, intercepting decision-grade subcommands to:
|
|
26
|
+
* 1. Construct a subcommand-specific prompt
|
|
27
|
+
* 2. Call Claude Code Runner (ADR-006)
|
|
28
|
+
* 3. Validate the output
|
|
29
|
+
* 4. Feed it into the platform pipeline
|
|
30
|
+
*
|
|
31
|
+
* ============================================================================
|
|
32
|
+
* DECISION
|
|
33
|
+
* ============================================================================
|
|
34
|
+
*
|
|
35
|
+
* 1. A new module `src/synthesis/router.ts` will implement the synthesis
|
|
36
|
+
* routing layer.
|
|
37
|
+
*
|
|
38
|
+
* 2. The router takes a SynthesisRequest:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* interface SynthesisRequest {
|
|
41
|
+
* command: string; // e.g. "simulate"
|
|
42
|
+
* subcommand: string; // e.g. "create"
|
|
43
|
+
* positionalArgs: string[]; // from parsed CLI args
|
|
44
|
+
* options: Record<string, string>;
|
|
45
|
+
* flags: Record<string, boolean>;
|
|
46
|
+
* userContext: {
|
|
47
|
+
* userId: string;
|
|
48
|
+
* orgId: string;
|
|
49
|
+
* traceId: string;
|
|
50
|
+
* };
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* 3. Routing logic:
|
|
55
|
+
* a. Look up (command, subcommand) in ADR-001 COMMAND_REGISTRY
|
|
56
|
+
* b. If synthesis === 'SYNTHESIS_FORBIDDEN', return null immediately
|
|
57
|
+
* c. If synthesis === 'SYNTHESIS_REQUIRED' or 'COMMITMENT_GRADE':
|
|
58
|
+
* i. Generate a run-id (UUID v4)
|
|
59
|
+
* ii. Load the prompt template for this (command, subcommand)
|
|
60
|
+
* iii. Inject arguments, context, run-id, and contract requirements
|
|
61
|
+
* iv. Call ClaudeCodeRunner.invoke()
|
|
62
|
+
* v. Return the validated SynthesisResult
|
|
63
|
+
*
|
|
64
|
+
* 4. SynthesisResult structure:
|
|
65
|
+
* ```typescript
|
|
66
|
+
* interface SynthesisResult<T> {
|
|
67
|
+
* data: T; // Contract-validated output
|
|
68
|
+
* runId: string; // UUID for this synthesis run
|
|
69
|
+
* command: string;
|
|
70
|
+
* subcommand: string;
|
|
71
|
+
* model: string; // Model used
|
|
72
|
+
* durationMs: number;
|
|
73
|
+
* contractSchema: string; // Schema name used for validation
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* 5. The router is a pure function with no side effects beyond calling
|
|
78
|
+
* ClaudeCodeRunner. It does NOT:
|
|
79
|
+
* - Write artifacts (that's ADR-008)
|
|
80
|
+
* - Call the platform API (that's the command executor)
|
|
81
|
+
* - Modify CLI state
|
|
82
|
+
*
|
|
83
|
+
* ============================================================================
|
|
84
|
+
* PROMPT TEMPLATE SYSTEM
|
|
85
|
+
* ============================================================================
|
|
86
|
+
*
|
|
87
|
+
* 1. Templates live in `src/synthesis/prompts/` as exported string constants
|
|
88
|
+
* (not .txt files — TypeScript provides compile-time safety and tree-shaking).
|
|
89
|
+
*
|
|
90
|
+
* 2. Each template is a function: (args: PromptArgs) => string
|
|
91
|
+
*
|
|
92
|
+
* 3. PromptArgs includes:
|
|
93
|
+
* - runId: string
|
|
94
|
+
* - seed: number
|
|
95
|
+
* - command: string
|
|
96
|
+
* - subcommand: string
|
|
97
|
+
* - positionalArgs: string[]
|
|
98
|
+
* - contractSchemaName: string
|
|
99
|
+
* - contractSchemaFields: string (human-readable field list)
|
|
100
|
+
*
|
|
101
|
+
* 4. Every template MUST include:
|
|
102
|
+
* - "Respond ONLY with a JSON object. No prose, no markdown, no explanation."
|
|
103
|
+
* - The exact contract schema name
|
|
104
|
+
* - The run-id and seed
|
|
105
|
+
* - The required fields for the output schema
|
|
106
|
+
*
|
|
107
|
+
* 5. Template naming: `{command}_{subcommand}` (e.g., simulate_create)
|
|
108
|
+
*
|
|
109
|
+
* ============================================================================
|
|
110
|
+
* DECISION-GRADE SUBCOMMAND MATRIX
|
|
111
|
+
* ============================================================================
|
|
112
|
+
*
|
|
113
|
+
* | Command | Subcommand | Synthesis Class | Contract Schema |
|
|
114
|
+
* |-----------|------------|----------------------|------------------|
|
|
115
|
+
* | simulate | create | SYNTHESIS_REQUIRED | simulation |
|
|
116
|
+
* | simulate | run | COMMITMENT_GRADE | simulation |
|
|
117
|
+
* | plan | create | SYNTHESIS_REQUIRED | plan |
|
|
118
|
+
* | plan | approve | COMMITMENT_GRADE | plan |
|
|
119
|
+
* | deploy | preview | SYNTHESIS_REQUIRED | intent |
|
|
120
|
+
* | deploy | run | COMMITMENT_GRADE | intent |
|
|
121
|
+
* | deploy | rollback | COMMITMENT_GRADE | intent |
|
|
122
|
+
* | export | terraform | SYNTHESIS_REQUIRED | export |
|
|
123
|
+
* | export | kubernetes | SYNTHESIS_REQUIRED | export |
|
|
124
|
+
* | export | erp | SYNTHESIS_REQUIRED | export |
|
|
125
|
+
* | policy | create | SYNTHESIS_REQUIRED | base |
|
|
126
|
+
* | policy | edit | SYNTHESIS_REQUIRED | base |
|
|
127
|
+
* | policy | enable | COMMITMENT_GRADE | base |
|
|
128
|
+
* | policy | disable | SYNTHESIS_REQUIRED | base |
|
|
129
|
+
* | policy | dry-run | SYNTHESIS_REQUIRED | base |
|
|
130
|
+
* | quantify | create | SYNTHESIS_REQUIRED | roiReport |
|
|
131
|
+
* | quantify | compare | COMMITMENT_GRADE | roiReport |
|
|
132
|
+
* | erp | surface | SYNTHESIS_REQUIRED | base |
|
|
133
|
+
* | erp | map | SYNTHESIS_REQUIRED | base |
|
|
134
|
+
* | erp | export | SYNTHESIS_REQUIRED | export |
|
|
135
|
+
*
|
|
136
|
+
* All other (command, subcommand) combinations return null from the router.
|
|
137
|
+
*
|
|
138
|
+
* ============================================================================
|
|
139
|
+
* INTEGRATION POINT
|
|
140
|
+
* ============================================================================
|
|
141
|
+
*
|
|
142
|
+
* The router is called from the CLI dispatch in src/cli/index.ts.
|
|
143
|
+
* The integration follows this pattern:
|
|
144
|
+
*
|
|
145
|
+
* ```typescript
|
|
146
|
+
* // In the command handler (e.g., simulate create)
|
|
147
|
+
* const synthesisResult = synthesisRouter.route({
|
|
148
|
+
* command: parsed.command,
|
|
149
|
+
* subcommand: parsed.subcommand,
|
|
150
|
+
* positionalArgs: parsed.positionalArgs,
|
|
151
|
+
* options: parsed.options,
|
|
152
|
+
* flags: parsed.flags,
|
|
153
|
+
* userContext: { userId, orgId, traceId },
|
|
154
|
+
* });
|
|
155
|
+
*
|
|
156
|
+
* if (synthesisResult) {
|
|
157
|
+
* // Decision-grade: use Claude Code output
|
|
158
|
+
* const platformResult = await executeWithSynthesis(synthesisResult);
|
|
159
|
+
* await persistArtifacts(synthesisResult, platformResult);
|
|
160
|
+
* } else {
|
|
161
|
+
* // Non-synthesis: proceed with existing command handler
|
|
162
|
+
* await executeExistingHandler(...);
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* ============================================================================
|
|
167
|
+
* ALTERNATIVES CONSIDERED
|
|
168
|
+
* ============================================================================
|
|
169
|
+
*
|
|
170
|
+
* A. Middleware-based routing (intercept all commands):
|
|
171
|
+
* Rejected — synthesis is the exception, not the rule. A middleware
|
|
172
|
+
* pattern would add overhead to every command, including the majority
|
|
173
|
+
* that are SYNTHESIS_FORBIDDEN.
|
|
174
|
+
*
|
|
175
|
+
* B. Prompt templates as external .txt files:
|
|
176
|
+
* Rejected — TypeScript functions provide compile-time safety,
|
|
177
|
+
* argument validation, and can reference contract types. External
|
|
178
|
+
* files would need a runtime loader and lose type safety.
|
|
179
|
+
*
|
|
180
|
+
* C. One giant prompt for all subcommands:
|
|
181
|
+
* Rejected — each subcommand has unique argument shapes, contract
|
|
182
|
+
* schemas, and domain-specific instructions. Specialized prompts
|
|
183
|
+
* produce better-structured output.
|
|
184
|
+
*
|
|
185
|
+
* ============================================================================
|
|
186
|
+
* CONSEQUENCES
|
|
187
|
+
* ============================================================================
|
|
188
|
+
*
|
|
189
|
+
* - Every decision-grade subcommand gets exactly one Claude Code call
|
|
190
|
+
* - Non-decision commands have zero synthesis overhead
|
|
191
|
+
* - Prompt templates are version-controlled and type-safe
|
|
192
|
+
* - New decision-grade subcommands require:
|
|
193
|
+
* a. ADR-001 COMMAND_REGISTRY entry with SYNTHESIS_REQUIRED/COMMITMENT_GRADE
|
|
194
|
+
* b. ADR-006 SYNTHESIS_SCHEMA_MAP entry
|
|
195
|
+
* c. A prompt template function in src/synthesis/prompts/
|
|
196
|
+
* d. CLI handler integration per the pattern above
|
|
197
|
+
* - The router is stateless and testable in isolation
|
|
198
|
+
*/
|
|
199
|
+
/**
|
|
200
|
+
* The decision-grade subcommand set.
|
|
201
|
+
* This is the canonical list; any subcommand NOT in this set
|
|
202
|
+
* must NEVER trigger Claude Code invocation.
|
|
203
|
+
*/
|
|
204
|
+
export const DECISION_GRADE_SUBCOMMANDS = new Set([
|
|
205
|
+
'simulate.create',
|
|
206
|
+
'simulate.run',
|
|
207
|
+
'plan.create',
|
|
208
|
+
'plan.approve',
|
|
209
|
+
'deploy.preview',
|
|
210
|
+
'deploy.run',
|
|
211
|
+
'deploy.rollback',
|
|
212
|
+
'export.terraform',
|
|
213
|
+
'export.kubernetes',
|
|
214
|
+
'export.erp',
|
|
215
|
+
'policy.create',
|
|
216
|
+
'policy.edit',
|
|
217
|
+
'policy.enable',
|
|
218
|
+
'policy.disable',
|
|
219
|
+
'policy.dry-run',
|
|
220
|
+
'quantify.create',
|
|
221
|
+
'quantify.compare',
|
|
222
|
+
'erp.surface',
|
|
223
|
+
'erp.map',
|
|
224
|
+
'erp.export',
|
|
225
|
+
]);
|
|
226
|
+
//# sourceMappingURL=adr-007-subcommand-synthesis-router.js.map
|