@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,42 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
const START_MARKER = '<!-- align:start -->';
|
|
4
|
+
const END_MARKER = '<!-- align:end -->';
|
|
5
|
+
const BLOCK_BODY = `## align — architecture conformance
|
|
6
|
+
|
|
7
|
+
This repo is checked by [align](https://github.com/SpikedPunchVictim/align) for dependency-direction and import-cycle
|
|
8
|
+
conformance. Run \`align check\` (or the \`align_check\` MCP tool if the align MCP server is
|
|
9
|
+
connected) after any structural code change — new imports, moved files, restructured modules.
|
|
10
|
+
|
|
11
|
+
**A red \`align check\` is blocking.** Do not consider a structural change complete while
|
|
12
|
+
\`align check\` reports red. Run \`align explain <ruleId>\` (or the \`align_explain_rule\` MCP tool)
|
|
13
|
+
to understand why a rule fired before proposing a fix.
|
|
14
|
+
|
|
15
|
+
For full rule-authoring guidance run \`align skill --topic authoring\`.`;
|
|
16
|
+
function block() {
|
|
17
|
+
return `${START_MARKER}\n${BLOCK_BODY}\n${END_MARKER}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Idempotent, HTML-comment-delimited write (ADR 009 consequence): re-running `align init` never
|
|
21
|
+
* duplicates or corrupts human-authored instructions around the block.
|
|
22
|
+
*/
|
|
23
|
+
export function writeAgentInstructions(rootDir, filename = 'CLAUDE.md') {
|
|
24
|
+
const filePath = path.join(rootDir, filename);
|
|
25
|
+
const newBlock = block();
|
|
26
|
+
if (!fs.existsSync(filePath)) {
|
|
27
|
+
fs.writeFileSync(filePath, `${newBlock}\n`, 'utf8');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const existing = fs.readFileSync(filePath, 'utf8');
|
|
31
|
+
const startIdx = existing.indexOf(START_MARKER);
|
|
32
|
+
const endIdx = existing.indexOf(END_MARKER);
|
|
33
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
34
|
+
const before = existing.slice(0, startIdx);
|
|
35
|
+
const after = existing.slice(endIdx + END_MARKER.length);
|
|
36
|
+
fs.writeFileSync(filePath, `${before}${newBlock}${after}`, 'utf8');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const separator = existing.endsWith('\n') ? '\n' : '\n\n';
|
|
40
|
+
fs.writeFileSync(filePath, `${existing}${separator}${newBlock}\n`, 'utf8');
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=claude-md.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/init/claude-md.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAC5C,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC,MAAM,UAAU,GAAG;;;;;;;;;;wEAUqD,CAAC;AAEzE,SAAS,KAAK;IACZ,OAAO,GAAG,YAAY,KAAK,UAAU,KAAK,UAAU,EAAE,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,QAAQ,GAAG,WAAW;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IAEzB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,QAAQ,IAAI,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACzD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1D,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotent, comment-delimited write: re-running never duplicates or corrupts the rest of
|
|
3
|
+
* `align.config.ts`. Splices the block back in between existing markers if found; otherwise
|
|
4
|
+
* appends it. Never touches file content it doesn't own.
|
|
5
|
+
*/
|
|
6
|
+
export declare function writeGeneratedRulesNote(configPath: string): void;
|
|
7
|
+
//# sourceMappingURL=config-comment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-comment.d.ts","sourceRoot":"","sources":["../../src/init/config-comment.ts"],"names":[],"mappings":"AAyBA;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAiBhE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Carried Stage 3 affordance (approved by the user ahead of Stage 4): `align build --apply` and
|
|
3
|
+
* `align init` write/refresh a short comment in `align.config.ts` noting that
|
|
4
|
+
* `.align/generated-rules.json` is auto-merged when present — visibility for the implicit merge
|
|
5
|
+
* `loadConfig` already performs (`mergeGeneratedRules`, `config.ts`). Idempotent, delimited,
|
|
6
|
+
* same 3-branch pattern as the CLAUDE.md agent-instructions block (`claude-md.ts`) — but using
|
|
7
|
+
* `//`-line comments since `align.config.ts` is TypeScript, not markdown (`<!-- -->` doesn't
|
|
8
|
+
* parse there).
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
const START_MARKER = '// align:generated-rules-note:start';
|
|
12
|
+
const END_MARKER = '// align:generated-rules-note:end';
|
|
13
|
+
function block() {
|
|
14
|
+
return [
|
|
15
|
+
START_MARKER,
|
|
16
|
+
'// `.align/generated-rules.json` (written by `align build --apply`, ADR 011) is merged into',
|
|
17
|
+
'// this ruleset automatically at load time (`mergeGeneratedRules`) — you never need to import',
|
|
18
|
+
'// it here. Run `align explain <ruleId>` to see a rule\'s provenance (hand-authored vs.',
|
|
19
|
+
'// doc-built).',
|
|
20
|
+
END_MARKER,
|
|
21
|
+
].join('\n');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Idempotent, comment-delimited write: re-running never duplicates or corrupts the rest of
|
|
25
|
+
* `align.config.ts`. Splices the block back in between existing markers if found; otherwise
|
|
26
|
+
* appends it. Never touches file content it doesn't own.
|
|
27
|
+
*/
|
|
28
|
+
export function writeGeneratedRulesNote(configPath) {
|
|
29
|
+
if (!fs.existsSync(configPath))
|
|
30
|
+
return; // nothing to annotate yet — `runInit` writes this first
|
|
31
|
+
const existing = fs.readFileSync(configPath, 'utf8');
|
|
32
|
+
const newBlock = block();
|
|
33
|
+
const startIdx = existing.indexOf(START_MARKER);
|
|
34
|
+
const endIdx = existing.indexOf(END_MARKER);
|
|
35
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
36
|
+
const before = existing.slice(0, startIdx);
|
|
37
|
+
const after = existing.slice(endIdx + END_MARKER.length);
|
|
38
|
+
fs.writeFileSync(configPath, `${before}${newBlock}${after}`, 'utf8');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const separator = existing.endsWith('\n') ? '\n' : '\n\n';
|
|
42
|
+
fs.writeFileSync(configPath, `${existing}${separator}${newBlock}\n`, 'utf8');
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=config-comment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-comment.js","sourceRoot":"","sources":["../../src/init/config-comment.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,MAAM,YAAY,GAAG,qCAAqC,CAAC;AAC3D,MAAM,UAAU,GAAG,mCAAmC,CAAC;AAEvD,SAAS,KAAK;IACZ,OAAO;QACL,YAAY;QACZ,6FAA6F;QAC7F,+FAA+F;QAC/F,yFAAyF;QACzF,gBAAgB;QAChB,UAAU;KACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB;IACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,CAAC,wDAAwD;IAEhG,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IAEzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACzD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { loadWorkspacePackages } from '@spikedpunch/align-plugin-typescript';
|
|
2
|
+
export interface DetectedComponent {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly pattern: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Mechanical component auto-detection for `align init`. Groups by the *fixed (non-wildcard)
|
|
8
|
+
* prefix* of each `pnpm-workspace.yaml` glob pattern rather than one component per package — a
|
|
9
|
+
* generically-implementable heuristic that keeps the starter component count small without
|
|
10
|
+
* requiring the hand-curated judgment calls the spike applied to kluster (documented limitation:
|
|
11
|
+
* less semantically precise than a human-reviewed component map, but zero-config and directionally
|
|
12
|
+
* correct for the common "packages/*, application/*" monorepo shape).
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectComponents(rootDir: string): DetectedComponent[];
|
|
15
|
+
export { loadWorkspacePackages };
|
|
16
|
+
//# sourceMappingURL=detect-components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-components.d.ts","sourceRoot":"","sources":["../../src/init/detect-components.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAQrE;AAyGD,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { loadWorkspacePackages } from '@spikedpunch/align-plugin-typescript';
|
|
4
|
+
/**
|
|
5
|
+
* Mechanical component auto-detection for `align init`. Groups by the *fixed (non-wildcard)
|
|
6
|
+
* prefix* of each `pnpm-workspace.yaml` glob pattern rather than one component per package — a
|
|
7
|
+
* generically-implementable heuristic that keeps the starter component count small without
|
|
8
|
+
* requiring the hand-curated judgment calls the spike applied to kluster (documented limitation:
|
|
9
|
+
* less semantically precise than a human-reviewed component map, but zero-config and directionally
|
|
10
|
+
* correct for the common "packages/*, application/*" monorepo shape).
|
|
11
|
+
*/
|
|
12
|
+
export function detectComponents(rootDir) {
|
|
13
|
+
const wsPath = path.join(rootDir, 'pnpm-workspace.yaml');
|
|
14
|
+
if (fs.existsSync(wsPath)) {
|
|
15
|
+
return detectFromWorkspaceFile(rootDir);
|
|
16
|
+
}
|
|
17
|
+
const fromDirs = detectFromTopLevelPackageDirs(rootDir);
|
|
18
|
+
if (fromDirs.length > 0)
|
|
19
|
+
return fromDirs;
|
|
20
|
+
return detectSinglePackage(rootDir);
|
|
21
|
+
}
|
|
22
|
+
function detectFromWorkspaceFile(rootDir) {
|
|
23
|
+
// Re-derive the raw glob pattern list the same way loadWorkspacePackages does, but we only
|
|
24
|
+
// need the *patterns* here, not the resolved packages.
|
|
25
|
+
const wsPath = path.join(rootDir, 'pnpm-workspace.yaml');
|
|
26
|
+
const patterns = readWorkspacePatterns(wsPath);
|
|
27
|
+
const prefixes = new Set();
|
|
28
|
+
for (const pattern of patterns)
|
|
29
|
+
prefixes.add(fixedPrefix(pattern));
|
|
30
|
+
const components = [...prefixes]
|
|
31
|
+
.sort((a, b) => b.length - a.length) // longest/most-specific prefix classifies first
|
|
32
|
+
.map((prefix) => ({ name: sanitizeName(lastSegment(prefix)), pattern: `${prefix}/**` }));
|
|
33
|
+
return dedupeNames(components);
|
|
34
|
+
}
|
|
35
|
+
function readWorkspacePatterns(wsPath) {
|
|
36
|
+
try {
|
|
37
|
+
// Lightweight, dependency-free read of the `packages:` list — avoids importing the `yaml`
|
|
38
|
+
// package here too; a regex-free approach would need full YAML parsing, so we defer to a
|
|
39
|
+
// minimal line-based reader sufficient for the simple list shape pnpm-workspace.yaml uses.
|
|
40
|
+
const text = fs.readFileSync(wsPath, 'utf8');
|
|
41
|
+
const lines = text.split('\n');
|
|
42
|
+
const patterns = [];
|
|
43
|
+
let inPackages = false;
|
|
44
|
+
for (const line of lines) {
|
|
45
|
+
if (/^packages:\s*$/.test(line)) {
|
|
46
|
+
inPackages = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (inPackages) {
|
|
50
|
+
const m = /^\s*-\s*['"]?([^'"]+)['"]?\s*$/.exec(line);
|
|
51
|
+
if (m?.[1] !== undefined) {
|
|
52
|
+
patterns.push(m[1]);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (/^\S/.test(line))
|
|
56
|
+
break; // dedented to a new top-level key
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return patterns;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function fixedPrefix(pattern) {
|
|
66
|
+
const segments = pattern.split('/');
|
|
67
|
+
const idx = segments.findIndex((s) => s.includes('*'));
|
|
68
|
+
const prefixSegments = idx === -1 ? segments : segments.slice(0, idx);
|
|
69
|
+
return (prefixSegments.length > 0 ? prefixSegments.join('/') : segments[0]) || pattern;
|
|
70
|
+
}
|
|
71
|
+
function lastSegment(prefix) {
|
|
72
|
+
const segments = prefix.split('/');
|
|
73
|
+
return segments[segments.length - 1] ?? prefix;
|
|
74
|
+
}
|
|
75
|
+
/** Component names double as `c.<name>` property accesses and unquoted object-literal keys in
|
|
76
|
+
* the generated DSL (render-config.ts), so they must be valid JS identifiers — not just valid
|
|
77
|
+
* against the IR's `^[A-Za-z][A-Za-z0-9_-]*$` ComponentName pattern, which permits hyphens that
|
|
78
|
+
* `c.kluster-bt` would then parse as a subtraction expression. camelCase rather than hyphenate. */
|
|
79
|
+
function sanitizeName(raw) {
|
|
80
|
+
const stripped = raw.replace(/^@/, '');
|
|
81
|
+
const camel = stripped
|
|
82
|
+
.split(/[^A-Za-z0-9]+/)
|
|
83
|
+
.filter((s) => s.length > 0)
|
|
84
|
+
.map((s, i) => (i === 0 ? s : s.charAt(0).toUpperCase() + s.slice(1)))
|
|
85
|
+
.join('');
|
|
86
|
+
return /^[A-Za-z]/.test(camel) ? camel : `c${camel.charAt(0).toUpperCase()}${camel.slice(1)}`;
|
|
87
|
+
}
|
|
88
|
+
function dedupeNames(components) {
|
|
89
|
+
const seen = new Map();
|
|
90
|
+
return components.map((c) => {
|
|
91
|
+
const count = seen.get(c.name) ?? 0;
|
|
92
|
+
seen.set(c.name, count + 1);
|
|
93
|
+
return count === 0 ? c : { ...c, name: `${c.name}-${count + 1}` };
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function detectFromTopLevelPackageDirs(rootDir) {
|
|
97
|
+
let entries;
|
|
98
|
+
try {
|
|
99
|
+
entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
const components = [];
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules')
|
|
107
|
+
continue;
|
|
108
|
+
if (fs.existsSync(path.join(rootDir, entry.name, 'package.json'))) {
|
|
109
|
+
components.push({ name: sanitizeName(entry.name), pattern: `${entry.name}/**` });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return dedupeNames(components);
|
|
113
|
+
}
|
|
114
|
+
function detectSinglePackage(rootDir) {
|
|
115
|
+
const hasSrc = fs.existsSync(path.join(rootDir, 'src'));
|
|
116
|
+
return [{ name: 'app', pattern: hasSrc ? 'src/**' : '**' }];
|
|
117
|
+
}
|
|
118
|
+
// Re-exported for callers that already have the resolved workspace package list handy (e.g. the
|
|
119
|
+
// layer-suggestion step, which needs both the grouping above and per-package names for edges).
|
|
120
|
+
export { loadWorkspacePackages };
|
|
121
|
+
//# sourceMappingURL=detect-components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-components.js","sourceRoot":"","sources":["../../src/init/detect-components.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `align init` ensures the target repo's `.gitignore` excludes telemetry's local-only files.
|
|
3
|
+
* Idempotent — only appends entries not already present (any line-trimmed match, not just an
|
|
4
|
+
* exact-position match), creates `.gitignore` from scratch if the repo doesn't have one yet.
|
|
5
|
+
* Returns whether it actually wrote anything (so `runInit` can decide whether to print a note).
|
|
6
|
+
*/
|
|
7
|
+
export declare function ensureTelemetryGitignored(rootDir: string): boolean;
|
|
8
|
+
//# sourceMappingURL=gitignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/init/gitignore.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYlE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
// IMPLEMENTATION_PLAN.md's telemetry spec: local-only, opt-in — never meant to be committed.
|
|
4
|
+
// Every other `.align/*` artifact (baseline.json, generated-rules.json, ruleset-ir.json) IS meant
|
|
5
|
+
// to be committed (align's own `.gitignore` only excludes `.align/cache/` and these two) — this
|
|
6
|
+
// must never blanket-ignore `.align/` itself.
|
|
7
|
+
const TELEMETRY_GITIGNORE_ENTRIES = ['.align/telemetry.jsonl', '.align/telemetry-state.json'];
|
|
8
|
+
/**
|
|
9
|
+
* `align init` ensures the target repo's `.gitignore` excludes telemetry's local-only files.
|
|
10
|
+
* Idempotent — only appends entries not already present (any line-trimmed match, not just an
|
|
11
|
+
* exact-position match), creates `.gitignore` from scratch if the repo doesn't have one yet.
|
|
12
|
+
* Returns whether it actually wrote anything (so `runInit` can decide whether to print a note).
|
|
13
|
+
*/
|
|
14
|
+
export function ensureTelemetryGitignored(rootDir) {
|
|
15
|
+
const gitignorePath = path.join(rootDir, '.gitignore');
|
|
16
|
+
const existing = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf8') : '';
|
|
17
|
+
const existingLines = new Set(existing.split(/\r?\n/).map((l) => l.trim()));
|
|
18
|
+
const missing = TELEMETRY_GITIGNORE_ENTRIES.filter((entry) => !existingLines.has(entry));
|
|
19
|
+
if (missing.length === 0)
|
|
20
|
+
return false;
|
|
21
|
+
const trimmed = existing.replace(/\s*$/, '');
|
|
22
|
+
const block = `# align telemetry (opt-in, local-only — ALIGN_TELEMETRY=1 / --telemetry / align.config.ts telemetry:true)\n${missing.join('\n')}\n`;
|
|
23
|
+
const content = trimmed.length === 0 ? block : `${trimmed}\n\n${block}`;
|
|
24
|
+
fs.writeFileSync(gitignorePath, content, 'utf8');
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=gitignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/init/gitignore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,6FAA6F;AAC7F,kGAAkG;AAClG,gGAAgG;AAChG,8CAA8C;AAC9C,MAAM,2BAA2B,GAAG,CAAC,wBAAwB,EAAE,6BAA6B,CAAU,CAAC;AAEvG;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACzF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,8GAA8G,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACnJ,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,OAAO,KAAK,EAAE,CAAC;IACxE,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DetectedComponent } from './detect-components.js';
|
|
2
|
+
import type { LayerSuggestion } from './suggest-layers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Renders the `align init` starter `align.config.ts`. Cycles-first (ADR 009: on the untouched,
|
|
5
|
+
* architecturally-healthy kluster repo, cycle detection found two real latent bugs while every
|
|
6
|
+
* `no-dependency` rule was green) — `arch.no-cycles()` ships active; the inferred layer
|
|
7
|
+
* statements ship commented out ("~3 layer macros commented sensibly," IMPLEMENTATION_PLAN.md
|
|
8
|
+
* Stage 1) since they're a suggestion a human should confirm, not a silently-enforced guess.
|
|
9
|
+
*
|
|
10
|
+
* `greenfieldComponents` (R4, greenfield mode, IMPLEMENTATION_PLAN.md Design Reserve): names of
|
|
11
|
+
* detected components that matched zero files at probe-scan time (or every component, under
|
|
12
|
+
* `align init --greenfield`) — rendered as `{ pattern, empty: 'until-populated' }` instead of the
|
|
13
|
+
* plain string shorthand, so architecture-first authoring works out of the box: rules referencing
|
|
14
|
+
* the component load immediately, `align check` shows it as ungrounded-but-green (R1) instead of a
|
|
15
|
+
* load-time crash, and the empty-check auto-arms the moment real files land.
|
|
16
|
+
*/
|
|
17
|
+
export declare function renderConfig(components: readonly DetectedComponent[], layers: readonly LayerSuggestion[], greenfieldComponents?: ReadonlySet<string>): string;
|
|
18
|
+
//# sourceMappingURL=render-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-config.d.ts","sourceRoot":"","sources":["../../src/init/render-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,oBAAoB,GAAE,WAAW,CAAC,MAAM,CAAa,GACpD,MAAM,CAgDR"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the `align init` starter `align.config.ts`. Cycles-first (ADR 009: on the untouched,
|
|
3
|
+
* architecturally-healthy kluster repo, cycle detection found two real latent bugs while every
|
|
4
|
+
* `no-dependency` rule was green) — `arch.no-cycles()` ships active; the inferred layer
|
|
5
|
+
* statements ship commented out ("~3 layer macros commented sensibly," IMPLEMENTATION_PLAN.md
|
|
6
|
+
* Stage 1) since they're a suggestion a human should confirm, not a silently-enforced guess.
|
|
7
|
+
*
|
|
8
|
+
* `greenfieldComponents` (R4, greenfield mode, IMPLEMENTATION_PLAN.md Design Reserve): names of
|
|
9
|
+
* detected components that matched zero files at probe-scan time (or every component, under
|
|
10
|
+
* `align init --greenfield`) — rendered as `{ pattern, empty: 'until-populated' }` instead of the
|
|
11
|
+
* plain string shorthand, so architecture-first authoring works out of the box: rules referencing
|
|
12
|
+
* the component load immediately, `align check` shows it as ungrounded-but-green (R1) instead of a
|
|
13
|
+
* load-time crash, and the empty-check auto-arms the moment real files land.
|
|
14
|
+
*/
|
|
15
|
+
export function renderConfig(components, layers, greenfieldComponents = new Set()) {
|
|
16
|
+
const componentLines = components
|
|
17
|
+
.map((c) => greenfieldComponents.has(c.name)
|
|
18
|
+
? ` ${JSON.stringify(c.name)}: { pattern: '${c.pattern}', empty: 'until-populated' }, // matched zero files at init time — architecture-first component, see the note above`
|
|
19
|
+
: ` ${JSON.stringify(c.name)}: '${c.pattern}',`)
|
|
20
|
+
.join('\n');
|
|
21
|
+
const layerLines = layers
|
|
22
|
+
.map((l) => {
|
|
23
|
+
const args = l.canDependOn.map((c) => `c.${c}`).join(', ');
|
|
24
|
+
const line = l.canDependOn.length === 0
|
|
25
|
+
? `c.arch.component(c.${l.layer}).isIsolated()`
|
|
26
|
+
: `c.arch.layer(c.${l.layer}).canOnlyDependOn(${args})`;
|
|
27
|
+
return ` // ${l.evidence}.\n // ${line},`;
|
|
28
|
+
})
|
|
29
|
+
.join('\n');
|
|
30
|
+
const greenfieldNote = greenfieldComponents.size > 0
|
|
31
|
+
? `//\n// ${greenfieldComponents.size} component(s) below matched zero files when \`align init\` ran (architecture-first ` +
|
|
32
|
+
`authoring — components declared before code exists). They're marked \`empty: 'until-populated'\`: ` +
|
|
33
|
+
`\`align check\` treats them as provisionally green (surfaced distinctly, never silently), and the ` +
|
|
34
|
+
`moment real files land under the selector the empty-check auto-arms — no manual flag flip needed. ` +
|
|
35
|
+
`Run \`align doctor\` any time to see which ones are still empty vs. ready to have the marker removed.\n`
|
|
36
|
+
: '';
|
|
37
|
+
return `import { defineProject } from '@spikedpunch/align-core/dsl';
|
|
38
|
+
|
|
39
|
+
// Generated by \`align init\`. Components are auto-detected from your workspace layout — review
|
|
40
|
+
// the names/patterns below and adjust as needed; they're a starting point, not a final answer.
|
|
41
|
+
${greenfieldNote}export default defineProject({
|
|
42
|
+
components: {
|
|
43
|
+
${componentLines}
|
|
44
|
+
},
|
|
45
|
+
rules: (c) => [
|
|
46
|
+
// Cycles-first (align's day-one value, per real evidence: cycle detection finds latent bugs
|
|
47
|
+
// on healthy repos far more often than dependency-direction rules do on first run).
|
|
48
|
+
c.arch.noCycles(),
|
|
49
|
+
|
|
50
|
+
// Suggested layering, inferred from today's measured cross-component edges. Uncomment the
|
|
51
|
+
// ones that reflect your intended architecture — each is backed by the evidence noted above it.
|
|
52
|
+
${layerLines.length > 0 ? layerLines : ' // (not enough cross-component edges detected yet to suggest a layering)'}
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=render-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-config.js","sourceRoot":"","sources":["../../src/init/render-config.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAC1B,UAAwC,EACxC,MAAkC,EAClC,uBAA4C,IAAI,GAAG,EAAE;IAErD,MAAM,cAAc,GAAG,UAAU;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9B,CAAC,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,sHAAsH;QAC/K,CAAC,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,IAAI,CACrD;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,UAAU,GAAG,MAAM;SACtB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,GACR,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;YACxB,CAAC,CAAC,sBAAsB,CAAC,CAAC,KAAK,gBAAgB;YAC/C,CAAC,CAAC,kBAAkB,CAAC,CAAC,KAAK,qBAAqB,IAAI,GAAG,CAAC;QAC5D,OAAO,UAAU,CAAC,CAAC,QAAQ,aAAa,IAAI,GAAG,CAAC;IAClD,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,cAAc,GAClB,oBAAoB,CAAC,IAAI,GAAG,CAAC;QAC3B,CAAC,CAAC,UAAU,oBAAoB,CAAC,IAAI,qFAAqF;YACxH,oGAAoG;YACpG,oGAAoG;YACpG,oGAAoG;YACpG,yGAAyG;QAC3G,CAAC,CAAC,EAAE,CAAC;IAET,OAAO;;;;EAIP,cAAc;;EAEd,cAAc;;;;;;;;;EASd,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,8EAA8E;;;CAGpH,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DependencyGraph } from '@spikedpunch/align-core';
|
|
2
|
+
export interface LayerSuggestion {
|
|
3
|
+
readonly layer: string;
|
|
4
|
+
readonly canDependOn: readonly string[];
|
|
5
|
+
readonly evidence: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Coarse 3-tier layering inferred from the measured cross-component edge matrix — "apps depend on
|
|
9
|
+
* libraries, libraries stay leaf" rather than kluster's hand-curated 8-component model (spike Q5).
|
|
10
|
+
* Mechanical, not semantic: components with only outgoing cross-component edges are "top" (apps),
|
|
11
|
+
* components with only incoming cross-component edges are "leaf" (libraries), everything else is
|
|
12
|
+
* "middle." `align init` renders these as commented-out DSL lines (IMPLEMENTATION_PLAN.md Stage 1:
|
|
13
|
+
* "~3 layer macros commented sensibly") — a human confirms before any of them go live.
|
|
14
|
+
*/
|
|
15
|
+
export declare function suggestLayers(graph: DependencyGraph): LayerSuggestion[];
|
|
16
|
+
//# sourceMappingURL=suggest-layers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-layers.d.ts","sourceRoot":"","sources":["../../src/init/suggest-layers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,EAAE,CAsDvE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coarse 3-tier layering inferred from the measured cross-component edge matrix — "apps depend on
|
|
3
|
+
* libraries, libraries stay leaf" rather than kluster's hand-curated 8-component model (spike Q5).
|
|
4
|
+
* Mechanical, not semantic: components with only outgoing cross-component edges are "top" (apps),
|
|
5
|
+
* components with only incoming cross-component edges are "leaf" (libraries), everything else is
|
|
6
|
+
* "middle." `align init` renders these as commented-out DSL lines (IMPLEMENTATION_PLAN.md Stage 1:
|
|
7
|
+
* "~3 layer macros commented sensibly") — a human confirms before any of them go live.
|
|
8
|
+
*/
|
|
9
|
+
export function suggestLayers(graph) {
|
|
10
|
+
const componentNames = [...new Set(graph.nodes.map((n) => n.component))].filter((c) => c !== '__unmapped__');
|
|
11
|
+
if (componentNames.length < 2)
|
|
12
|
+
return [];
|
|
13
|
+
const fileToComponent = new Map(graph.nodes.map((n) => [n.file, n.component]));
|
|
14
|
+
const outgoing = new Map();
|
|
15
|
+
const incoming = new Map();
|
|
16
|
+
const edgeCounts = new Map();
|
|
17
|
+
for (const edge of graph.edges) {
|
|
18
|
+
const from = fileToComponent.get(edge.from);
|
|
19
|
+
const to = fileToComponent.get(edge.to);
|
|
20
|
+
if (from === undefined || to === undefined || from === to)
|
|
21
|
+
continue;
|
|
22
|
+
(outgoing.get(from) ?? outgoing.set(from, new Set()).get(from))?.add(to);
|
|
23
|
+
(incoming.get(to) ?? incoming.set(to, new Set()).get(to))?.add(from);
|
|
24
|
+
const key = `${from}>${to}`;
|
|
25
|
+
edgeCounts.set(key, (edgeCounts.get(key) ?? 0) + 1);
|
|
26
|
+
}
|
|
27
|
+
const top = [];
|
|
28
|
+
const leaf = [];
|
|
29
|
+
const middle = [];
|
|
30
|
+
for (const name of componentNames) {
|
|
31
|
+
const hasOut = (outgoing.get(name)?.size ?? 0) > 0;
|
|
32
|
+
const hasIn = (incoming.get(name)?.size ?? 0) > 0;
|
|
33
|
+
if (hasOut && !hasIn)
|
|
34
|
+
top.push(name);
|
|
35
|
+
else if (hasIn && !hasOut)
|
|
36
|
+
leaf.push(name);
|
|
37
|
+
else
|
|
38
|
+
middle.push(name);
|
|
39
|
+
}
|
|
40
|
+
const suggestions = [];
|
|
41
|
+
if (top.length > 0 && (middle.length > 0 || leaf.length > 0)) {
|
|
42
|
+
const canDependOn = [...middle, ...leaf];
|
|
43
|
+
suggestions.push({
|
|
44
|
+
layer: top[0],
|
|
45
|
+
canDependOn,
|
|
46
|
+
evidence: `'${top[0]}' has outgoing edges into ${canDependOn.map((c) => `'${c}'`).join(', ')} and none pointing back`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (middle.length > 0 && leaf.length > 0) {
|
|
50
|
+
suggestions.push({
|
|
51
|
+
layer: middle[0],
|
|
52
|
+
canDependOn: leaf,
|
|
53
|
+
evidence: `'${middle[0]}' depends on ${leaf.map((c) => `'${c}'`).join(', ')}, which take no cross-component dependencies`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (leaf.length > 0) {
|
|
57
|
+
suggestions.push({
|
|
58
|
+
layer: leaf[0],
|
|
59
|
+
canDependOn: [],
|
|
60
|
+
evidence: `'${leaf[0]}' has no outgoing cross-component edges today — a candidate for isolation`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return suggestions.slice(0, 3);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=suggest-layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-layers.js","sourceRoot":"","sources":["../../src/init/suggest-layers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/** Builds the McpServer with tools registered but no transport attached — split out from
|
|
3
|
+
* `startMcpServer` so tests can connect it to an in-process `InMemoryTransport` instead of stdio
|
|
4
|
+
* (MCP contract tests via the SDK's own client, per the Stage 1 plan). */
|
|
5
|
+
export declare function createMcpServer(rootDir: string): McpServer;
|
|
6
|
+
export declare function startMcpServer(rootDir: string): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBpE;;0EAE0E;AAC1E,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CA4K1D;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnE"}
|