@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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/align-dir.d.ts +55 -0
  4. package/dist/align-dir.d.ts.map +1 -0
  5. package/dist/align-dir.js +184 -0
  6. package/dist/align-dir.js.map +1 -0
  7. package/dist/commands/agent.d.ts +14 -0
  8. package/dist/commands/agent.d.ts.map +1 -0
  9. package/dist/commands/agent.js +142 -0
  10. package/dist/commands/agent.js.map +1 -0
  11. package/dist/commands/baseline.d.ts +4 -0
  12. package/dist/commands/baseline.d.ts.map +1 -0
  13. package/dist/commands/baseline.js +57 -0
  14. package/dist/commands/baseline.js.map +1 -0
  15. package/dist/commands/build-report.d.ts +4 -0
  16. package/dist/commands/build-report.d.ts.map +1 -0
  17. package/dist/commands/build-report.js +122 -0
  18. package/dist/commands/build-report.js.map +1 -0
  19. package/dist/commands/build.d.ts +73 -0
  20. package/dist/commands/build.d.ts.map +1 -0
  21. package/dist/commands/build.js +289 -0
  22. package/dist/commands/build.js.map +1 -0
  23. package/dist/commands/check.d.ts +31 -0
  24. package/dist/commands/check.d.ts.map +1 -0
  25. package/dist/commands/check.js +203 -0
  26. package/dist/commands/check.js.map +1 -0
  27. package/dist/commands/doctor.d.ts +20 -0
  28. package/dist/commands/doctor.d.ts.map +1 -0
  29. package/dist/commands/doctor.js +173 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/explain.d.ts +3 -0
  32. package/dist/commands/explain.d.ts.map +1 -0
  33. package/dist/commands/explain.js +54 -0
  34. package/dist/commands/explain.js.map +1 -0
  35. package/dist/commands/export-ir.d.ts +21 -0
  36. package/dist/commands/export-ir.d.ts.map +1 -0
  37. package/dist/commands/export-ir.js +33 -0
  38. package/dist/commands/export-ir.js.map +1 -0
  39. package/dist/commands/init.d.ts +13 -0
  40. package/dist/commands/init.d.ts.map +1 -0
  41. package/dist/commands/init.js +93 -0
  42. package/dist/commands/init.js.map +1 -0
  43. package/dist/commands/skill.d.ts +20 -0
  44. package/dist/commands/skill.d.ts.map +1 -0
  45. package/dist/commands/skill.js +23 -0
  46. package/dist/commands/skill.js.map +1 -0
  47. package/dist/commands/telemetry.d.ts +52 -0
  48. package/dist/commands/telemetry.d.ts.map +1 -0
  49. package/dist/commands/telemetry.js +238 -0
  50. package/dist/commands/telemetry.js.map +1 -0
  51. package/dist/composition-root.d.ts +14 -0
  52. package/dist/composition-root.d.ts.map +1 -0
  53. package/dist/composition-root.js +18 -0
  54. package/dist/composition-root.js.map +1 -0
  55. package/dist/config.d.ts +31 -0
  56. package/dist/config.d.ts.map +1 -0
  57. package/dist/config.js +39 -0
  58. package/dist/config.js.map +1 -0
  59. package/dist/index.d.ts +3 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +4 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/init/claude-md.d.ts +6 -0
  64. package/dist/init/claude-md.d.ts.map +1 -0
  65. package/dist/init/claude-md.js +42 -0
  66. package/dist/init/claude-md.js.map +1 -0
  67. package/dist/init/config-comment.d.ts +7 -0
  68. package/dist/init/config-comment.d.ts.map +1 -0
  69. package/dist/init/config-comment.js +44 -0
  70. package/dist/init/config-comment.js.map +1 -0
  71. package/dist/init/detect-components.d.ts +16 -0
  72. package/dist/init/detect-components.d.ts.map +1 -0
  73. package/dist/init/detect-components.js +121 -0
  74. package/dist/init/detect-components.js.map +1 -0
  75. package/dist/init/gitignore.d.ts +8 -0
  76. package/dist/init/gitignore.d.ts.map +1 -0
  77. package/dist/init/gitignore.js +27 -0
  78. package/dist/init/gitignore.js.map +1 -0
  79. package/dist/init/render-config.d.ts +18 -0
  80. package/dist/init/render-config.d.ts.map +1 -0
  81. package/dist/init/render-config.js +57 -0
  82. package/dist/init/render-config.js.map +1 -0
  83. package/dist/init/suggest-layers.d.ts +16 -0
  84. package/dist/init/suggest-layers.d.ts.map +1 -0
  85. package/dist/init/suggest-layers.js +65 -0
  86. package/dist/init/suggest-layers.js.map +1 -0
  87. package/dist/mcp/server.d.ts +7 -0
  88. package/dist/mcp/server.d.ts.map +1 -0
  89. package/dist/mcp/server.js +182 -0
  90. package/dist/mcp/server.js.map +1 -0
  91. package/dist/program.d.ts +11 -0
  92. package/dist/program.d.ts.map +1 -0
  93. package/dist/program.js +199 -0
  94. package/dist/program.js.map +1 -0
  95. package/dist/skill/bullet-grammar.d.ts +2 -0
  96. package/dist/skill/bullet-grammar.d.ts.map +1 -0
  97. package/dist/skill/bullet-grammar.js +12 -0
  98. package/dist/skill/bullet-grammar.js.map +1 -0
  99. package/dist/skill/cli-inventory.d.ts +16 -0
  100. package/dist/skill/cli-inventory.d.ts.map +1 -0
  101. package/dist/skill/cli-inventory.js +17 -0
  102. package/dist/skill/cli-inventory.js.map +1 -0
  103. package/dist/skill/condensed.d.ts +2 -0
  104. package/dist/skill/condensed.d.ts.map +1 -0
  105. package/dist/skill/condensed.js +24 -0
  106. package/dist/skill/condensed.js.map +1 -0
  107. package/dist/skill/dsl-verbs.d.ts +2 -0
  108. package/dist/skill/dsl-verbs.d.ts.map +1 -0
  109. package/dist/skill/dsl-verbs.js +10 -0
  110. package/dist/skill/dsl-verbs.js.map +1 -0
  111. package/dist/skill/fix-loop-protocol.d.ts +18 -0
  112. package/dist/skill/fix-loop-protocol.d.ts.map +1 -0
  113. package/dist/skill/fix-loop-protocol.js +38 -0
  114. package/dist/skill/fix-loop-protocol.js.map +1 -0
  115. package/dist/skill/gates.d.ts +2 -0
  116. package/dist/skill/gates.d.ts.map +1 -0
  117. package/dist/skill/gates.js +20 -0
  118. package/dist/skill/gates.js.map +1 -0
  119. package/dist/skill/install.d.ts +25 -0
  120. package/dist/skill/install.d.ts.map +1 -0
  121. package/dist/skill/install.js +49 -0
  122. package/dist/skill/install.js.map +1 -0
  123. package/dist/skill/render.d.ts +15 -0
  124. package/dist/skill/render.d.ts.map +1 -0
  125. package/dist/skill/render.js +35 -0
  126. package/dist/skill/render.js.map +1 -0
  127. package/dist/skill/rule-kinds.d.ts +12 -0
  128. package/dist/skill/rule-kinds.d.ts.map +1 -0
  129. package/dist/skill/rule-kinds.js +47 -0
  130. package/dist/skill/rule-kinds.js.map +1 -0
  131. package/dist/skill/static-sections.d.ts +5 -0
  132. package/dist/skill/static-sections.d.ts.map +1 -0
  133. package/dist/skill/static-sections.js +74 -0
  134. package/dist/skill/static-sections.js.map +1 -0
  135. package/dist/skill/version-stamp.d.ts +22 -0
  136. package/dist/skill/version-stamp.d.ts.map +1 -0
  137. package/dist/skill/version-stamp.js +29 -0
  138. package/dist/skill/version-stamp.js.map +1 -0
  139. package/dist/telemetry/check-event.d.ts +7 -0
  140. package/dist/telemetry/check-event.d.ts.map +1 -0
  141. package/dist/telemetry/check-event.js +29 -0
  142. package/dist/telemetry/check-event.js.map +1 -0
  143. package/dist/telemetry/index.d.ts +8 -0
  144. package/dist/telemetry/index.d.ts.map +1 -0
  145. package/dist/telemetry/index.js +8 -0
  146. package/dist/telemetry/index.js.map +1 -0
  147. package/dist/telemetry/process-context.d.ts +9 -0
  148. package/dist/telemetry/process-context.d.ts.map +1 -0
  149. package/dist/telemetry/process-context.js +10 -0
  150. package/dist/telemetry/process-context.js.map +1 -0
  151. package/dist/telemetry/recorder.d.ts +43 -0
  152. package/dist/telemetry/recorder.d.ts.map +1 -0
  153. package/dist/telemetry/recorder.js +61 -0
  154. package/dist/telemetry/recorder.js.map +1 -0
  155. package/dist/telemetry/resolve.d.ts +19 -0
  156. package/dist/telemetry/resolve.d.ts.map +1 -0
  157. package/dist/telemetry/resolve.js +18 -0
  158. package/dist/telemetry/resolve.js.map +1 -0
  159. package/dist/telemetry/ruleset-hash.d.ts +10 -0
  160. package/dist/telemetry/ruleset-hash.d.ts.map +1 -0
  161. package/dist/telemetry/ruleset-hash.js +12 -0
  162. package/dist/telemetry/ruleset-hash.js.map +1 -0
  163. package/dist/telemetry/session.d.ts +6 -0
  164. package/dist/telemetry/session.d.ts.map +1 -0
  165. package/dist/telemetry/session.js +9 -0
  166. package/dist/telemetry/session.js.map +1 -0
  167. package/dist/telemetry/violations.d.ts +10 -0
  168. package/dist/telemetry/violations.d.ts.map +1 -0
  169. package/dist/telemetry/violations.js +36 -0
  170. package/dist/telemetry/violations.js.map +1 -0
  171. package/package.json +58 -0
@@ -0,0 +1,93 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as readline from 'node:readline/promises';
4
+ import { defineProject } from '@spikedpunch/align-core/dsl';
5
+ import { toComponentName } from '@spikedpunch/align-core';
6
+ import { TypeScriptPlugin } from '@spikedpunch/align-plugin-typescript';
7
+ import { detectComponents } from '../init/detect-components.js';
8
+ import { suggestLayers } from '../init/suggest-layers.js';
9
+ import { renderConfig } from '../init/render-config.js';
10
+ import { writeAgentInstructions } from '../init/claude-md.js';
11
+ import { writeGeneratedRulesNote } from '../init/config-comment.js';
12
+ import { ensureTelemetryGitignored } from '../init/gitignore.js';
13
+ import { createOrchestrator } from '../composition-root.js';
14
+ import { CONFIG_FILENAME, loadConfig } from '../config.js';
15
+ import { writeBaseline, ensureAlignDir } from '../align-dir.js';
16
+ export async function runInit(rootDir, options) {
17
+ const configPath = path.join(rootDir, CONFIG_FILENAME);
18
+ ensureAlignDir(rootDir);
19
+ if (!fs.existsSync(configPath)) {
20
+ const detected = detectComponents(rootDir);
21
+ console.log(`Detected ${detected.length} component(s): ${detected.map((c) => c.name).join(', ')}`);
22
+ // Scan once with components-only (no rules yet) to derive layer suggestions from real edges.
23
+ // `empty: 'allow'` here (not the default 'fail') so the probe scan never crashes on a
24
+ // greenfield repo before we've even had a chance to decide which components need the
25
+ // until-populated marker below — this is a throwaway probe ruleset, never written to disk.
26
+ const componentsInput = Object.fromEntries(detected.map((c) => [c.name, { pattern: c.pattern, empty: 'allow' }]));
27
+ const probeRuleset = defineProject({ components: componentsInput });
28
+ const plugin = new TypeScriptPlugin();
29
+ const graph = await plugin.scanner.scan({ rootDir, components: probeRuleset.components, excludes: [] });
30
+ const layers = suggestLayers(graph);
31
+ // R4: components matching zero files right now (or every component, under --greenfield) get
32
+ // `empty: 'until-populated'` instead of the default fail-on-empty — architecture-first
33
+ // authoring (rules declared before code) works out of the box instead of hitting
34
+ // `ComponentValidationError` on the very first `align check`.
35
+ const populatedNames = new Set(graph.nodes.map((n) => n.component));
36
+ const greenfieldComponents = new Set(detected.filter((c) => options.greenfield === true || !populatedNames.has(toComponentName(c.name))).map((c) => c.name));
37
+ fs.writeFileSync(configPath, renderConfig(detected, layers, greenfieldComponents), 'utf8');
38
+ console.log(`Wrote ${CONFIG_FILENAME} (cycles-first starter ruleset; ${layers.length} layer suggestion(s) commented out).`);
39
+ if (greenfieldComponents.size > 0) {
40
+ const reason = options.greenfield === true ? '--greenfield' : 'matched zero files';
41
+ console.log(`${greenfieldComponents.size} component(s) (${reason}) set to empty: 'until-populated' ` +
42
+ `(architecture-first authoring: rules load now, enforcement auto-arms once files land): ` +
43
+ `${[...greenfieldComponents].join(', ')}.`);
44
+ }
45
+ }
46
+ else {
47
+ console.log(`${CONFIG_FILENAME} already exists — leaving it as-is.`);
48
+ }
49
+ writeGeneratedRulesNote(configPath);
50
+ writeAgentInstructions(rootDir);
51
+ console.log('Wrote/updated CLAUDE.md agent-instructions block.');
52
+ if (ensureTelemetryGitignored(rootDir)) {
53
+ console.log('Wrote/updated .gitignore (excluded .align/telemetry.jsonl + .align/telemetry-state.json — opt-in, local-only).');
54
+ }
55
+ const { ruleset, excludes, hostRules } = await loadConfig(rootDir);
56
+ const { orchestrator } = createOrchestrator(ruleset, [], hostRules);
57
+ const run = await orchestrator.check({ rootDir, excludes });
58
+ const violations = run.gates.flatMap((g) => g.violations);
59
+ if (violations.length === 0) {
60
+ writeBaseline(rootDir, []);
61
+ console.log('Initial check is green — no baseline seeding needed.');
62
+ return 0;
63
+ }
64
+ const isInteractive = options.nonInteractive === true ? false : (options.nonInteractive ?? process.stdin.isTTY === true);
65
+ if (!options.acceptExisting && !isInteractive) {
66
+ console.log(`align check found ${violations.length} pre-existing violation(s). Re-run with --accept-existing to seed ` +
67
+ `the baseline non-interactively (silence is never consent — ADR 006), or run interactively to be prompted.`);
68
+ return 1;
69
+ }
70
+ let shouldSeed = options.acceptExisting;
71
+ if (!shouldSeed && isInteractive) {
72
+ console.log(`\nalign check found ${violations.length} pre-existing violation(s) — this is normal on a repo align hasn't seen before.`);
73
+ console.log('Seeding the baseline tolerates them as existing debt; run `align baseline show` any time to review what was seeded.');
74
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
75
+ const answer = await rl.question('Seed the baseline with these violations now? [y/N] ');
76
+ rl.close();
77
+ shouldSeed = /^y(es)?$/i.test(answer.trim());
78
+ }
79
+ if (!shouldSeed) {
80
+ console.log('Not seeding the baseline. `align check` will report red until you fix these or run `align baseline accept`.');
81
+ return 1;
82
+ }
83
+ writeBaseline(rootDir, violations.map((v) => ({
84
+ fingerprint: v.id,
85
+ ruleId: v.ruleId,
86
+ file: v.file,
87
+ acceptedAt: Date.now(),
88
+ acceptedBy: options.acceptExisting ? 'accept-existing' : 'init-seed',
89
+ })));
90
+ console.log(`Seeded baseline with ${violations.length} pre-existing violation(s) — run \`align baseline show\` to review.`);
91
+ return 0;
92
+ }
93
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Command } from 'commander';
2
+ import { type SkillTopic } from '../skill/render.js';
3
+ export type { SkillTopic };
4
+ export interface SkillOptions {
5
+ readonly topic: SkillTopic;
6
+ readonly install: boolean;
7
+ }
8
+ /**
9
+ * `align skill` (Stage 5, IMPLEMENTATION_PLAN.md "Elevated first items"): emits the LLM-facing
10
+ * authoring/fixing guide, generated live from the installed binary's own registries so it cannot
11
+ * drift from what this specific install actually supports. `--install` additionally writes
12
+ * `.claude/skills/align/SKILL.md` into the target repo (cwd).
13
+ *
14
+ * `program` is the already-built `commander` tree the CLI command inventory section reads
15
+ * (`../program.js`'s `buildProgram()`'s own `program` closure variable, passed in by its `skill`
16
+ * action rather than re-imported here — see `skill/cli-inventory.ts`'s doc comment for why a
17
+ * static import back to `program.ts` would be a dependency cycle).
18
+ */
19
+ export declare function runSkill(rootDir: string, options: SkillOptions, program: Command): Promise<number>;
20
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG1E,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAUxG"}
@@ -0,0 +1,23 @@
1
+ import { renderSkillMarkdown } from '../skill/render.js';
2
+ import { writeSkillFile } from '../skill/install.js';
3
+ /**
4
+ * `align skill` (Stage 5, IMPLEMENTATION_PLAN.md "Elevated first items"): emits the LLM-facing
5
+ * authoring/fixing guide, generated live from the installed binary's own registries so it cannot
6
+ * drift from what this specific install actually supports. `--install` additionally writes
7
+ * `.claude/skills/align/SKILL.md` into the target repo (cwd).
8
+ *
9
+ * `program` is the already-built `commander` tree the CLI command inventory section reads
10
+ * (`../program.js`'s `buildProgram()`'s own `program` closure variable, passed in by its `skill`
11
+ * action rather than re-imported here — see `skill/cli-inventory.ts`'s doc comment for why a
12
+ * static import back to `program.ts` would be a dependency cycle).
13
+ */
14
+ export async function runSkill(rootDir, options, program) {
15
+ const markdown = renderSkillMarkdown(options.topic, program);
16
+ process.stdout.write(`${markdown}\n`);
17
+ if (options.install) {
18
+ const filePath = writeSkillFile(rootDir, program);
19
+ console.error(`Wrote ${filePath}`);
20
+ }
21
+ return 0;
22
+ }
23
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAmB,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AASrD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe,EAAE,OAAqB,EAAE,OAAgB;IACrF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC;IAEtC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,52 @@
1
+ export declare const DEFAULT_TELEMETRY_FILE = ".align/telemetry.jsonl";
2
+ export interface TelemetryReportOptions {
3
+ readonly file?: string;
4
+ readonly json: boolean;
5
+ }
6
+ interface LatencyStats {
7
+ readonly count: number;
8
+ readonly p50?: number;
9
+ readonly p90?: number;
10
+ readonly p99?: number;
11
+ }
12
+ interface RuleFiringCount {
13
+ readonly ruleId: string;
14
+ readonly count: number;
15
+ }
16
+ interface TimeToGreen {
17
+ readonly ruleId: string;
18
+ readonly resolvedCount: number;
19
+ readonly avgMs: number;
20
+ readonly medianMs: number;
21
+ }
22
+ interface FrictionCount {
23
+ readonly errorKind: string;
24
+ readonly count: number;
25
+ }
26
+ interface SegmentLatency {
27
+ readonly key: string;
28
+ readonly checks: number;
29
+ readonly p50?: number;
30
+ }
31
+ export interface TelemetrySummary {
32
+ readonly totalEvents: number;
33
+ readonly skippedLines: number;
34
+ readonly checkLatencyMs: LatencyStats;
35
+ readonly topFiringRules: readonly RuleFiringCount[];
36
+ readonly timeToGreen: readonly TimeToGreen[];
37
+ readonly deadRules: readonly string[];
38
+ readonly baselineVsFix: {
39
+ readonly baselined: number;
40
+ readonly resolved: number;
41
+ readonly ratio?: number;
42
+ };
43
+ readonly friction: readonly FrictionCount[];
44
+ readonly segments: {
45
+ readonly bySession: readonly SegmentLatency[];
46
+ readonly byAlignVersion: readonly SegmentLatency[];
47
+ };
48
+ }
49
+ export declare function buildTelemetrySummary(rootDir: string, filePath: string): Promise<TelemetrySummary>;
50
+ export declare function runTelemetryReport(rootDir: string, options: TelemetryReportOptions): Promise<number>;
51
+ export {};
52
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/commands/telemetry.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAoCD,UAAU,YAAY;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAeD,UAAU,eAAe;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,cAAc;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,YAAY,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;IACpD,QAAQ,CAAC,WAAW,EAAE,SAAS,WAAW,EAAE,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3G,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,SAAS,cAAc,EAAE,CAAA;KAAE,CAAC;CAC1H;AAuDD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2CxG;AAkFD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1G"}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * `align telemetry` — turns the raw `.align/telemetry.jsonl` accretion into the report a
3
+ * human/coordinator actually reads (IMPLEMENTATION_PLAN.md's telemetry spec): check-latency
4
+ * percentiles, top-firing rules, time-to-green per rule, dead rules, baseline-vs-fix ratio, and
5
+ * friction ranking. Reads only — never writes telemetry.jsonl itself.
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import { telemetryJsonlPath } from '../align-dir.js';
9
+ import { loadConfig } from '../config.js';
10
+ export const DEFAULT_TELEMETRY_FILE = '.align/telemetry.jsonl';
11
+ /** Malformed lines (a hand-edited file, a truncated write from a crashed process) are skipped, not
12
+ * fatal — this is an analysis tool over an append-only log, not a schema boundary anything else
13
+ * depends on (unlike `.align/generated-rules.json`'s "corrupted is never absent" discipline). */
14
+ function parseLines(raw) {
15
+ const envelopes = [];
16
+ let skipped = 0;
17
+ for (const line of raw.split('\n')) {
18
+ const trimmed = line.trim();
19
+ if (trimmed.length === 0)
20
+ continue;
21
+ try {
22
+ const parsed = JSON.parse(trimmed);
23
+ if (parsed !== null && typeof parsed === 'object' && 'event' in parsed && 'command' in parsed) {
24
+ envelopes.push(parsed);
25
+ }
26
+ else {
27
+ skipped += 1;
28
+ }
29
+ }
30
+ catch {
31
+ skipped += 1;
32
+ }
33
+ }
34
+ return { envelopes, skipped };
35
+ }
36
+ function percentile(sortedAsc, p) {
37
+ if (sortedAsc.length === 0)
38
+ return undefined;
39
+ const idx = Math.min(sortedAsc.length - 1, Math.max(0, Math.ceil((p / 100) * sortedAsc.length) - 1));
40
+ return sortedAsc[idx];
41
+ }
42
+ function latencyStats(wallMsValues) {
43
+ const sorted = [...wallMsValues].sort((a, b) => a - b);
44
+ const p50 = percentile(sorted, 50);
45
+ const p90 = percentile(sorted, 90);
46
+ const p99 = percentile(sorted, 99);
47
+ return {
48
+ count: sorted.length,
49
+ ...(p50 !== undefined ? { p50 } : {}),
50
+ ...(p90 !== undefined ? { p90 } : {}),
51
+ ...(p99 !== undefined ? { p99 } : {}),
52
+ };
53
+ }
54
+ function median(values) {
55
+ const sorted = [...values].sort((a, b) => a - b);
56
+ const mid = Math.floor(sorted.length / 2);
57
+ const midValue = sorted[mid];
58
+ const midValueBefore = sorted[mid - 1];
59
+ if (midValue === undefined)
60
+ return 0;
61
+ return sorted.length % 2 === 0 && midValueBefore !== undefined ? (midValueBefore + midValue) / 2 : midValue;
62
+ }
63
+ function computeTimeToGreen(envelopes) {
64
+ // Processed in file order (append-only log — the order events were written IS the order they
65
+ // occurred) so an `appeared` is always seen before the `resolved` that closes it out.
66
+ const openByFingerprint = new Map();
67
+ const deltasByRule = new Map();
68
+ for (const env of envelopes) {
69
+ if (env.event.kind !== 'violation-appeared' && env.event.kind !== 'violation-resolved')
70
+ continue;
71
+ const event = env.event;
72
+ if (event.kind === 'violation-appeared') {
73
+ openByFingerprint.set(event.violationFingerprint, { ruleId: event.ruleId, ts: env.ts });
74
+ continue;
75
+ }
76
+ const opened = openByFingerprint.get(event.violationFingerprint);
77
+ if (opened === undefined)
78
+ continue; // resolved without a seen appear (pre-dates this telemetry log) — not measurable
79
+ openByFingerprint.delete(event.violationFingerprint);
80
+ const deltaMs = env.ts - opened.ts;
81
+ const list = deltasByRule.get(opened.ruleId);
82
+ if (list === undefined)
83
+ deltasByRule.set(opened.ruleId, [deltaMs]);
84
+ else
85
+ list.push(deltaMs);
86
+ }
87
+ return [...deltasByRule.entries()]
88
+ .map(([ruleId, deltas]) => ({
89
+ ruleId,
90
+ resolvedCount: deltas.length,
91
+ avgMs: deltas.reduce((a, b) => a + b, 0) / deltas.length,
92
+ medianMs: median(deltas),
93
+ }))
94
+ .sort((a, b) => b.resolvedCount - a.resolvedCount);
95
+ }
96
+ async function computeDeadRules(rootDir, firedRuleIds) {
97
+ try {
98
+ const { ruleset } = await loadConfig(rootDir);
99
+ return ruleset.rules.map((r) => r.id).filter((id) => !firedRuleIds.has(id));
100
+ }
101
+ catch {
102
+ // align.config.ts is unreadable/missing right now (e.g. summarizing a JSONL copied off a
103
+ // different checkout) — dead-rule analysis needs today's active ruleset to mean anything;
104
+ // every other section of the report is still computed from the log alone.
105
+ return [];
106
+ }
107
+ }
108
+ export async function buildTelemetrySummary(rootDir, filePath) {
109
+ const raw = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';
110
+ const { envelopes, skipped } = parseLines(raw);
111
+ const checkWallMs = envelopes.filter((e) => e.event.kind === 'check').map((e) => e.event.wallMs);
112
+ const appearedCounts = new Map();
113
+ for (const e of envelopes) {
114
+ if (e.event.kind !== 'violation-appeared')
115
+ continue;
116
+ const ruleId = e.event.ruleId;
117
+ appearedCounts.set(ruleId, (appearedCounts.get(ruleId) ?? 0) + 1);
118
+ }
119
+ const topFiringRules = [...appearedCounts.entries()]
120
+ .map(([ruleId, count]) => ({ ruleId, count }))
121
+ .sort((a, b) => b.count - a.count);
122
+ const resolvedCount = envelopes.filter((e) => e.event.kind === 'violation-resolved').length;
123
+ const baselinedCount = envelopes
124
+ .filter((e) => e.event.kind === 'baseline' && e.event.action === 'accept')
125
+ .reduce((sum, e) => sum + (e.event.counts.accepted ?? 0), 0);
126
+ const frictionCounts = new Map();
127
+ for (const e of envelopes) {
128
+ if (e.event.kind !== 'error')
129
+ continue;
130
+ const kind = e.event.errorKind;
131
+ frictionCounts.set(kind, (frictionCounts.get(kind) ?? 0) + 1);
132
+ }
133
+ const friction = [...frictionCounts.entries()].map(([errorKind, count]) => ({ errorKind, count })).sort((a, b) => b.count - a.count);
134
+ const bySession = segmentLatency(envelopes, (e) => e.sessionId);
135
+ const byAlignVersion = segmentLatency(envelopes, (e) => e.alignVersion);
136
+ const total = baselinedCount + resolvedCount;
137
+ return {
138
+ totalEvents: envelopes.length,
139
+ skippedLines: skipped,
140
+ checkLatencyMs: latencyStats(checkWallMs),
141
+ topFiringRules,
142
+ timeToGreen: computeTimeToGreen(envelopes),
143
+ deadRules: await computeDeadRules(rootDir, new Set(appearedCounts.keys())),
144
+ baselineVsFix: { baselined: baselinedCount, resolved: resolvedCount, ...(total > 0 ? { ratio: baselinedCount / total } : {}) },
145
+ friction,
146
+ segments: { bySession, byAlignVersion },
147
+ };
148
+ }
149
+ function segmentLatency(envelopes, keyOf) {
150
+ const byKey = new Map();
151
+ for (const e of envelopes) {
152
+ if (e.event.kind !== 'check')
153
+ continue;
154
+ const key = keyOf(e);
155
+ const list = byKey.get(key);
156
+ const wallMs = e.event.wallMs;
157
+ if (list === undefined)
158
+ byKey.set(key, [wallMs]);
159
+ else
160
+ list.push(wallMs);
161
+ }
162
+ return [...byKey.entries()]
163
+ .map(([key, values]) => {
164
+ const sorted = [...values].sort((a, b) => a - b);
165
+ const p50 = percentile(sorted, 50);
166
+ return { key, checks: values.length, ...(p50 !== undefined ? { p50 } : {}) };
167
+ })
168
+ .sort((a, b) => b.checks - a.checks);
169
+ }
170
+ function fmtMs(ms) {
171
+ if (ms === undefined)
172
+ return 'n/a';
173
+ if (ms < 1000)
174
+ return `${Math.round(ms)}ms`;
175
+ return `${(ms / 1000).toFixed(1)}s`;
176
+ }
177
+ function printHuman(summary) {
178
+ console.log(`align telemetry — ${summary.totalEvents} event(s) read${summary.skippedLines > 0 ? ` (${summary.skippedLines} malformed line(s) skipped)` : ''}`);
179
+ console.log('\ncheck latency:');
180
+ if (summary.checkLatencyMs.count === 0) {
181
+ console.log(' no check events recorded yet.');
182
+ }
183
+ else {
184
+ console.log(` p50=${fmtMs(summary.checkLatencyMs.p50)} p90=${fmtMs(summary.checkLatencyMs.p90)} ` +
185
+ `p99=${fmtMs(summary.checkLatencyMs.p99)} (n=${summary.checkLatencyMs.count})`);
186
+ }
187
+ console.log('\ntop-firing rules:');
188
+ if (summary.topFiringRules.length === 0) {
189
+ console.log(' none.');
190
+ }
191
+ else {
192
+ for (const r of summary.topFiringRules.slice(0, 20))
193
+ console.log(` ${r.count.toString().padStart(4)} ${r.ruleId}`);
194
+ }
195
+ console.log('\ntime-to-green per rule (appeared -> resolved):');
196
+ if (summary.timeToGreen.length === 0) {
197
+ console.log(' no appear->resolve transitions observed yet.');
198
+ }
199
+ else {
200
+ for (const t of summary.timeToGreen) {
201
+ console.log(` ${t.ruleId}: avg=${fmtMs(t.avgMs)} median=${fmtMs(t.medianMs)} (n=${t.resolvedCount})`);
202
+ }
203
+ }
204
+ console.log('\ndead rules (in the active ruleset, never fired):');
205
+ console.log(summary.deadRules.length === 0 ? ' none.' : summary.deadRules.map((r) => ` ${r}`).join('\n'));
206
+ console.log('\nbaseline-vs-fix:');
207
+ console.log(` baselined=${summary.baselineVsFix.baselined} resolved(fixed)=${summary.baselineVsFix.resolved}` +
208
+ (summary.baselineVsFix.ratio !== undefined ? ` baseline-ratio=${(summary.baselineVsFix.ratio * 100).toFixed(0)}%` : ''));
209
+ console.log('\nfriction (error events by kind):');
210
+ if (summary.friction.length === 0) {
211
+ console.log(' none.');
212
+ }
213
+ else {
214
+ for (const f of summary.friction)
215
+ console.log(` ${f.count.toString().padStart(4)} ${f.errorKind}`);
216
+ }
217
+ if (summary.segments.bySession.length > 1) {
218
+ console.log('\nby session (check latency p50):');
219
+ for (const s of summary.segments.bySession)
220
+ console.log(` ${s.key}: ${s.checks} check(s), p50=${fmtMs(s.p50)}`);
221
+ }
222
+ if (summary.segments.byAlignVersion.length > 1) {
223
+ console.log('\nby align version (check latency p50):');
224
+ for (const s of summary.segments.byAlignVersion)
225
+ console.log(` ${s.key}: ${s.checks} check(s), p50=${fmtMs(s.p50)}`);
226
+ }
227
+ }
228
+ export async function runTelemetryReport(rootDir, options) {
229
+ const filePath = telemetryJsonlPath(rootDir, options.file);
230
+ const summary = await buildTelemetrySummary(rootDir, filePath);
231
+ if (options.json) {
232
+ process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
233
+ return 0;
234
+ }
235
+ printHuman(summary);
236
+ return 0;
237
+ }
238
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/commands/telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `@spikedpunch/align-cli` is the composition root (ARCHITECTURE.md §5): the only package that imports a
3
+ * concrete `LanguagePlugin` and registers it. Core never imports `plugin-typescript` directly.
4
+ */
5
+ import { GateOrchestrator, InMemoryBaselineStore, type BaselineEntry, type HostPredicateRegistry, type RulesetIR } from '@spikedpunch/align-core';
6
+ /** `hostPredicates` defaults to empty so every existing caller keeps working unchanged; a real
7
+ * `align.config.ts` with a `hostRules` export flows its extracted registry (`config.ts`'s
8
+ * `LoadedConfig.hostRules`) in here — this is the one place align's CLI wires the config-side
9
+ * predicate functions into core's evaluator (docs/proposals/rule-expansion-evaluation.md §B.0). */
10
+ export declare function createOrchestrator(ruleset: RulesetIR, baselineEntries: readonly BaselineEntry[], hostPredicates?: HostPredicateRegistry): {
11
+ readonly orchestrator: GateOrchestrator;
12
+ readonly baselineStore: InMemoryBaselineStore;
13
+ };
14
+ //# sourceMappingURL=composition-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition-root.d.ts","sourceRoot":"","sources":["../src/composition-root.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EAErB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACf,MAAM,yBAAyB,CAAC;AAGjC;;;mGAGmG;AACnG,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,EAClB,eAAe,EAAE,SAAS,aAAa,EAAE,EACzC,cAAc,GAAE,qBAAiC,GAChD;IACD,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;CAC/C,CAMA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `@spikedpunch/align-cli` is the composition root (ARCHITECTURE.md §5): the only package that imports a
3
+ * concrete `LanguagePlugin` and registers it. Core never imports `plugin-typescript` directly.
4
+ */
5
+ import { GateOrchestrator, InMemoryBaselineStore, StaticPluginRegistry, } from '@spikedpunch/align-core';
6
+ import { NodeManifestScanner, TypeScriptPlugin } from '@spikedpunch/align-plugin-typescript';
7
+ /** `hostPredicates` defaults to empty so every existing caller keeps working unchanged; a real
8
+ * `align.config.ts` with a `hostRules` export flows its extracted registry (`config.ts`'s
9
+ * `LoadedConfig.hostRules`) in here — this is the one place align's CLI wires the config-side
10
+ * predicate functions into core's evaluator (docs/proposals/rule-expansion-evaluation.md §B.0). */
11
+ export function createOrchestrator(ruleset, baselineEntries, hostPredicates = new Map()) {
12
+ const registry = new StaticPluginRegistry([new TypeScriptPlugin()]);
13
+ const baselineStore = new InMemoryBaselineStore(baselineEntries);
14
+ const manifestScanner = new NodeManifestScanner();
15
+ const orchestrator = new GateOrchestrator(registry, ruleset, baselineStore, hostPredicates, manifestScanner);
16
+ return { orchestrator, baselineStore };
17
+ }
18
+ //# sourceMappingURL=composition-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition-root.js","sourceRoot":"","sources":["../src/composition-root.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,GAIrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7F;;;mGAGmG;AACnG,MAAM,UAAU,kBAAkB,CAChC,OAAkB,EAClB,eAAyC,EACzC,iBAAwC,IAAI,GAAG,EAAE;IAKjD,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,IAAI,qBAAqB,CAAC,eAAe,CAAC,CAAC;IACjE,MAAM,eAAe,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;IAC7G,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type HostPredicateRegistry, type RulesetIR } from '@spikedpunch/align-core';
2
+ export interface LoadedConfig {
3
+ readonly ruleset: RulesetIR;
4
+ readonly excludes: readonly string[];
5
+ readonly hostRules: HostPredicateRegistry;
6
+ readonly telemetry?: boolean;
7
+ }
8
+ export interface LoadConfigOptions {
9
+ /** Merge `.align/generated-rules.json` into the loaded ruleset when present (ADR 011's
10
+ * config-integration mechanism — see `@spikedpunch/align-core`'s `mergeGeneratedRules`). Defaults to `true`
11
+ * so every existing surface (`check`, `doctor`, `mcp`) enforces doc-built rules automatically,
12
+ * with zero required edits to `align.config.ts`. `align build`'s own dry-run pipeline passes
13
+ * `false` to see the hand-authored ruleset in isolation, since it needs to diff the CURRENT
14
+ * on-disk generated rules against a freshly PROPOSED set, not a set that's already merged in. */
15
+ readonly includeGenerated?: boolean;
16
+ }
17
+ export declare const CONFIG_FILENAME = "align.config.ts";
18
+ /**
19
+ * Loads `align.config.ts` from the repo root. Node 22+ strips TypeScript types natively on
20
+ * dynamic import of a `.ts` file (verified: no `tsx`/`jiti` dependency needed for erasable
21
+ * syntax) — align.config.ts is restricted to erasable TS (interfaces, type annotations; no
22
+ * enums/parameter-properties) precisely so this keeps working without a build step.
23
+ *
24
+ * ADR 011 config-integration mechanism: after loading the hand-authored ruleset, this merges in
25
+ * `.align/generated-rules.json` when present (`mergeGeneratedRules`, `@spikedpunch/align-core/build`) — the
26
+ * loader boundary was chosen over an explicit `withGeneratedRules()` call in every
27
+ * `align.config.ts` (or `defineProject` doing its own fs I/O) as the least-magical option that
28
+ * still requires zero human edits to the config file; see the Stage 3 final report.
29
+ */
30
+ export declare function loadConfig(rootDir: string, options?: LoadConfigOptions): Promise<LoadedConfig>;
31
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2C,KAAK,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAG9H,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAK5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAOrC,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;IAO1C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAMD,MAAM,WAAW,iBAAiB;IAChC;;;;;qGAKiG;IACjG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBxG"}
package/dist/config.js ADDED
@@ -0,0 +1,39 @@
1
+ import * as path from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { mergeGeneratedRules } from '@spikedpunch/align-core';
4
+ import { readGeneratedRules } from './align-dir.js';
5
+ function toHostPredicateRegistry(hostRules) {
6
+ return new Map(Object.entries(hostRules ?? {}));
7
+ }
8
+ export const CONFIG_FILENAME = 'align.config.ts';
9
+ /**
10
+ * Loads `align.config.ts` from the repo root. Node 22+ strips TypeScript types natively on
11
+ * dynamic import of a `.ts` file (verified: no `tsx`/`jiti` dependency needed for erasable
12
+ * syntax) — align.config.ts is restricted to erasable TS (interfaces, type annotations; no
13
+ * enums/parameter-properties) precisely so this keeps working without a build step.
14
+ *
15
+ * ADR 011 config-integration mechanism: after loading the hand-authored ruleset, this merges in
16
+ * `.align/generated-rules.json` when present (`mergeGeneratedRules`, `@spikedpunch/align-core/build`) — the
17
+ * loader boundary was chosen over an explicit `withGeneratedRules()` call in every
18
+ * `align.config.ts` (or `defineProject` doing its own fs I/O) as the least-magical option that
19
+ * still requires zero human edits to the config file; see the Stage 3 final report.
20
+ */
21
+ export async function loadConfig(rootDir, options = {}) {
22
+ const includeGenerated = options.includeGenerated ?? true;
23
+ const configPath = path.join(rootDir, CONFIG_FILENAME);
24
+ const mod = (await import(pathToFileURL(configPath).href));
25
+ if (mod.default === undefined) {
26
+ throw new Error(`${CONFIG_FILENAME} must have a default export (the result of defineProject(...)).`);
27
+ }
28
+ const excludes = mod.excludes ?? [];
29
+ const hostRules = toHostPredicateRegistry(mod.hostRules);
30
+ const telemetry = mod.telemetry !== undefined ? { telemetry: mod.telemetry } : {};
31
+ if (!includeGenerated)
32
+ return { ruleset: mod.default, excludes, hostRules, ...telemetry };
33
+ const generated = readGeneratedRules(rootDir);
34
+ if (generated === undefined)
35
+ return { ruleset: mod.default, excludes, hostRules, ...telemetry };
36
+ const mergedRules = mergeGeneratedRules(mod.default.rules, generated.rules);
37
+ return { ruleset: { ...mod.default, rules: [...mergedRules] }, excludes, hostRules, ...telemetry };
38
+ }
39
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAkE,MAAM,yBAAyB,CAAC;AAC9H,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAyBpD,SAAS,uBAAuB,CAAC,SAAoD;IACnF,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;AAClD,CAAC;AAYD,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,UAA6B,EAAE;IAC/E,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAKxD,CAAC;IACF,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,eAAe,iEAAiE,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAElF,IAAI,CAAC,gBAAgB;QAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;IAE1F,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;IAEhG,MAAM,WAAW,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5E,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;AACrG,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { buildProgram } from './program.js';
3
+ await buildProgram().parseAsync(process.argv);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,YAAY,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Idempotent, HTML-comment-delimited write (ADR 009 consequence): re-running `align init` never
3
+ * duplicates or corrupts human-authored instructions around the block.
4
+ */
5
+ export declare function writeAgentInstructions(rootDir: string, filename?: string): void;
6
+ //# sourceMappingURL=claude-md.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/init/claude-md.ts"],"names":[],"mappings":"AAsBA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAc,GAAG,IAAI,CAqBpF"}