@spikedpunch/align-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/align-dir.d.ts +55 -0
- package/dist/align-dir.d.ts.map +1 -0
- package/dist/align-dir.js +184 -0
- package/dist/align-dir.js.map +1 -0
- package/dist/commands/agent.d.ts +14 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +142 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/baseline.d.ts +4 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +57 -0
- package/dist/commands/baseline.js.map +1 -0
- package/dist/commands/build-report.d.ts +4 -0
- package/dist/commands/build-report.d.ts.map +1 -0
- package/dist/commands/build-report.js +122 -0
- package/dist/commands/build-report.js.map +1 -0
- package/dist/commands/build.d.ts +73 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +289 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/check.d.ts +31 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +203 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/doctor.d.ts +20 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +173 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/explain.d.ts +3 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +54 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/export-ir.d.ts +21 -0
- package/dist/commands/export-ir.d.ts.map +1 -0
- package/dist/commands/export-ir.js +33 -0
- package/dist/commands/export-ir.js.map +1 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +93 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/skill.d.ts +20 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +23 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/telemetry.d.ts +52 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +238 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/composition-root.d.ts +14 -0
- package/dist/composition-root.d.ts.map +1 -0
- package/dist/composition-root.js +18 -0
- package/dist/composition-root.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +39 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/init/claude-md.d.ts +6 -0
- package/dist/init/claude-md.d.ts.map +1 -0
- package/dist/init/claude-md.js +42 -0
- package/dist/init/claude-md.js.map +1 -0
- package/dist/init/config-comment.d.ts +7 -0
- package/dist/init/config-comment.d.ts.map +1 -0
- package/dist/init/config-comment.js +44 -0
- package/dist/init/config-comment.js.map +1 -0
- package/dist/init/detect-components.d.ts +16 -0
- package/dist/init/detect-components.d.ts.map +1 -0
- package/dist/init/detect-components.js +121 -0
- package/dist/init/detect-components.js.map +1 -0
- package/dist/init/gitignore.d.ts +8 -0
- package/dist/init/gitignore.d.ts.map +1 -0
- package/dist/init/gitignore.js +27 -0
- package/dist/init/gitignore.js.map +1 -0
- package/dist/init/render-config.d.ts +18 -0
- package/dist/init/render-config.d.ts.map +1 -0
- package/dist/init/render-config.js +57 -0
- package/dist/init/render-config.js.map +1 -0
- package/dist/init/suggest-layers.d.ts +16 -0
- package/dist/init/suggest-layers.d.ts.map +1 -0
- package/dist/init/suggest-layers.js +65 -0
- package/dist/init/suggest-layers.js.map +1 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +182 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/program.d.ts +11 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +199 -0
- package/dist/program.js.map +1 -0
- package/dist/skill/bullet-grammar.d.ts +2 -0
- package/dist/skill/bullet-grammar.d.ts.map +1 -0
- package/dist/skill/bullet-grammar.js +12 -0
- package/dist/skill/bullet-grammar.js.map +1 -0
- package/dist/skill/cli-inventory.d.ts +16 -0
- package/dist/skill/cli-inventory.d.ts.map +1 -0
- package/dist/skill/cli-inventory.js +17 -0
- package/dist/skill/cli-inventory.js.map +1 -0
- package/dist/skill/condensed.d.ts +2 -0
- package/dist/skill/condensed.d.ts.map +1 -0
- package/dist/skill/condensed.js +24 -0
- package/dist/skill/condensed.js.map +1 -0
- package/dist/skill/dsl-verbs.d.ts +2 -0
- package/dist/skill/dsl-verbs.d.ts.map +1 -0
- package/dist/skill/dsl-verbs.js +10 -0
- package/dist/skill/dsl-verbs.js.map +1 -0
- package/dist/skill/fix-loop-protocol.d.ts +18 -0
- package/dist/skill/fix-loop-protocol.d.ts.map +1 -0
- package/dist/skill/fix-loop-protocol.js +38 -0
- package/dist/skill/fix-loop-protocol.js.map +1 -0
- package/dist/skill/gates.d.ts +2 -0
- package/dist/skill/gates.d.ts.map +1 -0
- package/dist/skill/gates.js +20 -0
- package/dist/skill/gates.js.map +1 -0
- package/dist/skill/install.d.ts +25 -0
- package/dist/skill/install.d.ts.map +1 -0
- package/dist/skill/install.js +49 -0
- package/dist/skill/install.js.map +1 -0
- package/dist/skill/render.d.ts +15 -0
- package/dist/skill/render.d.ts.map +1 -0
- package/dist/skill/render.js +35 -0
- package/dist/skill/render.js.map +1 -0
- package/dist/skill/rule-kinds.d.ts +12 -0
- package/dist/skill/rule-kinds.d.ts.map +1 -0
- package/dist/skill/rule-kinds.js +47 -0
- package/dist/skill/rule-kinds.js.map +1 -0
- package/dist/skill/static-sections.d.ts +5 -0
- package/dist/skill/static-sections.d.ts.map +1 -0
- package/dist/skill/static-sections.js +74 -0
- package/dist/skill/static-sections.js.map +1 -0
- package/dist/skill/version-stamp.d.ts +22 -0
- package/dist/skill/version-stamp.d.ts.map +1 -0
- package/dist/skill/version-stamp.js +29 -0
- package/dist/skill/version-stamp.js.map +1 -0
- package/dist/telemetry/check-event.d.ts +7 -0
- package/dist/telemetry/check-event.d.ts.map +1 -0
- package/dist/telemetry/check-event.js +29 -0
- package/dist/telemetry/check-event.js.map +1 -0
- package/dist/telemetry/index.d.ts +8 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +8 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/process-context.d.ts +9 -0
- package/dist/telemetry/process-context.d.ts.map +1 -0
- package/dist/telemetry/process-context.js +10 -0
- package/dist/telemetry/process-context.js.map +1 -0
- package/dist/telemetry/recorder.d.ts +43 -0
- package/dist/telemetry/recorder.d.ts.map +1 -0
- package/dist/telemetry/recorder.js +61 -0
- package/dist/telemetry/recorder.js.map +1 -0
- package/dist/telemetry/resolve.d.ts +19 -0
- package/dist/telemetry/resolve.d.ts.map +1 -0
- package/dist/telemetry/resolve.js +18 -0
- package/dist/telemetry/resolve.js.map +1 -0
- package/dist/telemetry/ruleset-hash.d.ts +10 -0
- package/dist/telemetry/ruleset-hash.d.ts.map +1 -0
- package/dist/telemetry/ruleset-hash.js +12 -0
- package/dist/telemetry/ruleset-hash.js.map +1 -0
- package/dist/telemetry/session.d.ts +6 -0
- package/dist/telemetry/session.d.ts.map +1 -0
- package/dist/telemetry/session.js +9 -0
- package/dist/telemetry/session.js.map +1 -0
- package/dist/telemetry/violations.d.ts +10 -0
- package/dist/telemetry/violations.d.ts.map +1 -0
- package/dist/telemetry/violations.js +36 -0
- package/dist/telemetry/violations.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `align mcp` — stdio MCP server (ADR 001/007). Token-economy discipline: structured-fields-only
|
|
3
|
+
* payloads, priority-sorted, capped, and paginated; passing gates contribute counts only, never
|
|
4
|
+
* per-item prose (ADR 007). Tool descriptions carry searchable capability keywords for
|
|
5
|
+
* deferred-loading harnesses (ADR 009 — probe 1 found align's tools surfaced as deferred tools
|
|
6
|
+
* requiring an explicit load before use).
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT (stdio transport): stdout carries JSON-RPC frames; all logging goes to stderr.
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { buildMcpCheckPayload, proposeRulesFromDoc, ruleFragmentSchema, toRepoRelativePath } from '@spikedpunch/align-core';
|
|
16
|
+
import { loadConfig } from '../config.js';
|
|
17
|
+
import { createOrchestrator } from '../composition-root.js';
|
|
18
|
+
import { readBaseline, writeBaseline } from '../align-dir.js';
|
|
19
|
+
import { buildExplainPayload } from '../commands/explain.js';
|
|
20
|
+
import { DEFAULT_DOC_PATH, proposeFromClientSubmission, writeBuildArtifacts } from '../commands/build.js';
|
|
21
|
+
import { renderCondensedFixingSkill } from '../skill/condensed.js';
|
|
22
|
+
/** Shared by `align_check`/`align_violations`: runs a fresh check and persists any move-transfer
|
|
23
|
+
* (ADR 006) the run performed, so a renamed file's baselined violation doesn't need a separate
|
|
24
|
+
* `align baseline prune` to stop being re-reported on the next call. */
|
|
25
|
+
async function freshCheck(rootDir) {
|
|
26
|
+
const { ruleset, excludes, hostRules } = await loadConfig(rootDir);
|
|
27
|
+
const { orchestrator, baselineStore } = createOrchestrator(ruleset, readBaseline(rootDir), hostRules);
|
|
28
|
+
const run = await orchestrator.check({ rootDir, excludes });
|
|
29
|
+
if (run.advisories.some((a) => a.kind === 'baseline-moved')) {
|
|
30
|
+
writeBaseline(rootDir, baselineStore.snapshot());
|
|
31
|
+
}
|
|
32
|
+
return run;
|
|
33
|
+
}
|
|
34
|
+
/** Builds the McpServer with tools registered but no transport attached — split out from
|
|
35
|
+
* `startMcpServer` so tests can connect it to an in-process `InMemoryTransport` instead of stdio
|
|
36
|
+
* (MCP contract tests via the SDK's own client, per the Stage 1 plan). */
|
|
37
|
+
export function createMcpServer(rootDir) {
|
|
38
|
+
// `instructions` (Stage 5, IMPLEMENTATION_PLAN.md "Elevated first items"): the condensed
|
|
39
|
+
// fixing-topic skill, token-budgeted (~30 lines), rendered from the same source module the full
|
|
40
|
+
// `align skill --topic fixing` markdown expands (packages/cli/src/skill/fix-loop-protocol.ts) —
|
|
41
|
+
// not a second hand-written copy of the protocol.
|
|
42
|
+
const server = new McpServer({ name: 'align', version: '0.1.0' }, { instructions: renderCondensedFixingSkill() });
|
|
43
|
+
server.registerTool('align_check', {
|
|
44
|
+
title: 'Check architecture conformance',
|
|
45
|
+
description: 'Runs align architecture rules (dependency-direction constraints + import-cycle detection ' +
|
|
46
|
+
'over the project dependency graph) and returns a green/red/error verdict with per-gate ' +
|
|
47
|
+
'counts. Performs a FRESH full repo scan every call — the result always reflects the ' +
|
|
48
|
+
'current on-disk code, never a cached or stale prior scan. Call this after structural code ' +
|
|
49
|
+
'changes (new imports, moved files, restructured modules) to verify architecture is intact.',
|
|
50
|
+
inputSchema: {},
|
|
51
|
+
}, async () => {
|
|
52
|
+
const run = await freshCheck(rootDir);
|
|
53
|
+
const payload = buildMcpCheckPayload(run, { maxPerRule: 10, pageSize: 50 });
|
|
54
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
55
|
+
});
|
|
56
|
+
server.registerTool('align_violations', {
|
|
57
|
+
title: 'List architecture violations',
|
|
58
|
+
description: 'Returns the current architecture violations (dependency-direction breaches, import ' +
|
|
59
|
+
'cycles) in priority order, with file, line, specifier, and a machine-readable fix hint ' +
|
|
60
|
+
'per violation. Structured fields only — pass an optional cursor to page through results ' +
|
|
61
|
+
'beyond the first page. Performs a fresh scan every call (ADR 005).',
|
|
62
|
+
inputSchema: { cursor: z.string().optional() },
|
|
63
|
+
}, async ({ cursor }) => {
|
|
64
|
+
const run = await freshCheck(rootDir);
|
|
65
|
+
const payload = buildMcpCheckPayload(run, { maxPerRule: 10, pageSize: 50, ...(cursor === undefined ? {} : { cursor }) });
|
|
66
|
+
return {
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: 'text',
|
|
70
|
+
text: JSON.stringify({ violations: payload.violations, pagination: payload.pagination }, null, 2),
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
server.registerTool('align_explain_rule', {
|
|
76
|
+
title: 'Explain an architecture rule',
|
|
77
|
+
description: 'Explains one align architecture rule by id: its kind (no-dependency / no-cycles / ' +
|
|
78
|
+
'layers), the rationale (.because() text), and the components it constrains with example ' +
|
|
79
|
+
'files from the current tree. Use this to understand WHY a violation was raised before ' +
|
|
80
|
+
'proposing a fix.',
|
|
81
|
+
inputSchema: { ruleId: z.string() },
|
|
82
|
+
}, async ({ ruleId }) => {
|
|
83
|
+
const payload = await buildExplainPayload(rootDir, ruleId);
|
|
84
|
+
if (payload === undefined) {
|
|
85
|
+
return { isError: true, content: [{ type: 'text', text: `Unknown rule id '${ruleId}'.` }] };
|
|
86
|
+
}
|
|
87
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
88
|
+
});
|
|
89
|
+
const proposalInputSchema = z.object({
|
|
90
|
+
section: z.string(),
|
|
91
|
+
fragment: ruleFragmentSchema,
|
|
92
|
+
sourceLineRange: z.object({ startLine: z.number().int(), endLine: z.number().int() }),
|
|
93
|
+
sourceQuote: z.string(),
|
|
94
|
+
});
|
|
95
|
+
server.registerTool('align_propose_rules', {
|
|
96
|
+
title: 'Propose architecture rules from a markdown doc (build)',
|
|
97
|
+
description: 'Compiles an architecture/best-practices markdown doc into align rules — the same ' +
|
|
98
|
+
'precision ladder as `align build` (fenced ```align blocks, structured `- **Rule**:` ' +
|
|
99
|
+
'bullets, prose needing judgment). TWO-PASS: call with ONLY `doc_path` first (discovery) ' +
|
|
100
|
+
'to get per-section tier classification, deterministically-extracted rules, and an empty ' +
|
|
101
|
+
'"concerns" scaffold for prose sections for YOU to fill with your own judgment (align ' +
|
|
102
|
+
'never invents rules from prose). Then call again with `proposals` (your confirmed ' +
|
|
103
|
+
'concerns turned into rule fragments with provenance, plus any deterministic rules you ' +
|
|
104
|
+
'want to keep) to validate, ground selectors against the components registry, and dry-run ' +
|
|
105
|
+
'the impact (added/flagged-ungroundable/violation-count delta) — nothing is written yet. ' +
|
|
106
|
+
'Add `apply: true` on a follow-up call once you have reviewed the dry run to write ' +
|
|
107
|
+
'.align/generated-rules.json + rules.lock.json + the audit report. align validates and ' +
|
|
108
|
+
'grounds; no API key or LLM call happens inside align itself.',
|
|
109
|
+
inputSchema: {
|
|
110
|
+
doc_path: z.string().optional(),
|
|
111
|
+
proposals: z.array(proposalInputSchema).optional(),
|
|
112
|
+
apply: z.boolean().optional(),
|
|
113
|
+
accept_new_into_baseline: z.boolean().optional(),
|
|
114
|
+
},
|
|
115
|
+
}, async ({ doc_path, proposals, apply, accept_new_into_baseline }) => {
|
|
116
|
+
const docRelPath = doc_path ?? DEFAULT_DOC_PATH;
|
|
117
|
+
if (proposals === undefined) {
|
|
118
|
+
// Pass 1 — Discovery (ADR 011 two-pass clarification): classify sections, surface the
|
|
119
|
+
// deterministic tier-1/2 rules ready to pass through verbatim, and an empty `concerns`
|
|
120
|
+
// scaffold per prose section for the client to fill — align never invents rules from
|
|
121
|
+
// prose.
|
|
122
|
+
const absDocPath = path.join(rootDir, docRelPath);
|
|
123
|
+
if (!fs.existsSync(absDocPath)) {
|
|
124
|
+
return { isError: true, content: [{ type: 'text', text: `Doc not found: ${docRelPath}` }] };
|
|
125
|
+
}
|
|
126
|
+
const docText = fs.readFileSync(absDocPath, 'utf8');
|
|
127
|
+
const { ruleset, hostRules } = await loadConfig(rootDir, { includeGenerated: false });
|
|
128
|
+
const proposal = proposeRulesFromDoc(docText, toRepoRelativePath(docRelPath), ruleset.components, new Set(hostRules.keys()));
|
|
129
|
+
return {
|
|
130
|
+
content: [
|
|
131
|
+
{
|
|
132
|
+
type: 'text',
|
|
133
|
+
text: JSON.stringify({
|
|
134
|
+
docPath: docRelPath,
|
|
135
|
+
sections: proposal.sections,
|
|
136
|
+
deterministicRules: proposal.rules,
|
|
137
|
+
flagged: proposal.flagged,
|
|
138
|
+
proseSections: proposal.proseSections,
|
|
139
|
+
}, null, 2),
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// Pass 2 (validate/ground/dry-run, no write) or `{ apply: true }` (writes via the same
|
|
145
|
+
// pipeline as `align build --apply`).
|
|
146
|
+
let result;
|
|
147
|
+
try {
|
|
148
|
+
result = await proposeFromClientSubmission(rootDir, docRelPath, proposals);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
return { isError: true, content: [{ type: 'text', text: err instanceof Error ? err.message : String(err) }] };
|
|
152
|
+
}
|
|
153
|
+
const diffPayload = {
|
|
154
|
+
docPath: docRelPath,
|
|
155
|
+
accepted: result.proposal.rules.map((r) => ({ id: r.id, kind: r.kind, provenance: r.provenance })),
|
|
156
|
+
flaggedUngroundable: result.proposal.flagged,
|
|
157
|
+
diff: {
|
|
158
|
+
added: result.diff.added.map((r) => r.id),
|
|
159
|
+
changed: result.diff.changed.map((c) => c.after.id),
|
|
160
|
+
removed: result.diff.removed.map((r) => r.id),
|
|
161
|
+
unchanged: result.diff.unchanged.map((r) => r.id),
|
|
162
|
+
},
|
|
163
|
+
impact: { addsNewViolations: result.impact.addedNew.length, masksBaselined: result.impact.maskedBaselined.length },
|
|
164
|
+
};
|
|
165
|
+
if (apply !== true) {
|
|
166
|
+
return { content: [{ type: 'text', text: JSON.stringify(diffPayload, null, 2) }] };
|
|
167
|
+
}
|
|
168
|
+
const applied = writeBuildArtifacts(rootDir, result, { acceptNewIntoBaseline: accept_new_into_baseline === true });
|
|
169
|
+
if (!applied.ok) {
|
|
170
|
+
return { isError: true, content: [{ type: 'text', text: applied.message }] };
|
|
171
|
+
}
|
|
172
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ...diffPayload, applied: true, message: applied.message }, null, 2) }] };
|
|
173
|
+
});
|
|
174
|
+
return server;
|
|
175
|
+
}
|
|
176
|
+
export async function startMcpServer(rootDir) {
|
|
177
|
+
const server = createMcpServer(rootDir);
|
|
178
|
+
const transport = new StdioServerTransport();
|
|
179
|
+
await server.connect(transport);
|
|
180
|
+
console.error('[align] MCP server ready on stdio');
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the `align` commander program without invoking `parseAsync` — split out of `index.ts`
|
|
4
|
+
* (Stage 5, IMPLEMENTATION_PLAN.md "Elevated first items") so the CLI command inventory is a
|
|
5
|
+
* live, introspectable object (`program.commands`) instead of a hand-maintained list: `align
|
|
6
|
+
* skill`'s generated CLI-command-inventory section (`packages/cli/src/skill/cli-inventory.ts`)
|
|
7
|
+
* calls this function and walks the real `Command` tree, so it cannot list a command that doesn't
|
|
8
|
+
* exist or omit one that does. `index.ts` is now just `buildProgram().parseAsync(process.argv)`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildProgram(): Command;
|
|
11
|
+
//# sourceMappingURL=program.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAmOtC"}
|
package/dist/program.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { runCheck } from './commands/check.js';
|
|
3
|
+
import { runExportIr } from './commands/export-ir.js';
|
|
4
|
+
import { runInit } from './commands/init.js';
|
|
5
|
+
import { baselineAccept, baselinePrune, baselineShow } from './commands/baseline.js';
|
|
6
|
+
import { buildExplainPayload } from './commands/explain.js';
|
|
7
|
+
import { runDoctor } from './commands/doctor.js';
|
|
8
|
+
import { runBuild, DEFAULT_DOC_PATH } from './commands/build.js';
|
|
9
|
+
import { runAgentCommand } from './commands/agent.js';
|
|
10
|
+
import { runSkill } from './commands/skill.js';
|
|
11
|
+
import { runTelemetryReport, DEFAULT_TELEMETRY_FILE } from './commands/telemetry.js';
|
|
12
|
+
import { startMcpServer } from './mcp/server.js';
|
|
13
|
+
import { ALIGN_VERSION, resolveTelemetryPreConfig } from './telemetry/index.js';
|
|
14
|
+
/** `--telemetry` / `--no-telemetry` (IMPLEMENTATION_PLAN.md's telemetry spec) share commander's
|
|
15
|
+
* negatable-option pairing on every command that can emit telemetry: neither flag passed leaves
|
|
16
|
+
* `opts.telemetry` `undefined` ("defer to `ALIGN_TELEMETRY`/`align.config.ts`"), `--telemetry`
|
|
17
|
+
* forces `true`, `--no-telemetry` forces `false` and overrides env/config (verified directly
|
|
18
|
+
* against commander's own option-merging behavior, not assumed). */
|
|
19
|
+
function addTelemetryOptions(cmd) {
|
|
20
|
+
return cmd
|
|
21
|
+
.option('--telemetry', 'force-enable the local-only telemetry log for this run (see also ALIGN_TELEMETRY=1 / align.config.ts telemetry:true)')
|
|
22
|
+
.option('--no-telemetry', 'disable telemetry for this run — overrides ALIGN_TELEMETRY / align.config.ts telemetry:true');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds the `align` commander program without invoking `parseAsync` — split out of `index.ts`
|
|
26
|
+
* (Stage 5, IMPLEMENTATION_PLAN.md "Elevated first items") so the CLI command inventory is a
|
|
27
|
+
* live, introspectable object (`program.commands`) instead of a hand-maintained list: `align
|
|
28
|
+
* skill`'s generated CLI-command-inventory section (`packages/cli/src/skill/cli-inventory.ts`)
|
|
29
|
+
* calls this function and walks the real `Command` tree, so it cannot list a command that doesn't
|
|
30
|
+
* exist or omit one that does. `index.ts` is now just `buildProgram().parseAsync(process.argv)`.
|
|
31
|
+
*/
|
|
32
|
+
export function buildProgram() {
|
|
33
|
+
const program = new Command();
|
|
34
|
+
program
|
|
35
|
+
.name('align')
|
|
36
|
+
.description('Architecture-conformance verification oracle for LLM coding agents.')
|
|
37
|
+
.version(ALIGN_VERSION, '-v, --version', 'print the align CLI version');
|
|
38
|
+
program
|
|
39
|
+
.command('init')
|
|
40
|
+
.description('Detect components, write a starter align.config.ts, and seed the baseline.')
|
|
41
|
+
.option('--accept-existing', 'seed the baseline non-interactively with all pre-existing violations', false)
|
|
42
|
+
.option('--greenfield', "force every detected component to empty: 'until-populated' regardless of today's file count (architecture-first authoring)", false)
|
|
43
|
+
.action(async (opts) => {
|
|
44
|
+
const code = await runInit(process.cwd(), { acceptExisting: opts.acceptExisting, greenfield: opts.greenfield });
|
|
45
|
+
process.exitCode = code;
|
|
46
|
+
});
|
|
47
|
+
addTelemetryOptions(program
|
|
48
|
+
.command('check')
|
|
49
|
+
.description('Run architecture rules against a fresh scan of the repo. Exit 0 iff green.')
|
|
50
|
+
.option('--json', 'print the structured check payload as JSON', false)
|
|
51
|
+
.option('--frozen-rules', 'also fail if a doc-built ruleset has drifted from its lockfile (ADR 011)', false)
|
|
52
|
+
.option('--untrusted', 'never execute align.config.ts (or any hostRules predicate) — load the ruleset from ' +
|
|
53
|
+
'.align/ruleset-ir.json instead (ADR 014). Refuses if that file is missing or contains a ' +
|
|
54
|
+
'custom.host rule; run `align export-ir` in a trusted checkout first.', false)
|
|
55
|
+
.option('--ir-only', 'alias for --untrusted', false)
|
|
56
|
+
.option('--ir <path>', 'override the .align/ruleset-ir.json path --untrusted/--ir-only reads from')).action(async (opts) => {
|
|
57
|
+
const telemetryPreConfig = resolveTelemetryPreConfig({ telemetry: opts.telemetry });
|
|
58
|
+
const code = await runCheck(process.cwd(), {
|
|
59
|
+
json: opts.json,
|
|
60
|
+
frozenRules: opts.frozenRules,
|
|
61
|
+
untrusted: opts.untrusted || opts.irOnly,
|
|
62
|
+
...(opts.ir !== undefined ? { ir: opts.ir } : {}),
|
|
63
|
+
...(telemetryPreConfig !== undefined ? { telemetryPreConfig } : {}),
|
|
64
|
+
});
|
|
65
|
+
process.exitCode = code;
|
|
66
|
+
});
|
|
67
|
+
program
|
|
68
|
+
.command('export-ir')
|
|
69
|
+
.description('Run once in a trusted context: import align.config.ts and write the effective ruleset ' +
|
|
70
|
+
'(components + rules, no functions) as portable JSON to .align/ruleset-ir.json — the data ' +
|
|
71
|
+
'source `align check --untrusted` reads instead of executing align.config.ts (ADR 014).')
|
|
72
|
+
.option('--out <path>', 'override the default .align/ruleset-ir.json output path')
|
|
73
|
+
.action(async (opts) => {
|
|
74
|
+
const code = await runExportIr(process.cwd(), opts.out !== undefined ? { out: opts.out } : {});
|
|
75
|
+
process.exitCode = code;
|
|
76
|
+
});
|
|
77
|
+
const baseline = program.command('baseline').description('Manage the violation baseline (tolerated debt).');
|
|
78
|
+
addTelemetryOptions(baseline
|
|
79
|
+
.command('accept')
|
|
80
|
+
.description('Accept current violations into the baseline (optionally scoped to one rule).')
|
|
81
|
+
.option('--rule <ruleId>', 'only accept violations of this rule')).action(async (opts) => {
|
|
82
|
+
const telemetryPreConfig = resolveTelemetryPreConfig({ telemetry: opts.telemetry });
|
|
83
|
+
process.exitCode = await baselineAccept(process.cwd(), opts.rule, telemetryPreConfig);
|
|
84
|
+
});
|
|
85
|
+
addTelemetryOptions(baseline.command('prune').description('Remove baseline entries for violations that no longer exist; report moved entries.')).action(async (opts) => {
|
|
86
|
+
const telemetryPreConfig = resolveTelemetryPreConfig({ telemetry: opts.telemetry });
|
|
87
|
+
process.exitCode = await baselinePrune(process.cwd(), telemetryPreConfig);
|
|
88
|
+
});
|
|
89
|
+
baseline
|
|
90
|
+
.command('show')
|
|
91
|
+
.description('List baselined violations (optionally scoped to one rule).')
|
|
92
|
+
.option('--rule <ruleId>', 'only show violations of this rule')
|
|
93
|
+
.action(async (opts) => {
|
|
94
|
+
process.exitCode = await baselineShow(process.cwd(), opts.rule);
|
|
95
|
+
});
|
|
96
|
+
program
|
|
97
|
+
.command('explain <ruleId>')
|
|
98
|
+
.description('Explain one architecture rule: its kind, rationale, and constrained components.')
|
|
99
|
+
.action(async (ruleId) => {
|
|
100
|
+
const payload = await buildExplainPayload(process.cwd(), ruleId);
|
|
101
|
+
if (payload === undefined) {
|
|
102
|
+
console.error(`Unknown rule id '${ruleId}'.`);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
107
|
+
});
|
|
108
|
+
program
|
|
109
|
+
.command('doctor')
|
|
110
|
+
.description('Read-only advisory survey: dead tsconfig path aliases, uncertainty breakdown, unmapped ' +
|
|
111
|
+
'files, workspace-orphaned packages, empty components, stale installed skill snapshot ' +
|
|
112
|
+
'(`align skill --install`). Never fails — exit code is always 0.')
|
|
113
|
+
.option('--json', 'print structured advisories + capped per-specifier uncertainty detail as JSON', false)
|
|
114
|
+
.action(async (opts) => {
|
|
115
|
+
process.exitCode = await runDoctor(process.cwd(), { json: opts.json });
|
|
116
|
+
});
|
|
117
|
+
addTelemetryOptions(program
|
|
118
|
+
.command('build')
|
|
119
|
+
.description('Compile a markdown architecture doc into the ruleset (ADR 011): fenced ```align blocks + ' +
|
|
120
|
+
'structured `- **Rule**:` bullets, zero LLM. Default is dry-run (prints the proposal diff + ' +
|
|
121
|
+
'impact delta, writes nothing).')
|
|
122
|
+
.option('--doc <path>', 'doc to build (default docs/ARCHITECTURE-RULES.md)', DEFAULT_DOC_PATH)
|
|
123
|
+
.option('--apply', 'write .align/generated-rules.json, rules.lock.json, and the audit report', false)
|
|
124
|
+
.option('--if-changed', 'exit 0 immediately if the doc is unchanged since the last build', false)
|
|
125
|
+
.option('--verify', 'exit red if the doc or generated-rules.json has drifted from the lockfile (ADR 011)', false)
|
|
126
|
+
.option('--accept-new-into-baseline', 'seed any new violations the proposal adds into the baseline', false)).action(async (opts) => {
|
|
127
|
+
const telemetryPreConfig = resolveTelemetryPreConfig({ telemetry: opts.telemetry });
|
|
128
|
+
const code = await runBuild(process.cwd(), {
|
|
129
|
+
doc: opts.doc,
|
|
130
|
+
apply: opts.apply,
|
|
131
|
+
ifChanged: opts.ifChanged,
|
|
132
|
+
verify: opts.verify,
|
|
133
|
+
acceptNewIntoBaseline: opts.acceptNewIntoBaseline,
|
|
134
|
+
...(telemetryPreConfig !== undefined ? { telemetryPreConfig } : {}),
|
|
135
|
+
});
|
|
136
|
+
process.exitCode = code;
|
|
137
|
+
});
|
|
138
|
+
const agent = program.command('agent').description('Built-in BYOK LLM fix loop (Stage 4, ADR 010). Requires ANTHROPIC_API_KEY.');
|
|
139
|
+
addTelemetryOptions(agent
|
|
140
|
+
.command('run')
|
|
141
|
+
.description('DISCOVER -> GROUP -> PLAN+FIX -> APPLY -> VERIFY -> REPAIR -> ESCALATE -> DONE -> TERMINAL MERGE. ' +
|
|
142
|
+
'Refuses a dirty worktree; every apply is a commit on a fresh align/fixes-<date> branch; never ' +
|
|
143
|
+
'touches align.config.ts or .align/**.')
|
|
144
|
+
.option('--max-attempts <n>', 'max REPAIR attempts per file group', (v) => Number.parseInt(v, 10), 3)
|
|
145
|
+
.option('--pr', 'push the work branch and open a draft PR (default)', true)
|
|
146
|
+
.option('--auto-merge', 'fast-forward merge into the base branch and delete the work branch instead of opening a PR', false)
|
|
147
|
+
.option('--allow-untested', 'allow PLAN+FIX on files with zero detected test coverage (default: refuse)', false)
|
|
148
|
+
.option('--allow-symbol-removals', 'allow a fix that deletes an exported symbol to commit (default: escalate)', false)
|
|
149
|
+
.option('--model <id>', 'override the FixProvider model id (default: config/env ALIGN_AGENT_MODEL, else claude-sonnet-5)')
|
|
150
|
+
.option('--dry-run', 'DISCOVER+GROUP+PLAN only — print proposed edits without applying or committing', false)).action(async (opts) => {
|
|
151
|
+
const telemetryPreConfig = resolveTelemetryPreConfig({ telemetry: opts.telemetry });
|
|
152
|
+
const code = await runAgentCommand(process.cwd(), {
|
|
153
|
+
maxAttempts: opts.maxAttempts,
|
|
154
|
+
pr: opts.pr,
|
|
155
|
+
autoMerge: opts.autoMerge,
|
|
156
|
+
allowUntested: opts.allowUntested,
|
|
157
|
+
allowSymbolRemovals: opts.allowSymbolRemovals,
|
|
158
|
+
...(opts.model !== undefined ? { model: opts.model } : {}),
|
|
159
|
+
dryRun: opts.dryRun,
|
|
160
|
+
...(telemetryPreConfig !== undefined ? { telemetryPreConfig } : {}),
|
|
161
|
+
});
|
|
162
|
+
process.exitCode = code;
|
|
163
|
+
});
|
|
164
|
+
program
|
|
165
|
+
.command('mcp')
|
|
166
|
+
.description('Start the align MCP server (stdio) exposing align_check / align_violations / align_explain_rule.')
|
|
167
|
+
.action(async () => {
|
|
168
|
+
await startMcpServer(process.cwd());
|
|
169
|
+
});
|
|
170
|
+
program
|
|
171
|
+
.command('skill')
|
|
172
|
+
.description('Print the LLM-facing align authoring/fixing guide (rule kinds, DSL verbs, bullet grammar, ' +
|
|
173
|
+
'gates, and CLI commands generated live from the installed binary — never hand-written prose ' +
|
|
174
|
+
'that can drift). --install writes .claude/skills/align/SKILL.md into this repo, stamped with ' +
|
|
175
|
+
'the installing version (`align doctor` flags it once the snapshot goes stale).')
|
|
176
|
+
.option('--topic <topic>', 'authoring | fixing | all', 'all')
|
|
177
|
+
.option('--install', 'write .claude/skills/align/SKILL.md (idempotent, delimited block)', false)
|
|
178
|
+
.action(async (opts) => {
|
|
179
|
+
const topic = opts.topic;
|
|
180
|
+
if (topic !== 'authoring' && topic !== 'fixing' && topic !== 'all') {
|
|
181
|
+
console.error(`Invalid --topic '${opts.topic}' — expected authoring | fixing | all.`);
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
process.exitCode = await runSkill(process.cwd(), { topic, install: opts.install }, program);
|
|
186
|
+
});
|
|
187
|
+
program
|
|
188
|
+
.command('telemetry')
|
|
189
|
+
.description('Summarize .align/telemetry.jsonl (opt-in, local-only — see ALIGN_TELEMETRY/--telemetry): check-latency ' +
|
|
190
|
+
'percentiles, top-firing rules, time-to-green per rule, dead rules, baseline-vs-fix ratio, and ' +
|
|
191
|
+
'friction ranking by error kind. The report the coordinator/user reads after a dogfood session.')
|
|
192
|
+
.option('--file <path>', `JSONL file to read (default ${DEFAULT_TELEMETRY_FILE})`)
|
|
193
|
+
.option('--json', 'print the structured summary as JSON', false)
|
|
194
|
+
.action(async (opts) => {
|
|
195
|
+
process.exitCode = await runTelemetryReport(process.cwd(), { json: opts.json, ...(opts.file !== undefined ? { file: opts.file } : {}) });
|
|
196
|
+
});
|
|
197
|
+
return program;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bullet-grammar.d.ts","sourceRoot":"","sources":["../../src/skill/bullet-grammar.ts"],"names":[],"mappings":"AAQA,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier-2 bullet-grammar reference for `align skill` — reads `@spikedpunch/align-core`'s
|
|
3
|
+
* `BULLET_GRAMMAR_FORMS` catalog (`build/tier2.ts`), which is itself asserted against the real
|
|
4
|
+
* `parseBulletSentence` parser in core's own test suite. This module only renders; it introduces
|
|
5
|
+
* no new grammar knowledge of its own.
|
|
6
|
+
*/
|
|
7
|
+
import { BULLET_GRAMMAR_FORMS } from '@spikedpunch/align-core';
|
|
8
|
+
export function renderBulletGrammarSection() {
|
|
9
|
+
const rows = BULLET_GRAMMAR_FORMS.map((form) => `- \`${form.ruleKind}\` — ${form.pattern}\n e.g. \`- **Rule**: ${form.example}\``);
|
|
10
|
+
return rows.join('\n');
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=bullet-grammar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bullet-grammar.js","sourceRoot":"","sources":["../../src/skill/bullet-grammar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,UAAU,0BAA0B;IACxC,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,OAAO,0BAA0B,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;IACpI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command inventory for `align skill` — walks a real `commander` `Command` tree instead of
|
|
3
|
+
* hand-maintaining a second list, so a command added to/removed from `program.ts` shows up here
|
|
4
|
+
* automatically.
|
|
5
|
+
*
|
|
6
|
+
* Takes the `Command` as a parameter rather than importing `buildProgram` from `../program.js`
|
|
7
|
+
* itself: `program.ts` registers the `skill` command (which imports this module transitively via
|
|
8
|
+
* `render.ts`), so a static import back to `program.ts` here would close an
|
|
9
|
+
* `arch.no-cycles`-violating cycle — align's own dogfood ruleset caught exactly this shape when it
|
|
10
|
+
* was first wired up. `program.ts`'s `skill` command action passes its own already-built `program`
|
|
11
|
+
* closure variable in; callers outside the CLI action (e.g. tests) build one via `buildProgram()`
|
|
12
|
+
* and pass it in the same way.
|
|
13
|
+
*/
|
|
14
|
+
import type { Command } from 'commander';
|
|
15
|
+
export declare function renderCliInventorySection(program: Command): string;
|
|
16
|
+
//# sourceMappingURL=cli-inventory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-inventory.d.ts","sourceRoot":"","sources":["../../src/skill/cli-inventory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAIlE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function renderCommand(cmd, pathPrefix, depth) {
|
|
2
|
+
const indent = ' '.repeat(depth);
|
|
3
|
+
const usage = cmd.usage();
|
|
4
|
+
const fullPath = `${pathPrefix} ${cmd.name()}`.trim();
|
|
5
|
+
const description = cmd.description();
|
|
6
|
+
const lines = [`${indent}- \`align ${fullPath}${usage.length > 0 ? ` ${usage}` : ''}\`${description.length > 0 ? ` — ${description}` : ''}`];
|
|
7
|
+
for (const sub of cmd.commands)
|
|
8
|
+
lines.push(...renderCommand(sub, fullPath, depth + 1));
|
|
9
|
+
return lines;
|
|
10
|
+
}
|
|
11
|
+
export function renderCliInventorySection(program) {
|
|
12
|
+
const lines = [];
|
|
13
|
+
for (const cmd of program.commands)
|
|
14
|
+
lines.push(...renderCommand(cmd, '', 0));
|
|
15
|
+
return lines.join('\n');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=cli-inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-inventory.js","sourceRoot":"","sources":["../../src/skill/cli-inventory.ts"],"names":[],"mappings":"AAeA,SAAS,aAAa,CAAC,GAAY,EAAE,UAAkB,EAAE,KAAa;IACpE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,GAAG,UAAU,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,aAAa,QAAQ,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7I,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"condensed.d.ts","sourceRoot":"","sources":["../../src/skill/condensed.ts"],"names":[],"mappings":"AAWA,wBAAgB,0BAA0B,IAAI,MAAM,CAanD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Condensed fixing-topic skill for the MCP server's native `instructions` field (Stage 5,
|
|
3
|
+
* IMPLEMENTATION_PLAN.md "Elevated first items" — "pairs with the packaging/bin item; both live
|
|
4
|
+
* probes tried bare align/npx first"). Token-budgeted (~30 lines max): renders `FIX_LOOP_PROTOCOL`
|
|
5
|
+
* summaries (`fix-loop-protocol.ts`) — the SAME source `align skill --topic fixing`'s full
|
|
6
|
+
* markdown expands with `.detail` — plus a one-line tool pointer. Never hand-duplicated prose.
|
|
7
|
+
*/
|
|
8
|
+
import { FIX_LOOP_PROTOCOL } from './fix-loop-protocol.js';
|
|
9
|
+
const MAX_LINES = 30;
|
|
10
|
+
export function renderCondensedFixingSkill() {
|
|
11
|
+
const lines = [
|
|
12
|
+
'align — architecture-conformance oracle. Tools: align_check, align_violations, align_explain_rule, align_propose_rules.',
|
|
13
|
+
'',
|
|
14
|
+
'Fix-loop protocol:',
|
|
15
|
+
...FIX_LOOP_PROTOCOL.map((p) => `- ${p.summary}`),
|
|
16
|
+
'',
|
|
17
|
+
'Run `align_check` after structural changes. Every call is a fresh scan.',
|
|
18
|
+
];
|
|
19
|
+
if (lines.length > MAX_LINES) {
|
|
20
|
+
throw new Error(`skill/condensed.ts: renderCondensedFixingSkill() produced ${lines.length} lines, over the ${MAX_LINES}-line MCP instructions budget.`);
|
|
21
|
+
}
|
|
22
|
+
return lines.join('\n');
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=condensed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"condensed.js","sourceRoot":"","sources":["../../src/skill/condensed.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,MAAM,UAAU,0BAA0B;IACxC,MAAM,KAAK,GAAa;QACtB,yHAAyH;QACzH,EAAE;QACF,oBAAoB;QACpB,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QACjD,EAAE;QACF,yEAAyE;KAC1E,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,6DAA6D,KAAK,CAAC,MAAM,oBAAoB,SAAS,gCAAgC,CAAC,CAAC;IAC1J,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsl-verbs.d.ts","sourceRoot":"","sources":["../../src/skill/dsl-verbs.ts"],"names":[],"mappings":"AAMA,wBAAgB,qBAAqB,IAAI,MAAM,CAK9C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSL verb table for `align skill` — reads `@spikedpunch/align-core/dsl`'s runtime-introspected verb manifest
|
|
3
|
+
* (`dsl/verb-manifest.ts`) rather than hand-typing the builder surface a second time.
|
|
4
|
+
*/
|
|
5
|
+
import { describeDslVerbs } from '@spikedpunch/align-core/dsl';
|
|
6
|
+
export function renderDslVerbsSection() {
|
|
7
|
+
const rows = describeDslVerbs().map((verb) => `| \`${verb.path}\` | ${verb.description} | ${verb.producesRuleKind.map((k) => `\`${k}\``).join(', ')} |`);
|
|
8
|
+
return ['| Verb | Meaning | Produces |', '| --- | --- | --- |', ...rows].join('\n');
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=dsl-verbs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsl-verbs.js","sourceRoot":"","sources":["../../src/skill/dsl-verbs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,UAAU,qBAAqB;IACnC,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC,GAAG,CACjC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,WAAW,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACpH,CAAC;IACF,OAAO,CAAC,+BAA+B,EAAE,qBAAqB,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fix-loop protocol (Stage 5 static prose — hand-written, stable; not schema-generated). This is
|
|
3
|
+
* the single source both the full `align skill --topic fixing` markdown
|
|
4
|
+
* (`packages/cli/src/skill/static-sections.ts`) and the condensed MCP server `instructions` field
|
|
5
|
+
* (`packages/cli/src/skill/condensed.ts`) render from, so the two surfaces cannot say different
|
|
6
|
+
* things about the same protocol — only how much of it they show.
|
|
7
|
+
*
|
|
8
|
+
* One point per line, ordered by how often an agent needs to be reminded of it (spike probe 2:
|
|
9
|
+
* the agent independently verified fixes and refused to burn edits against a stale signal — this
|
|
10
|
+
* protocol is what codifies that behavior for every future session, not just the one that
|
|
11
|
+
* discovered it).
|
|
12
|
+
*/
|
|
13
|
+
export interface ProtocolPoint {
|
|
14
|
+
readonly summary: string;
|
|
15
|
+
readonly detail: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const FIX_LOOP_PROTOCOL: readonly ProtocolPoint[];
|
|
18
|
+
//# sourceMappingURL=fix-loop-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix-loop-protocol.d.ts","sourceRoot":"","sources":["../../src/skill/fix-loop-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,aAAa,EA0CrD,CAAC"}
|