@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,122 @@
1
+ /**
2
+ * Human-readable rendering for `align build` (ADR 011) — split out of `build.ts` (which owns the
3
+ * dry-run/apply/verify pipeline itself) purely for `arch.metric:loc:cli`'s max-500-lines-per-file
4
+ * limit: this is presentation logic with no pipeline state of its own, a clean single-
5
+ * responsibility seam, not code moved just to dodge the metric.
6
+ */
7
+ import { renderViolationMessage } from '@spikedpunch/align-core';
8
+ export function renderBuildReport(result) {
9
+ const lines = [
10
+ `# align build report`,
11
+ ``,
12
+ `Doc: \`${result.docRelPath}\` (${result.docContentHash})`,
13
+ `Built: ${new Date().toISOString()}`,
14
+ ``,
15
+ `## Impact`,
16
+ ``,
17
+ `- Adds ${result.impact.addedNew.length} new violation(s)`,
18
+ `- Masks ${result.impact.maskedBaselined.length} previously-baselined violation(s)`,
19
+ ``,
20
+ `## Rules`,
21
+ ``,
22
+ ];
23
+ for (const rule of result.proposal.rules) {
24
+ const quote = rule.provenance.sourceQuote ?? '';
25
+ const range = rule.provenance.sourceLineRange;
26
+ const lineRef = range === undefined ? '' : `:${range.startLine}${range.endLine !== range.startLine ? `-${range.endLine}` : ''}`;
27
+ lines.push(`### \`${rule.id}\``);
28
+ lines.push('');
29
+ lines.push(`- Source: \`${rule.provenance.sourceFile ?? result.docRelPath}${lineRef}\``);
30
+ lines.push(`- Quote: "${quote}"`);
31
+ lines.push(`- IR: \`${JSON.stringify({ kind: rule.kind, ...ruleSelectors(rule) })}\``);
32
+ lines.push('');
33
+ }
34
+ if (result.proposal.flagged.length > 0) {
35
+ lines.push(`## Flagged (not written)`, '');
36
+ for (const f of result.proposal.flagged) {
37
+ lines.push(`- **${f.reason}** (\`${f.section}\`, ${f.sourceFile}:${f.sourceLineRange.startLine}): ${f.detail}`);
38
+ }
39
+ lines.push('');
40
+ }
41
+ if (result.diff.added.length + result.diff.changed.length + result.diff.removed.length > 0) {
42
+ lines.push(`## Diff vs. previous generated-rules.json`, '');
43
+ for (const r of result.diff.added)
44
+ lines.push(`- + added \`${r.id}\``);
45
+ for (const c of result.diff.changed)
46
+ lines.push(`- ~ changed \`${c.after.id}\``);
47
+ for (const r of result.diff.removed)
48
+ lines.push(`- - removed \`${r.id}\``);
49
+ lines.push('');
50
+ }
51
+ return `${lines.join('\n')}\n`;
52
+ }
53
+ function ruleSelectors(rule) {
54
+ switch (rule.kind) {
55
+ case 'arch.no-dependency':
56
+ return { from: rule.from, to: rule.to };
57
+ case 'arch.no-cycles':
58
+ return { scope: rule.scope, includeTypeOnly: rule.includeTypeOnly };
59
+ case 'arch.layers':
60
+ return { layers: rule.layers };
61
+ case 'custom.host':
62
+ return { hostRuleName: rule.hostRuleName };
63
+ case 'arch.metric':
64
+ return { target: rule.target, metric: rule.metric, max: rule.max };
65
+ case 'security.manifest.source-hygiene':
66
+ case 'security.manifest.new-dependency':
67
+ return {}; // no selectors — repo-wide, no ComponentRef (ADR 013)
68
+ default:
69
+ return {};
70
+ }
71
+ }
72
+ export function printDryRunReport(result) {
73
+ console.log(`align build — ${result.docRelPath}\n`);
74
+ for (const section of result.proposal.sections) {
75
+ console.log(` [${section.tier.padEnd(7)}] ${section.headingText} (${section.ruleIds.length} rule(s))`);
76
+ }
77
+ if (result.diff.added.length > 0) {
78
+ console.log(`\n + ${result.diff.added.length} added:`);
79
+ for (const r of result.diff.added)
80
+ console.log(` ${r.id} ${quoteOf(r)}`);
81
+ }
82
+ if (result.diff.changed.length > 0) {
83
+ console.log(`\n ~ ${result.diff.changed.length} changed:`);
84
+ for (const c of result.diff.changed)
85
+ console.log(` ${c.after.id} ${quoteOf(c.after)}`);
86
+ }
87
+ if (result.diff.provenanceOnlyChanged.length > 0) {
88
+ console.log(`\n ${result.diff.provenanceOnlyChanged.length} unchanged (provenance-only updates — because/source text differs, nothing structural):`);
89
+ for (const c of result.diff.provenanceOnlyChanged)
90
+ console.log(` ${c.after.id} ${quoteOf(c.after)}`);
91
+ }
92
+ if (result.diff.removed.length > 0) {
93
+ console.log(`\n - ${result.diff.removed.length} removed:`);
94
+ for (const r of result.diff.removed)
95
+ console.log(` ${r.id}`);
96
+ }
97
+ if (result.diff.added.length + result.diff.changed.length + result.diff.removed.length === 0) {
98
+ console.log(`\n no structural rule changes (empty diff)${result.diff.provenanceOnlyChanged.length > 0 ? ' — provenance-only updates above' : ''}.`);
99
+ }
100
+ if (result.proposal.flagged.length > 0) {
101
+ console.log(`\n ${result.proposal.flagged.length} flagged (never silently written):`);
102
+ for (const f of result.proposal.flagged)
103
+ console.log(` [${f.reason}] ${f.sourceFile}:${f.sourceLineRange.startLine} ${f.detail}`);
104
+ }
105
+ if (result.proposal.proseSections.length > 0) {
106
+ console.log(`\n ${result.proposal.proseSections.length} prose section(s) need judgment — use \`align_propose_rules\` (MCP) or wait for Stage 4 BYOK:`);
107
+ for (const p of result.proposal.proseSections)
108
+ console.log(` ${p.headingText} (${p.startLine}-${p.endLine})`);
109
+ }
110
+ console.log(`\n impact: adds ${result.impact.addedNew.length} new violation(s), masks ${result.impact.maskedBaselined.length} previously-baselined.`);
111
+ if (result.impact.addedNew.length > 0) {
112
+ for (const v of result.impact.addedNew.slice(0, 10))
113
+ console.log(` ${v.file}:${v.range.startLine} [${v.ruleId}] ${renderViolationMessage(v)}`);
114
+ if (result.impact.addedNew.length > 10)
115
+ console.log(` ... +${result.impact.addedNew.length - 10} more`);
116
+ }
117
+ }
118
+ function quoteOf(rule) {
119
+ const q = rule.provenance.sourceQuote;
120
+ return q === undefined ? '' : `"${q.length > 80 ? `${q.slice(0, 77)}...` : q}"`;
121
+ }
122
+ //# sourceMappingURL=build-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-report.js","sourceRoot":"","sources":["../../src/commands/build-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { type Advisory, type BuildProposal, type ImpactDelta, type RepoRelativePath, type RuleDiff, type RuleFragment, type SourceRange } from '@spikedpunch/align-core';
2
+ export declare const DEFAULT_DOC_PATH = "docs/ARCHITECTURE-RULES.md";
3
+ export interface BuildOptions {
4
+ readonly doc?: string;
5
+ readonly apply: boolean;
6
+ readonly ifChanged: boolean;
7
+ readonly verify: boolean;
8
+ readonly acceptNewIntoBaseline: boolean;
9
+ readonly nonInteractive?: boolean;
10
+ readonly telemetryPreConfig?: boolean;
11
+ }
12
+ export interface DryRunResult {
13
+ readonly docRelPath: string;
14
+ readonly docPath: RepoRelativePath;
15
+ readonly docContentHash: string;
16
+ readonly proposal: BuildProposal;
17
+ readonly diff: RuleDiff;
18
+ readonly impact: ImpactDelta;
19
+ }
20
+ /**
21
+ * The deterministic dry-run pipeline (ADR 011): parse the doc -> propose rules (precision ladder,
22
+ * tiers 1+2, zero LLM) -> `computeBuildResult`. Shared by the CLI (`runBuild`) and, indirectly, the
23
+ * MCP `align_propose_rules` tool's pass-1 discovery response (which surfaces the same
24
+ * deterministic rules for the client to pass through in pass 2).
25
+ */
26
+ export declare function dryRunBuild(rootDir: string, docRelPath: string): Promise<DryRunResult>;
27
+ export interface ClientSubmission {
28
+ readonly fragment: RuleFragment;
29
+ /** The section anchor this proposal belongs to (echoed back from pass 1's section list) —
30
+ * used only for the audit report / lockfile attribution, never for grounding (grounding is
31
+ * selector-based, `ground.ts`). */
32
+ readonly section: string;
33
+ readonly sourceLineRange: SourceRange;
34
+ readonly sourceQuote: string;
35
+ }
36
+ /**
37
+ * Assembles a `BuildProposal` from an MCP client's submitted proposals (ADR 011 two-pass
38
+ * clarification, pass 2/apply): re-parses the doc for its deterministic tier-1/2 rules (cheap,
39
+ * idempotent — gives the correct section list/hashes for the lockfile) and merges in the client's
40
+ * submissions, each grounded exactly the same way a doc-parsed fragment is (`ground.ts`) — align
41
+ * validates and grounds; the client agent supplies the judgment (no API key in align, ADR 011).
42
+ */
43
+ export declare function proposeFromClientSubmission(rootDir: string, docRelPath: string, submissions: readonly ClientSubmission[]): Promise<DryRunResult>;
44
+ export interface ApplyResult {
45
+ readonly ok: boolean;
46
+ readonly message: string;
47
+ }
48
+ /**
49
+ * Writes `.align/generated-rules.json`, `.align/rules.lock.json`, and
50
+ * `.align/last-build-report.md` (ADR 011) — the same function backs both `align build --apply`
51
+ * and the MCP `align_propose_rules` `{ apply: true }` call. New violations require explicit
52
+ * consent (`acceptNewIntoBaseline`) mirroring `align init`'s baseline-seed consent doctrine
53
+ * (ADR 006) — refuses to write otherwise.
54
+ */
55
+ export declare function writeBuildArtifacts(rootDir: string, result: DryRunResult, options: {
56
+ readonly acceptNewIntoBaseline: boolean;
57
+ }): ApplyResult;
58
+ export interface VerifyResult {
59
+ readonly ok: boolean;
60
+ readonly advisories: readonly Advisory[];
61
+ }
62
+ /**
63
+ * `--verify` / `align check --frozen-rules` (ADR 011): red iff the doc's section hashes no longer
64
+ * match the lockfile (`doc-drift`) or `.align/generated-rules.json` was hand-edited/removed since
65
+ * the last `--apply` (`divergence`, content-hashed in the lockfile). If no lockfile exists yet,
66
+ * this is a deliberate no-op (`ok: true`) — `align check --frozen-rules` shouldn't fail a repo
67
+ * that has never run `align build`; `runBuild`'s own `--verify` path treats a missing lockfile as
68
+ * an explicit failure instead, since the user asked specifically to verify build state.
69
+ */
70
+ export declare function verifyFrozenRules(rootDir: string): VerifyResult;
71
+ /** CLI entrypoint (`align build`). */
72
+ export declare function runBuild(rootDir: string, options: BuildOptions): Promise<number>;
73
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAGA,OAAO,EAYL,KAAK,QAAQ,EACb,KAAK,aAAa,EAMlB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,KAAK,YAAY,EAGjB,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAiBjC,eAAO,MAAM,gBAAgB,+BAA+B,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AAsBD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAmCD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAa5F;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC;;uCAEmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,SAAS,gBAAgB,EAAE,GACvC,OAAO,CAAC,YAAY,CAAC,CAgDvB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE;IAAE,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAA;CAAE,GACnD,WAAW,CA8Db;AAYD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC1C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA4B/D;AAED,sCAAsC;AACtC,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAwEtF"}
@@ -0,0 +1,289 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as readline from 'node:readline/promises';
4
+ import { ComponentValidationError, computeImpactDelta, diffGeneratedRules, evaluateRule, groundFragment, InMemoryBaselineStore, mergeGeneratedRules, proposeRulesFromDoc, sha256Hex, toRepoRelativePath, toRuleId, } from '@spikedpunch/align-core';
5
+ import { TypeScriptPlugin } from '@spikedpunch/align-plugin-typescript';
6
+ import { loadConfig, CONFIG_FILENAME } from '../config.js';
7
+ import { writeGeneratedRulesNote } from '../init/config-comment.js';
8
+ import { printDryRunReport, renderBuildReport } from './build-report.js';
9
+ import { readBaseline, readGeneratedRules, readGeneratedRulesRaw, readRulesLock, writeBaseline, writeGeneratedRules, writeLastBuildReport, writeRulesLock, } from '../align-dir.js';
10
+ import { computeRulesetIrHash, createTelemetryRecorder } from '../telemetry/index.js';
11
+ export const DEFAULT_DOC_PATH = 'docs/ARCHITECTURE-RULES.md';
12
+ /** `build` telemetry (IMPLEMENTATION_PLAN.md's telemetry spec): recorded once per successful
13
+ * `dryRunBuild`/`proposeFromClientSubmission` — dry-run and `--apply` both compute the same
14
+ * `DryRunResult`, so one call covers both; `--verify` and an `--if-changed` no-op never reach a
15
+ * `DryRunResult` at all and so never emit (nothing was actually built/diffed to report). */
16
+ async function recordBuildTelemetry(rootDir, docRelPath, result, telemetryPreConfig) {
17
+ const { ruleset, telemetry } = await loadConfig(rootDir);
18
+ const recorder = createTelemetryRecorder(rootDir, 'build', telemetryPreConfig, telemetry);
19
+ if (!recorder.enabled)
20
+ return;
21
+ recorder.record({
22
+ kind: 'build',
23
+ doc: docRelPath,
24
+ structuralChanges: result.diff.added.length + result.diff.changed.length + result.diff.removed.length,
25
+ provenanceOnlyChanges: result.diff.provenanceOnlyChanged.length,
26
+ impactDelta: { newViolations: result.impact.addedNew.length, maskedBaselined: result.impact.maskedBaselined.length },
27
+ }, { rulesetIrHash: computeRulesetIrHash(ruleset) });
28
+ }
29
+ /**
30
+ * The shared back half of the build pipeline (ADR 011): given a fully-formed `BuildProposal` —
31
+ * either derived from parsing the doc (`dryRunBuild`) or assembled from an MCP client's submitted
32
+ * proposals (`proposeFromClientSubmission`) — diffs it against what's currently written and
33
+ * compiles both the current and proposed effective rulesets in memory to compute the impact delta.
34
+ * One scan, two `evaluateRule` passes (pure) — avoids a second filesystem rescan just to compare
35
+ * two rulesets against the same code. Writes nothing.
36
+ */
37
+ async function computeBuildResult(rootDir, docRelPath, docContentHash, proposal, baseRuleset, excludes, hostRules) {
38
+ const existingGenerated = readGeneratedRules(rootDir)?.rules ?? [];
39
+ const diff = diffGeneratedRules(existingGenerated, proposal.rules);
40
+ const currentEffectiveRules = mergeGeneratedRules(baseRuleset.rules, existingGenerated);
41
+ const proposedEffectiveRules = mergeGeneratedRules(baseRuleset.rules, proposal.rules);
42
+ const plugin = new TypeScriptPlugin();
43
+ const graph = await plugin.scanner.scan({ rootDir, components: baseRuleset.components, excludes });
44
+ const currentViolations = currentEffectiveRules.flatMap((r) => evaluateRule(r, graph, baseRuleset.components, hostRules));
45
+ const proposedViolations = proposedEffectiveRules.flatMap((r) => evaluateRule(r, graph, baseRuleset.components, hostRules));
46
+ const impact = computeImpactDelta(currentViolations, proposedViolations, readBaseline(rootDir));
47
+ return { docRelPath, docPath: toRepoRelativePath(docRelPath), docContentHash, proposal, diff, impact };
48
+ }
49
+ /**
50
+ * The deterministic dry-run pipeline (ADR 011): parse the doc -> propose rules (precision ladder,
51
+ * tiers 1+2, zero LLM) -> `computeBuildResult`. Shared by the CLI (`runBuild`) and, indirectly, the
52
+ * MCP `align_propose_rules` tool's pass-1 discovery response (which surfaces the same
53
+ * deterministic rules for the client to pass through in pass 2).
54
+ */
55
+ export async function dryRunBuild(rootDir, docRelPath) {
56
+ const absDocPath = path.join(rootDir, docRelPath);
57
+ if (!fs.existsSync(absDocPath)) {
58
+ throw new Error(`Doc not found: ${docRelPath}`);
59
+ }
60
+ const docText = fs.readFileSync(absDocPath, 'utf8');
61
+ const docPath = toRepoRelativePath(docRelPath);
62
+ const docContentHash = sha256Hex(docText);
63
+ const { ruleset: baseRuleset, excludes, hostRules } = await loadConfig(rootDir, { includeGenerated: false });
64
+ const proposal = proposeRulesFromDoc(docText, docPath, baseRuleset.components, new Set(hostRules.keys()));
65
+ return computeBuildResult(rootDir, docRelPath, docContentHash, proposal, baseRuleset, excludes, hostRules);
66
+ }
67
+ /**
68
+ * Assembles a `BuildProposal` from an MCP client's submitted proposals (ADR 011 two-pass
69
+ * clarification, pass 2/apply): re-parses the doc for its deterministic tier-1/2 rules (cheap,
70
+ * idempotent — gives the correct section list/hashes for the lockfile) and merges in the client's
71
+ * submissions, each grounded exactly the same way a doc-parsed fragment is (`ground.ts`) — align
72
+ * validates and grounds; the client agent supplies the judgment (no API key in align, ADR 011).
73
+ */
74
+ export async function proposeFromClientSubmission(rootDir, docRelPath, submissions) {
75
+ const absDocPath = path.join(rootDir, docRelPath);
76
+ if (!fs.existsSync(absDocPath)) {
77
+ throw new Error(`Doc not found: ${docRelPath}`);
78
+ }
79
+ const docText = fs.readFileSync(absDocPath, 'utf8');
80
+ const docPath = toRepoRelativePath(docRelPath);
81
+ const docContentHash = sha256Hex(docText);
82
+ const { ruleset: baseRuleset, excludes, hostRules } = await loadConfig(rootDir, { includeGenerated: false });
83
+ const registeredHostPredicates = new Set(hostRules.keys());
84
+ const base = proposeRulesFromDoc(docText, docPath, baseRuleset.components, registeredHostPredicates);
85
+ const flagged = [...base.flagged];
86
+ const ruleIdsBySection = new Map(base.sections.map((s) => [s.anchor, [...s.ruleIds]]));
87
+ const byId = new Map(base.rules.map((r) => [r.id, r]));
88
+ for (const sub of submissions) {
89
+ const result = groundFragment(sub.fragment, sub.section, docPath, sub.sourceLineRange, sub.sourceQuote, baseRuleset.components, registeredHostPredicates);
90
+ if (!result.ok) {
91
+ flagged.push(result.flagged);
92
+ continue;
93
+ }
94
+ byId.set(result.rule.id, result.rule); // client submission wins on id collision with a tier-1/2 rule
95
+ const list = ruleIdsBySection.get(sub.section);
96
+ if (list === undefined)
97
+ ruleIdsBySection.set(sub.section, [result.rule.id]);
98
+ else
99
+ list.push(result.rule.id);
100
+ }
101
+ const proposal = {
102
+ sections: base.sections.map((s) => ({
103
+ ...s,
104
+ ruleIds: [...new Set(ruleIdsBySection.get(s.anchor) ?? [])].map((id) => toRuleId(id)),
105
+ })),
106
+ rules: [...byId.values()],
107
+ flagged,
108
+ proseSections: base.proseSections,
109
+ };
110
+ return computeBuildResult(rootDir, docRelPath, docContentHash, proposal, baseRuleset, excludes, hostRules);
111
+ }
112
+ /**
113
+ * Writes `.align/generated-rules.json`, `.align/rules.lock.json`, and
114
+ * `.align/last-build-report.md` (ADR 011) — the same function backs both `align build --apply`
115
+ * and the MCP `align_propose_rules` `{ apply: true }` call. New violations require explicit
116
+ * consent (`acceptNewIntoBaseline`) mirroring `align init`'s baseline-seed consent doctrine
117
+ * (ADR 006) — refuses to write otherwise.
118
+ */
119
+ export function writeBuildArtifacts(rootDir, result, options) {
120
+ if (result.impact.addedNew.length > 0 && !options.acceptNewIntoBaseline) {
121
+ return {
122
+ ok: false,
123
+ message: `The proposed ruleset adds ${result.impact.addedNew.length} new violation(s). Re-run with ` +
124
+ `--accept-new-into-baseline to seed them as tolerated debt (silence is never consent, ADR 006), ` +
125
+ `or address them in the doc/code first.`,
126
+ };
127
+ }
128
+ // Only groundable rules are ever written — `proposal.rules` already excludes everything in
129
+ // `proposal.flagged` (ADR 011: ungroundable -> flagged, never silently written).
130
+ const generatedFile = {
131
+ irVersion: '1',
132
+ docPath: result.docRelPath,
133
+ generatedAt: Date.now(),
134
+ rules: [...result.proposal.rules],
135
+ };
136
+ const rawWritten = writeGeneratedRules(rootDir, generatedFile);
137
+ const generatedRulesContentHash = sha256Hex(rawWritten);
138
+ writeGeneratedRulesNote(path.join(rootDir, CONFIG_FILENAME));
139
+ if (options.acceptNewIntoBaseline && result.impact.addedNew.length > 0) {
140
+ const store = new InMemoryBaselineStore(readBaseline(rootDir));
141
+ store.accept(result.impact.addedNew, 'manual');
142
+ writeBaseline(rootDir, store.snapshot());
143
+ }
144
+ const lock = {
145
+ irVersion: '1',
146
+ docPath: result.docRelPath,
147
+ docContentHash: result.docContentHash,
148
+ builtAt: Date.now(),
149
+ sections: result.proposal.sections.map((s) => ({
150
+ anchor: s.anchor,
151
+ headingText: s.headingText,
152
+ startLine: s.startLine,
153
+ endLine: s.endLine,
154
+ contentHash: s.contentHash,
155
+ tier: s.tier,
156
+ ruleIds: [...s.ruleIds],
157
+ })),
158
+ generatedRulesContentHash,
159
+ };
160
+ writeRulesLock(rootDir, lock);
161
+ writeLastBuildReport(rootDir, renderBuildReport(result));
162
+ const flaggedNote = result.proposal.flagged.length > 0 ? ` ${result.proposal.flagged.length} flagged (not written) — see the report.` : '';
163
+ const baselineNote = options.acceptNewIntoBaseline && result.impact.addedNew.length > 0
164
+ ? ` Seeded ${result.impact.addedNew.length} new violation(s) into the baseline.`
165
+ : '';
166
+ return {
167
+ ok: true,
168
+ message: `Wrote .align/generated-rules.json (${result.proposal.rules.length} rule(s)), .align/rules.lock.json, ` +
169
+ `and .align/last-build-report.md. Diff: ${result.diff.added.length} added, ${result.diff.changed.length} changed, ` +
170
+ `${result.diff.removed.length} removed, ${result.diff.unchanged.length} unchanged${provenanceOnlyNote(result.diff)}.` +
171
+ `${flaggedNote}${baselineNote}`,
172
+ };
173
+ }
174
+ /** Provenance-only changes (a `.because()`/source-quote edit with no structural difference) are
175
+ * reported separately from `unchanged`/`changed` — see `build/diff.ts`'s `RuleDiff.
176
+ * provenanceOnlyChanged` doc comment for the live-session bug this fixes (agent-attached rationale
177
+ * text made 10 byte-identical rules show up as "changed"). Renders nothing when there are none, so
178
+ * the common case (no provenance churn) doesn't add noise to every build's output. */
179
+ function provenanceOnlyNote(diff) {
180
+ if (diff.provenanceOnlyChanged.length === 0)
181
+ return '';
182
+ return `, ${diff.provenanceOnlyChanged.length} unchanged (provenance-only updates)`;
183
+ }
184
+ /**
185
+ * `--verify` / `align check --frozen-rules` (ADR 011): red iff the doc's section hashes no longer
186
+ * match the lockfile (`doc-drift`) or `.align/generated-rules.json` was hand-edited/removed since
187
+ * the last `--apply` (`divergence`, content-hashed in the lockfile). If no lockfile exists yet,
188
+ * this is a deliberate no-op (`ok: true`) — `align check --frozen-rules` shouldn't fail a repo
189
+ * that has never run `align build`; `runBuild`'s own `--verify` path treats a missing lockfile as
190
+ * an explicit failure instead, since the user asked specifically to verify build state.
191
+ */
192
+ export function verifyFrozenRules(rootDir) {
193
+ const lock = readRulesLock(rootDir);
194
+ if (lock === undefined)
195
+ return { ok: true, advisories: [] };
196
+ const advisories = [];
197
+ const absDocPath = path.join(rootDir, lock.docPath);
198
+ if (!fs.existsSync(absDocPath)) {
199
+ advisories.push({ kind: 'doc-drift', message: `${lock.docPath} (referenced by rules.lock.json) no longer exists.` });
200
+ }
201
+ else {
202
+ const docContentHash = sha256Hex(fs.readFileSync(absDocPath, 'utf8'));
203
+ if (docContentHash !== lock.docContentHash) {
204
+ advisories.push({
205
+ kind: 'doc-drift',
206
+ message: `${lock.docPath} has changed since the last \`align build --apply\` — run it again to refresh generated-rules.json.`,
207
+ });
208
+ }
209
+ }
210
+ const generatedRaw = readGeneratedRulesRaw(rootDir);
211
+ const generatedHash = generatedRaw === undefined ? undefined : sha256Hex(generatedRaw);
212
+ if (generatedHash !== lock.generatedRulesContentHash) {
213
+ advisories.push({
214
+ kind: 'divergence',
215
+ message: `.align/generated-rules.json does not match rules.lock.json — it was hand-edited or removed after the last \`align build --apply\`.`,
216
+ });
217
+ }
218
+ return { ok: advisories.length === 0, advisories };
219
+ }
220
+ /** CLI entrypoint (`align build`). */
221
+ export async function runBuild(rootDir, options) {
222
+ const docRelPath = options.doc ?? DEFAULT_DOC_PATH;
223
+ if (options.verify) {
224
+ const lock = readRulesLock(rootDir);
225
+ if (lock === undefined) {
226
+ console.log('No .align/rules.lock.json — run `align build --apply` first.');
227
+ return 1;
228
+ }
229
+ const result = verifyFrozenRules(rootDir);
230
+ if (result.ok) {
231
+ console.log('align build --verify: OK — doc and generated-rules.json match the lockfile.');
232
+ return 0;
233
+ }
234
+ for (const a of result.advisories)
235
+ console.log(` ${a.kind}: ${a.message}`);
236
+ return 1;
237
+ }
238
+ const absDocPath = path.join(rootDir, docRelPath);
239
+ if (!fs.existsSync(absDocPath)) {
240
+ console.error(`Doc not found: ${docRelPath}`);
241
+ return 1;
242
+ }
243
+ if (options.ifChanged) {
244
+ const lock = readRulesLock(rootDir);
245
+ if (lock !== undefined) {
246
+ const docContentHash = sha256Hex(fs.readFileSync(absDocPath, 'utf8'));
247
+ if (docContentHash === lock.docContentHash) {
248
+ console.log(`${docRelPath}: unchanged since the last build — nothing to do.`);
249
+ return 0;
250
+ }
251
+ }
252
+ }
253
+ // R3 (greenfield mode): `dryRunBuild` scans the same path `align check` does, so a
254
+ // zero-`empty:'fail'`-component throws the same `ComponentValidationError` — caught here the
255
+ // same way `orchestrator.ts` catches it, instead of a raw Node stack trace
256
+ // (GREENFIELD_TRIAD_REPORT.md §3). `'until-populated'`/`'allow'` components never throw at all.
257
+ let result;
258
+ try {
259
+ result = await dryRunBuild(rootDir, docRelPath);
260
+ }
261
+ catch (err) {
262
+ if (err instanceof ComponentValidationError) {
263
+ console.error(`align build: ${err.message}`);
264
+ return 1;
265
+ }
266
+ throw err;
267
+ }
268
+ printDryRunReport(result);
269
+ await recordBuildTelemetry(rootDir, docRelPath, result, options.telemetryPreConfig);
270
+ if (!options.apply) {
271
+ console.log('\nDry run only — nothing written. Re-run with --apply to write generated-rules.json.');
272
+ return 0;
273
+ }
274
+ let acceptNewIntoBaseline = options.acceptNewIntoBaseline;
275
+ if (result.impact.addedNew.length > 0 && !acceptNewIntoBaseline) {
276
+ const isInteractive = options.nonInteractive === true ? false : (options.nonInteractive ?? process.stdin.isTTY === true);
277
+ if (isInteractive) {
278
+ console.log(`\nThe proposed ruleset adds ${result.impact.addedNew.length} new violation(s).`);
279
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
280
+ const answer = await rl.question('Seed these into the baseline as tolerated debt and apply? [y/N] ');
281
+ rl.close();
282
+ acceptNewIntoBaseline = /^y(es)?$/i.test(answer.trim());
283
+ }
284
+ }
285
+ const applied = writeBuildArtifacts(rootDir, result, { acceptNewIntoBaseline });
286
+ console.log(`\n${applied.message}`);
287
+ return applied.ok ? 0 : 1;
288
+ }
289
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export interface CheckOptions {
2
+ readonly json: boolean;
3
+ /** `align check --frozen-rules` (ADR 011): also red if a doc-built ruleset has drifted from its
4
+ * lockfile (doc edited but not rebuilt) or `.align/generated-rules.json` was hand-edited since
5
+ * the last `align build --apply`. A no-op when `align build` has never run. Mutually exclusive
6
+ * with `untrusted` — frozen-rules verification is a trusted-mode, live-filesystem concern. */
7
+ readonly frozenRules?: boolean;
8
+ /** `align check --untrusted` (alias `--ir-only`, ADR 014): never imports align.config.ts, never
9
+ * invokes any repo-controlled code (no hostRules predicates either — see
10
+ * `assertNoCustomHostRules`). Loads the ruleset from a committed JSON artifact only
11
+ * (`.align/ruleset-ir.json` by default, `ir` below to override), written ahead of time by
12
+ * `align export-ir` in a trusted context. Refuses — never silently falls back to executing the
13
+ * config — when that artifact is missing or contains a `custom.host` rule. */
14
+ readonly untrusted?: boolean;
15
+ /** Overrides the default `.align/ruleset-ir.json` location `--untrusted` reads from. */
16
+ readonly ir?: string;
17
+ /** The CLI-flag/env half of the telemetry enable precedence, already resolved by `program.ts`
18
+ * (`resolveTelemetryPreConfig`) — `undefined` means "flags/env didn't decide, defer to
19
+ * `align.config.ts`'s `telemetry` export" (never read under `--untrusted`, ADR 014). */
20
+ readonly telemetryPreConfig?: boolean;
21
+ }
22
+ /**
23
+ * `align check` — FRESH scan every run (ADR 005: rescan-on-check, no caching of any kind).
24
+ * Exit 0 only on a fully green verdict (and, with `--frozen-rules`, no doc/generated-rules
25
+ * drift); 1 on red or error (ADR 008: error is environmental and halts/escalates, but from a
26
+ * shell's perspective both are "not safe to proceed"); 1 on a `--untrusted` refuse (missing IR
27
+ * artifact, custom.host present) — refusal is also "not safe to proceed", just before a scan ever
28
+ * starts.
29
+ */
30
+ export declare function runCheck(rootDir: string, options: CheckOptions): Promise<number>;
31
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB;;;kGAG8F;IAC9F,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;kFAK8E;IAC9E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,wFAAwF;IACxF,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB;;4FAEwF;IACxF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAYtF"}