@spikedpunch/align-core 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 +27 -0
- package/dist/baseline/fingerprint.d.ts +19 -0
- package/dist/baseline/fingerprint.d.ts.map +1 -0
- package/dist/baseline/fingerprint.js +0 -0
- package/dist/baseline/fingerprint.js.map +1 -0
- package/dist/baseline/store.d.ts +81 -0
- package/dist/baseline/store.d.ts.map +1 -0
- package/dist/baseline/store.js +111 -0
- package/dist/baseline/store.js.map +1 -0
- package/dist/build/diff.d.ts +22 -0
- package/dist/build/diff.d.ts.map +1 -0
- package/dist/build/diff.js +61 -0
- package/dist/build/diff.js.map +1 -0
- package/dist/build/export-ir.d.ts +11 -0
- package/dist/build/export-ir.d.ts.map +1 -0
- package/dist/build/export-ir.js +4 -0
- package/dist/build/export-ir.js.map +1 -0
- package/dist/build/ground.d.ts +32 -0
- package/dist/build/ground.d.ts.map +1 -0
- package/dist/build/ground.js +162 -0
- package/dist/build/ground.js.map +1 -0
- package/dist/build/hash.d.ts +10 -0
- package/dist/build/hash.d.ts.map +1 -0
- package/dist/build/hash.js +13 -0
- package/dist/build/hash.js.map +1 -0
- package/dist/build/impact.d.ts +20 -0
- package/dist/build/impact.d.ts.map +1 -0
- package/dist/build/impact.js +15 -0
- package/dist/build/impact.js.map +1 -0
- package/dist/build/index.d.ts +14 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +14 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/merge.d.ts +27 -0
- package/dist/build/merge.d.ts.map +1 -0
- package/dist/build/merge.js +85 -0
- package/dist/build/merge.js.map +1 -0
- package/dist/build/propose.d.ts +16 -0
- package/dist/build/propose.d.ts.map +1 -0
- package/dist/build/propose.js +126 -0
- package/dist/build/propose.js.map +1 -0
- package/dist/build/provenance.d.ts +19 -0
- package/dist/build/provenance.d.ts.map +1 -0
- package/dist/build/provenance.js +23 -0
- package/dist/build/provenance.js.map +1 -0
- package/dist/build/schema.d.ts +1825 -0
- package/dist/build/schema.d.ts.map +1 -0
- package/dist/build/schema.js +128 -0
- package/dist/build/schema.js.map +1 -0
- package/dist/build/sections.d.ts +30 -0
- package/dist/build/sections.d.ts.map +1 -0
- package/dist/build/sections.js +58 -0
- package/dist/build/sections.js.map +1 -0
- package/dist/build/tier1.d.ts +24 -0
- package/dist/build/tier1.d.ts.map +1 -0
- package/dist/build/tier1.js +68 -0
- package/dist/build/tier1.js.map +1 -0
- package/dist/build/tier2.d.ts +42 -0
- package/dist/build/tier2.d.ts.map +1 -0
- package/dist/build/tier2.js +187 -0
- package/dist/build/tier2.js.map +1 -0
- package/dist/build/types.d.ts +42 -0
- package/dist/build/types.d.ts.map +1 -0
- package/dist/build/types.js +2 -0
- package/dist/build/types.js.map +1 -0
- package/dist/components/glob.d.ts +10 -0
- package/dist/components/glob.d.ts.map +1 -0
- package/dist/components/glob.js +52 -0
- package/dist/components/glob.js.map +1 -0
- package/dist/components/registry.d.ts +51 -0
- package/dist/components/registry.d.ts.map +1 -0
- package/dist/components/registry.js +121 -0
- package/dist/components/registry.js.map +1 -0
- package/dist/dsl/factories.d.ts +86 -0
- package/dist/dsl/factories.d.ts.map +1 -0
- package/dist/dsl/factories.js +145 -0
- package/dist/dsl/factories.js.map +1 -0
- package/dist/dsl/index.d.ts +46 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +67 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl/reserved-names.typecheck.d.ts +2 -0
- package/dist/dsl/reserved-names.typecheck.d.ts.map +1 -0
- package/dist/dsl/reserved-names.typecheck.js +16 -0
- package/dist/dsl/reserved-names.typecheck.js.map +1 -0
- package/dist/dsl/verb-manifest.d.ts +12 -0
- package/dist/dsl/verb-manifest.d.ts.map +1 -0
- package/dist/dsl/verb-manifest.js +101 -0
- package/dist/dsl/verb-manifest.js.map +1 -0
- package/dist/fix/apply.d.ts +67 -0
- package/dist/fix/apply.d.ts.map +1 -0
- package/dist/fix/apply.js +163 -0
- package/dist/fix/apply.js.map +1 -0
- package/dist/fix/index.d.ts +3 -0
- package/dist/fix/index.d.ts.map +1 -0
- package/dist/fix/index.js +3 -0
- package/dist/fix/index.js.map +1 -0
- package/dist/fix/schema.d.ts +180 -0
- package/dist/fix/schema.d.ts.map +1 -0
- package/dist/fix/schema.js +41 -0
- package/dist/fix/schema.js.map +1 -0
- package/dist/gates/advisories.d.ts +11 -0
- package/dist/gates/advisories.d.ts.map +1 -0
- package/dist/gates/advisories.js +27 -0
- package/dist/gates/advisories.js.map +1 -0
- package/dist/gates/types.d.ts +36 -0
- package/dist/gates/types.d.ts.map +1 -0
- package/dist/gates/types.js +8 -0
- package/dist/gates/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +51 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +304 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/payload/builder.d.ts +49 -0
- package/dist/payload/builder.d.ts.map +1 -0
- package/dist/payload/builder.js +61 -0
- package/dist/payload/builder.js.map +1 -0
- package/dist/payload/mermaid.d.ts +22 -0
- package/dist/payload/mermaid.d.ts.map +1 -0
- package/dist/payload/mermaid.js +89 -0
- package/dist/payload/mermaid.js.map +1 -0
- package/dist/plugin/registry.d.ts +24 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/registry.js +24 -0
- package/dist/plugin/registry.js.map +1 -0
- package/dist/rules/component-refs.d.ts +26 -0
- package/dist/rules/component-refs.d.ts.map +1 -0
- package/dist/rules/component-refs.js +81 -0
- package/dist/rules/component-refs.js.map +1 -0
- package/dist/rules/evaluators.d.ts +50 -0
- package/dist/rules/evaluators.d.ts.map +1 -0
- package/dist/rules/evaluators.js +236 -0
- package/dist/rules/evaluators.js.map +1 -0
- package/dist/rules/host-rules.d.ts +109 -0
- package/dist/rules/host-rules.d.ts.map +1 -0
- package/dist/rules/host-rules.js +152 -0
- package/dist/rules/host-rules.js.map +1 -0
- package/dist/rules/index.d.ts +7 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +7 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/manifest-evaluators.d.ts +32 -0
- package/dist/rules/manifest-evaluators.d.ts.map +1 -0
- package/dist/rules/manifest-evaluators.js +124 -0
- package/dist/rules/manifest-evaluators.js.map +1 -0
- package/dist/rules/rule-category.d.ts +13 -0
- package/dist/rules/rule-category.d.ts.map +1 -0
- package/dist/rules/rule-category.js +27 -0
- package/dist/rules/rule-category.js.map +1 -0
- package/dist/rules/tarjan.d.ts +9 -0
- package/dist/rules/tarjan.d.ts.map +1 -0
- package/dist/rules/tarjan.js +102 -0
- package/dist/rules/tarjan.js.map +1 -0
- package/dist/scanner.d.ts +12 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +2 -0
- package/dist/scanner.js.map +1 -0
- package/dist/telemetry/diff.d.ts +27 -0
- package/dist/telemetry/diff.d.ts.map +1 -0
- package/dist/telemetry/diff.js +54 -0
- package/dist/telemetry/diff.js.map +1 -0
- package/dist/telemetry/index.d.ts +4 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +4 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/serialize.d.ts +10 -0
- package/dist/telemetry/serialize.d.ts.map +1 -0
- package/dist/telemetry/serialize.js +11 -0
- package/dist/telemetry/serialize.js.map +1 -0
- package/dist/telemetry/types.d.ts +138 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +3 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/types/branded.d.ts +26 -0
- package/dist/types/branded.d.ts.map +1 -0
- package/dist/types/branded.js +24 -0
- package/dist/types/branded.js.map +1 -0
- package/dist/types/graph.d.ts +46 -0
- package/dist/types/graph.d.ts.map +1 -0
- package/dist/types/graph.js +2 -0
- package/dist/types/graph.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/ir.d.ts +1747 -0
- package/dist/types/ir.d.ts.map +1 -0
- package/dist/types/ir.js +120 -0
- package/dist/types/ir.js.map +1 -0
- package/dist/types/manifest.d.ts +58 -0
- package/dist/types/manifest.d.ts.map +1 -0
- package/dist/types/manifest.js +2 -0
- package/dist/types/manifest.js.map +1 -0
- package/dist/types/violation.d.ts +94 -0
- package/dist/types/violation.d.ts.map +1 -0
- package/dist/types/violation.js +56 -0
- package/dist/types/violation.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edit-block apply pipeline — schema half (ADR 010).
|
|
3
|
+
*
|
|
4
|
+
* `FixProposal` is the zod-validated shape an LLM `FixProvider` (Stage 4, `@spikedpunch/align-agent`) must
|
|
5
|
+
* emit: search/replace edit blocks, never full files, never line-number diffs. This module has
|
|
6
|
+
* zero LLM-client dependencies — it is just a zod IR, validated the same way any other IR in
|
|
7
|
+
* `@spikedpunch/align-core` is validated (parse-don't-validate, CODING_BEST_PRACTICES.md §12). The engine
|
|
8
|
+
* that applies a validated `FixProposal` lives in `./apply.js`.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
export const editBlockSchema = z.object({
|
|
12
|
+
/** Exact, continuous block present in the file — literal character-for-character match. */
|
|
13
|
+
search: z.string().min(1, 'search must be non-empty'),
|
|
14
|
+
/** Replacement text. Empty string means deletion. */
|
|
15
|
+
replace: z.string(),
|
|
16
|
+
/** Disambiguation hint for the engine only — never injected into file content. */
|
|
17
|
+
nearLine: z.number().int().positive().optional(),
|
|
18
|
+
/** Violation ids this edit addresses (VERIFY attribution / REPAIR context). */
|
|
19
|
+
forViolations: z.array(z.string()).optional(),
|
|
20
|
+
});
|
|
21
|
+
export const fixProposalFileSchema = z.object({
|
|
22
|
+
path: z.string().min(1),
|
|
23
|
+
edits: z.array(editBlockSchema).min(1),
|
|
24
|
+
});
|
|
25
|
+
export const suppressionSchema = z.object({
|
|
26
|
+
ruleId: z.string().min(1),
|
|
27
|
+
file: z.string().min(1),
|
|
28
|
+
line: z.number().int().positive(),
|
|
29
|
+
});
|
|
30
|
+
export const fixProposalSchema = z.object({
|
|
31
|
+
files: z.array(fixProposalFileSchema).min(1),
|
|
32
|
+
/**
|
|
33
|
+
* Accepted and validated per ADR 010, but dormant in arch-first v1: no lint gates exist yet,
|
|
34
|
+
* so no rule category is suppressible. Any proposal that *uses* this field is rejected by the
|
|
35
|
+
* apply pipeline with "no suppressible rule categories active" — see `apply.ts`.
|
|
36
|
+
*/
|
|
37
|
+
suppressions: z.array(suppressionSchema).optional(),
|
|
38
|
+
/** Short rationale — becomes the git commit body. */
|
|
39
|
+
rationale: z.string().min(1),
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/fix/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,2FAA2F;IAC3F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,0BAA0B,CAAC;IACrD,qDAAqD;IACrD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,kFAAkF;IAClF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAChD,+EAA+E;IAC/E,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACvC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C;;;;OAIG;IACH,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE;IACnD,qDAAqD;IACrD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7B,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UncertaintyMarker } from '../types/graph.js';
|
|
2
|
+
import type { Advisory } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Groups uncertainty markers by reason (ADR 004's uncertainty vocabulary) into one advisory per
|
|
5
|
+
* reason, each naming its own affected-file count (Stage 2 polish over a single blended count): a
|
|
6
|
+
* lone "N specifiers could not be resolved" told an agent something was uncertain without saying
|
|
7
|
+
* whether it's an asset import (expected, ignorable) or an unresolvable specifier (worth
|
|
8
|
+
* investigating) — those are very different signals bundled into noise.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildUncertaintyAdvisories(uncertain: readonly UncertaintyMarker[]): Advisory[];
|
|
11
|
+
//# sourceMappingURL=advisories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advisories.d.ts","sourceRoot":"","sources":["../../src/gates/advisories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAqB,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,GAAG,QAAQ,EAAE,CAkB9F"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Groups uncertainty markers by reason (ADR 004's uncertainty vocabulary) into one advisory per
|
|
3
|
+
* reason, each naming its own affected-file count (Stage 2 polish over a single blended count): a
|
|
4
|
+
* lone "N specifiers could not be resolved" told an agent something was uncertain without saying
|
|
5
|
+
* whether it's an asset import (expected, ignorable) or an unresolvable specifier (worth
|
|
6
|
+
* investigating) — those are very different signals bundled into noise.
|
|
7
|
+
*/
|
|
8
|
+
export function buildUncertaintyAdvisories(uncertain) {
|
|
9
|
+
if (uncertain.length === 0)
|
|
10
|
+
return [];
|
|
11
|
+
const byReason = new Map();
|
|
12
|
+
for (const marker of uncertain) {
|
|
13
|
+
const list = byReason.get(marker.reason);
|
|
14
|
+
if (list === undefined)
|
|
15
|
+
byReason.set(marker.reason, [marker]);
|
|
16
|
+
else
|
|
17
|
+
list.push(marker);
|
|
18
|
+
}
|
|
19
|
+
return [...byReason.entries()]
|
|
20
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
21
|
+
.map(([reason, markers]) => ({
|
|
22
|
+
kind: 'uncertainty',
|
|
23
|
+
message: `${markers.length} specifier(s) across ${new Set(markers.map((m) => m.file)).size} file(s) ` +
|
|
24
|
+
`could not be resolved with certainty and were excluded from the graph — reason: ${reason}.`,
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=advisories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advisories.js","sourceRoot":"","sources":["../../src/gates/advisories.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CAAC,SAAuC;IAChF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0C,CAAC;IACnE,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,SAAS;YAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;;YACzD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;SAC3B,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EACL,GAAG,OAAO,CAAC,MAAM,wBAAwB,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,WAAW;YAC5F,mFAAmF,MAAM,GAAG;KAC/F,CAAC,CAAC,CAAC;AACR,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { RuleId } from '../types/branded.js';
|
|
2
|
+
import type { UngroundedComponent } from '../components/registry.js';
|
|
3
|
+
import { type Violation } from '../types/violation.js';
|
|
4
|
+
export type GateStatus = 'green' | 'red' | 'error' | 'skipped';
|
|
5
|
+
export declare const GATE_KINDS: readonly ["parse", "architecture", "security", "types", "lint", "format"];
|
|
6
|
+
export type GateKind = (typeof GATE_KINDS)[number];
|
|
7
|
+
export interface GateResult {
|
|
8
|
+
readonly gate: GateKind;
|
|
9
|
+
readonly status: GateStatus;
|
|
10
|
+
readonly violations: readonly Violation[];
|
|
11
|
+
readonly baselinedCount: number;
|
|
12
|
+
readonly passCount?: number;
|
|
13
|
+
readonly errorMessage?: string;
|
|
14
|
+
readonly durationMs: number;
|
|
15
|
+
readonly cacheHits: number;
|
|
16
|
+
readonly dependsOn: readonly (GateResult['gate'])[];
|
|
17
|
+
}
|
|
18
|
+
export interface Advisory {
|
|
19
|
+
readonly kind: string;
|
|
20
|
+
readonly message: string;
|
|
21
|
+
readonly ruleIds?: readonly RuleId[];
|
|
22
|
+
}
|
|
23
|
+
export interface CheckRun {
|
|
24
|
+
readonly verdict: 'green' | 'red' | 'error';
|
|
25
|
+
readonly gates: readonly GateResult[];
|
|
26
|
+
readonly advisories: readonly Advisory[];
|
|
27
|
+
readonly scannedAt: number;
|
|
28
|
+
/** R1 (greenfield mode, IMPLEMENTATION_PLAN.md Design Reserve "Greenfield mode"): every
|
|
29
|
+
* component that is green ONLY because it matched zero files this scan (`empty: 'allow'` or
|
|
30
|
+
* `'until-populated'`) — surfaced here (not just `align explain`/`doctor`) so a check-agent's own
|
|
31
|
+
* loop sees "green because compliant" and "green because empty" as distinguishable states.
|
|
32
|
+
* Always `[]` when the architecture gate didn't fully evaluate (parse/guard-step `error`) — there
|
|
33
|
+
* is no trustworthy classification to report yet. */
|
|
34
|
+
readonly ungroundedComponents: readonly UngroundedComponent[];
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gates/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAO/D,eAAO,MAAM,UAAU,2EAAoC,CAAC;AAC5D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;yDAKqD;IACrD,QAAQ,CAAC,oBAAoB,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC/D"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CATEGORIES } from '../types/violation.js';
|
|
2
|
+
// Derived from CATEGORIES (types/violation.ts), same single-source-of-truth discipline — 'parse'
|
|
3
|
+
// is the one gate kind that isn't a Category (it has no rule kinds of its own; a parse failure
|
|
4
|
+
// halts every downstream gate, ADR 008). `align skill`'s generated gate-list section reads this
|
|
5
|
+
// array directly (packages/cli/src/skill/gates.ts) so it cannot silently drift from GateResult's
|
|
6
|
+
// own shape.
|
|
7
|
+
export const GATE_KINDS = ['parse', ...CATEGORIES];
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/gates/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAkB,MAAM,uBAAuB,CAAC;AAInE,iGAAiG;AACjG,+FAA+F;AAC/F,gGAAgG;AAChG,iGAAiG;AACjG,aAAa;AACb,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,CAAU,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './types/index.js';
|
|
2
|
+
export * from './scanner.js';
|
|
3
|
+
export * from './rules/index.js';
|
|
4
|
+
export * from './components/registry.js';
|
|
5
|
+
export * from './components/glob.js';
|
|
6
|
+
export * from './gates/types.js';
|
|
7
|
+
export * from './gates/advisories.js';
|
|
8
|
+
export * from './baseline/store.js';
|
|
9
|
+
export * from './baseline/fingerprint.js';
|
|
10
|
+
export * from './plugin/registry.js';
|
|
11
|
+
export * from './orchestrator.js';
|
|
12
|
+
export * from './payload/builder.js';
|
|
13
|
+
export * from './payload/mermaid.js';
|
|
14
|
+
export * from './build/index.js';
|
|
15
|
+
export * from './fix/index.js';
|
|
16
|
+
export * from './telemetry/index.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './types/index.js';
|
|
2
|
+
export * from './scanner.js';
|
|
3
|
+
export * from './rules/index.js';
|
|
4
|
+
export * from './components/registry.js';
|
|
5
|
+
export * from './components/glob.js';
|
|
6
|
+
export * from './gates/types.js';
|
|
7
|
+
export * from './gates/advisories.js';
|
|
8
|
+
export * from './baseline/store.js';
|
|
9
|
+
export * from './baseline/fingerprint.js';
|
|
10
|
+
export * from './plugin/registry.js';
|
|
11
|
+
export * from './orchestrator.js';
|
|
12
|
+
export * from './payload/builder.js';
|
|
13
|
+
export * from './payload/mermaid.js';
|
|
14
|
+
export * from './build/index.js';
|
|
15
|
+
export * from './fix/index.js';
|
|
16
|
+
export * from './telemetry/index.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { RulesetIR } from './types/ir.js';
|
|
2
|
+
import { type ManifestScanner } from './types/manifest.js';
|
|
3
|
+
import type { BaselineStore } from './baseline/store.js';
|
|
4
|
+
import type { CheckRun } from './gates/types.js';
|
|
5
|
+
import type { PluginRegistry } from './plugin/registry.js';
|
|
6
|
+
import { type HostPredicateRegistry } from './rules/host-rules.js';
|
|
7
|
+
export interface CheckOptions {
|
|
8
|
+
readonly rootDir: string;
|
|
9
|
+
readonly excludes: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ties scanning, rule evaluation, and baseline filtering into one `CheckRun` (ARCHITECTURE.md
|
|
13
|
+
* §3). Rescan-on-check, always (ADR 005) — there is no cached-result path to call by mistake.
|
|
14
|
+
*/
|
|
15
|
+
export declare class GateOrchestrator {
|
|
16
|
+
private readonly registry;
|
|
17
|
+
private readonly ruleset;
|
|
18
|
+
private readonly baselineStore;
|
|
19
|
+
/** Injected, never constructed here (core stays framework-free) — the CLI composition root
|
|
20
|
+
* extracts this from `align.config.ts`'s `hostRules` export (`config.ts`, `composition-root.ts`).
|
|
21
|
+
* Defaults to empty so every pre-existing caller (tests, anything not using `custom.host`)
|
|
22
|
+
* keeps working unchanged. */
|
|
23
|
+
private readonly hostPredicates;
|
|
24
|
+
/** Injected, never constructed here (ADR 013, same seam as `hostPredicates` above) — the CLI
|
|
25
|
+
* composition root wires in `@spikedpunch/align-plugin-typescript`'s `NodeManifestScanner`. Defaults to a
|
|
26
|
+
* no-op so every pre-existing caller (tests, anything not authoring `security.manifest.*`
|
|
27
|
+
* rules) keeps working unchanged. */
|
|
28
|
+
private readonly manifestScanner;
|
|
29
|
+
constructor(registry: PluginRegistry, ruleset: RulesetIR, baselineStore: BaselineStore,
|
|
30
|
+
/** Injected, never constructed here (core stays framework-free) — the CLI composition root
|
|
31
|
+
* extracts this from `align.config.ts`'s `hostRules` export (`config.ts`, `composition-root.ts`).
|
|
32
|
+
* Defaults to empty so every pre-existing caller (tests, anything not using `custom.host`)
|
|
33
|
+
* keeps working unchanged. */
|
|
34
|
+
hostPredicates?: HostPredicateRegistry,
|
|
35
|
+
/** Injected, never constructed here (ADR 013, same seam as `hostPredicates` above) — the CLI
|
|
36
|
+
* composition root wires in `@spikedpunch/align-plugin-typescript`'s `NodeManifestScanner`. Defaults to a
|
|
37
|
+
* no-op so every pre-existing caller (tests, anything not authoring `security.manifest.*`
|
|
38
|
+
* rules) keeps working unchanged. */
|
|
39
|
+
manifestScanner?: ManifestScanner);
|
|
40
|
+
check(options: CheckOptions): Promise<CheckRun>;
|
|
41
|
+
/**
|
|
42
|
+
* `security` gate (ADR 013): scans the manifest domain (root + workspace `package.json` +
|
|
43
|
+
* `pnpm-lock.yaml`, `@spikedpunch/align-plugin-typescript`'s `NodeManifestScanner` in real deployments) and
|
|
44
|
+
* evaluates every `security.manifest.*` rule against it via `evaluateManifestRule`. Always
|
|
45
|
+
* `dependsOn: []` (ADR 008's always-run carve-out) — a manifest scan failure is this gate's own
|
|
46
|
+
* `error`, never cascades from or into the architecture gate's status.
|
|
47
|
+
*/
|
|
48
|
+
private runSecurityGate;
|
|
49
|
+
private scanAll;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAA4B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAY,QAAQ,EAAc,MAAM,kBAAkB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAetF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B;;;kCAG8B;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B;;;yCAGqC;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAZf,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,SAAS,EAClB,aAAa,EAAE,aAAa;IAC7C;;;kCAG8B;IACb,cAAc,GAAE,qBAA0C;IAC3E;;;yCAGqC;IACpB,eAAe,GAAE,eAAqC;IAGnE,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC;IA+IrD;;;;;;OAMG;YACW,eAAe;YAoDf,OAAO;CAkCtB"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { EMPTY_MANIFEST_INVENTORY } from './types/manifest.js';
|
|
2
|
+
import { buildUncertaintyAdvisories } from './gates/advisories.js';
|
|
3
|
+
import { evaluateRule } from './rules/evaluators.js';
|
|
4
|
+
import { evaluateManifestRule } from './rules/manifest-evaluators.js';
|
|
5
|
+
import { ruleCategoryOf } from './rules/rule-category.js';
|
|
6
|
+
import { validateRuleComponentRefs } from './rules/component-refs.js';
|
|
7
|
+
import { validateHostRules } from './rules/host-rules.js';
|
|
8
|
+
import { findUngroundedComponents, validateClassifiedComponents } from './components/registry.js';
|
|
9
|
+
/** No predicates registered — the default for callers that don't inject one (most existing tests
|
|
10
|
+
* exercise portable `arch.*` kinds only; a real deployment always gets a real registry from the
|
|
11
|
+
* CLI composition root, `packages/cli/src/composition-root.ts`). */
|
|
12
|
+
const NO_HOST_PREDICATES = new Map();
|
|
13
|
+
/** No-op default for callers that don't inject a real manifest scanner (most existing tests never
|
|
14
|
+
* author `security.manifest.*` rules; a real deployment gets `@spikedpunch/align-plugin-typescript`'s
|
|
15
|
+
* `NodeManifestScanner` from the CLI composition root — core never imports plugin-typescript
|
|
16
|
+
* directly, ADR 013/ARCHITECTURE.md §5). Returns the empty inventory, never throws — a repo with
|
|
17
|
+
* no `security.manifest.*` rules authored never even calls this. */
|
|
18
|
+
const NO_MANIFEST_SCANNER = { scan: () => EMPTY_MANIFEST_INVENTORY };
|
|
19
|
+
/**
|
|
20
|
+
* Ties scanning, rule evaluation, and baseline filtering into one `CheckRun` (ARCHITECTURE.md
|
|
21
|
+
* §3). Rescan-on-check, always (ADR 005) — there is no cached-result path to call by mistake.
|
|
22
|
+
*/
|
|
23
|
+
export class GateOrchestrator {
|
|
24
|
+
registry;
|
|
25
|
+
ruleset;
|
|
26
|
+
baselineStore;
|
|
27
|
+
hostPredicates;
|
|
28
|
+
manifestScanner;
|
|
29
|
+
constructor(registry, ruleset, baselineStore,
|
|
30
|
+
/** Injected, never constructed here (core stays framework-free) — the CLI composition root
|
|
31
|
+
* extracts this from `align.config.ts`'s `hostRules` export (`config.ts`, `composition-root.ts`).
|
|
32
|
+
* Defaults to empty so every pre-existing caller (tests, anything not using `custom.host`)
|
|
33
|
+
* keeps working unchanged. */
|
|
34
|
+
hostPredicates = NO_HOST_PREDICATES,
|
|
35
|
+
/** Injected, never constructed here (ADR 013, same seam as `hostPredicates` above) — the CLI
|
|
36
|
+
* composition root wires in `@spikedpunch/align-plugin-typescript`'s `NodeManifestScanner`. Defaults to a
|
|
37
|
+
* no-op so every pre-existing caller (tests, anything not authoring `security.manifest.*`
|
|
38
|
+
* rules) keeps working unchanged. */
|
|
39
|
+
manifestScanner = NO_MANIFEST_SCANNER) {
|
|
40
|
+
this.registry = registry;
|
|
41
|
+
this.ruleset = ruleset;
|
|
42
|
+
this.baselineStore = baselineStore;
|
|
43
|
+
this.hostPredicates = hostPredicates;
|
|
44
|
+
this.manifestScanner = manifestScanner;
|
|
45
|
+
}
|
|
46
|
+
async check(options) {
|
|
47
|
+
const scannedAt = Date.now();
|
|
48
|
+
// `security` gate (ADR 013): manifest-level, independent of the TypeScript source scan
|
|
49
|
+
// entirely — a disjoint scan domain (`ManifestInventory`, not `DependencyGraph`). Computed
|
|
50
|
+
// first, unconditionally, so a TS scan failure below never blocks it (ADR 008's always-run
|
|
51
|
+
// carve-out: `dependsOn: []`, "must always run regardless of what upstream gates report").
|
|
52
|
+
const { gateResult: securityGate, movedCount: securityMoves } = await this.runSecurityGate(options);
|
|
53
|
+
const parseStart = performance.now();
|
|
54
|
+
let graph;
|
|
55
|
+
try {
|
|
56
|
+
graph = await this.scanAll(options);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const parseGate = {
|
|
60
|
+
gate: 'parse',
|
|
61
|
+
status: 'error',
|
|
62
|
+
violations: [],
|
|
63
|
+
baselinedCount: 0,
|
|
64
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
65
|
+
durationMs: performance.now() - parseStart,
|
|
66
|
+
cacheHits: 0,
|
|
67
|
+
dependsOn: [],
|
|
68
|
+
};
|
|
69
|
+
const gates = [parseGate, skippedGate('architecture', ['parse']), securityGate];
|
|
70
|
+
return {
|
|
71
|
+
verdict: deriveVerdict(gates),
|
|
72
|
+
gates,
|
|
73
|
+
advisories: movedAdvisories(securityMoves),
|
|
74
|
+
scannedAt,
|
|
75
|
+
ungroundedComponents: [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const parseGate = {
|
|
79
|
+
gate: 'parse',
|
|
80
|
+
status: 'green',
|
|
81
|
+
violations: [],
|
|
82
|
+
baselinedCount: 0,
|
|
83
|
+
durationMs: performance.now() - parseStart,
|
|
84
|
+
cacheHits: 0,
|
|
85
|
+
dependsOn: [],
|
|
86
|
+
};
|
|
87
|
+
const archStart = performance.now();
|
|
88
|
+
// Vacuous-green guards (ARCHITECTURE.md's severity-zero false-green invariant), both
|
|
89
|
+
// surfaced as `error` — not `red`, not a silent drop (ADR 008: the architecture gate itself
|
|
90
|
+
// couldn't produce a trustworthy verdict, same category as a scanner crash above):
|
|
91
|
+
// 1. Every declared component must have at least one file classified to it this scan
|
|
92
|
+
// (`empty: 'allow' | 'until-populated'` opts out, ADR 003 + its greenfield-mode amendment).
|
|
93
|
+
// The TypeScript scanner independently enforces the selector-based half of this doctrine
|
|
94
|
+
// (`validateComponents`, plugin-typescript scanner.ts) at parse time; this
|
|
95
|
+
// classification-based check is plugin-independent and additionally catches a component
|
|
96
|
+
// fully shadowed by an earlier component's selector under first-match-wins — its rules
|
|
97
|
+
// would otherwise evaluate vacuously green. An opted-out-but-still-empty component isn't
|
|
98
|
+
// silently green either way: `findUngroundedComponents` below surfaces it (R1).
|
|
99
|
+
// 2. Every ComponentRef a rule embeds (hand-authored or `.align/generated-rules.json`-merged,
|
|
100
|
+
// ADR 011) must name a component present in the registry — otherwise `evaluateRule`
|
|
101
|
+
// simply never matches the stale name and the rule silently drops out.
|
|
102
|
+
// 3. Every `custom.host` rule must name a registered host predicate — an unregistered
|
|
103
|
+
// predicate is an unevaluatable rule reporting green. `this.hostPredicates`' key set is
|
|
104
|
+
// the real registered-name set once the CLI composition root injects one; a repo with no
|
|
105
|
+
// `hostRules` export gets the empty default, same as before registration existed.
|
|
106
|
+
const classifiedComponents = new Set(graph.nodes.map((n) => n.component));
|
|
107
|
+
try {
|
|
108
|
+
validateClassifiedComponents(this.ruleset.components, classifiedComponents);
|
|
109
|
+
validateRuleComponentRefs(this.ruleset.rules, this.ruleset.components);
|
|
110
|
+
validateHostRules(this.ruleset.rules, new Set(this.hostPredicates.keys()));
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
const gates = [parseGate, errorGate(err, archStart), securityGate];
|
|
114
|
+
return {
|
|
115
|
+
verdict: deriveVerdict(gates),
|
|
116
|
+
gates,
|
|
117
|
+
advisories: [...buildUncertaintyAdvisories(graph.uncertain), ...movedAdvisories(securityMoves)],
|
|
118
|
+
scannedAt,
|
|
119
|
+
ungroundedComponents: [],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// `security.manifest.*` rules never reach here — `ruleCategoryOf` partitions `RulesetIR.rules`
|
|
123
|
+
// between this graph-based pipeline and `runSecurityGate`'s manifest-based one (ADR 013), two
|
|
124
|
+
// disjoint scan domains that must never be evaluated through each other's dispatcher.
|
|
125
|
+
const architectureRules = this.ruleset.rules.filter((rule) => ruleCategoryOf(rule) === 'architecture');
|
|
126
|
+
// A registered predicate that throws (`HostPredicateExecutionError`) surfaces here — the
|
|
127
|
+
// reference-validity invariant's sibling (ADR 008 amendment): a buggy predicate must never be
|
|
128
|
+
// a silent pass, so it's caught at the same granularity as the guard-step failures above,
|
|
129
|
+
// never allowed to abort the process with an unattributed stack trace.
|
|
130
|
+
const allViolations = [];
|
|
131
|
+
try {
|
|
132
|
+
for (const rule of architectureRules) {
|
|
133
|
+
const violations = evaluateRule(rule, graph, this.ruleset.components, this.hostPredicates);
|
|
134
|
+
allViolations.push(...violations);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
const gates = [parseGate, errorGate(err, archStart), securityGate];
|
|
139
|
+
return {
|
|
140
|
+
verdict: deriveVerdict(gates),
|
|
141
|
+
gates,
|
|
142
|
+
advisories: [...buildUncertaintyAdvisories(graph.uncertain), ...movedAdvisories(securityMoves)],
|
|
143
|
+
scannedAt,
|
|
144
|
+
ungroundedComponents: [],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Move-transfer (ADR 006), run on every check — not just `baseline prune` — so a renamed
|
|
148
|
+
// file whose violation was already baselined doesn't turn CI red for one cycle. Mutates the
|
|
149
|
+
// store in place; the CLI/MCP surface persists the updated snapshot when transfers occurred.
|
|
150
|
+
const moves = this.baselineStore.reconcileMoves(allViolations);
|
|
151
|
+
const newViolations = allViolations.filter((v) => !this.baselineStore.isBaselined(v.id));
|
|
152
|
+
const baselinedCount = allViolations.length - newViolations.length;
|
|
153
|
+
const rulesWithNoViolations = architectureRules.filter((rule) => !allViolations.some((v) => v.ruleId === rule.id)).length;
|
|
154
|
+
const architectureGate = {
|
|
155
|
+
gate: 'architecture',
|
|
156
|
+
status: newViolations.length > 0 ? 'red' : 'green',
|
|
157
|
+
violations: newViolations,
|
|
158
|
+
baselinedCount,
|
|
159
|
+
passCount: rulesWithNoViolations,
|
|
160
|
+
durationMs: performance.now() - archStart,
|
|
161
|
+
cacheHits: 0,
|
|
162
|
+
dependsOn: ['parse'],
|
|
163
|
+
};
|
|
164
|
+
const advisories = [
|
|
165
|
+
...buildUncertaintyAdvisories(graph.uncertain),
|
|
166
|
+
...movedAdvisories(moves.length + securityMoves),
|
|
167
|
+
];
|
|
168
|
+
const gates = [parseGate, architectureGate, securityGate];
|
|
169
|
+
const verdict = deriveVerdict(gates);
|
|
170
|
+
// R1 (greenfield mode): computed once the guard step above has proven every component name
|
|
171
|
+
// is trustworthy — reuses the same classification set `validateClassifiedComponents` just
|
|
172
|
+
// validated against, no second pass over the graph.
|
|
173
|
+
const ungroundedComponents = findUngroundedComponents(this.ruleset.components, classifiedComponents);
|
|
174
|
+
return { verdict, gates, advisories, scannedAt, ungroundedComponents };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* `security` gate (ADR 013): scans the manifest domain (root + workspace `package.json` +
|
|
178
|
+
* `pnpm-lock.yaml`, `@spikedpunch/align-plugin-typescript`'s `NodeManifestScanner` in real deployments) and
|
|
179
|
+
* evaluates every `security.manifest.*` rule against it via `evaluateManifestRule`. Always
|
|
180
|
+
* `dependsOn: []` (ADR 008's always-run carve-out) — a manifest scan failure is this gate's own
|
|
181
|
+
* `error`, never cascades from or into the architecture gate's status.
|
|
182
|
+
*/
|
|
183
|
+
async runSecurityGate(options) {
|
|
184
|
+
const start = performance.now();
|
|
185
|
+
const securityRules = this.ruleset.rules.filter((rule) => ruleCategoryOf(rule) === 'security');
|
|
186
|
+
let inventory;
|
|
187
|
+
try {
|
|
188
|
+
inventory = await this.manifestScanner.scan({ rootDir: options.rootDir, excludes: options.excludes });
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
return {
|
|
192
|
+
gateResult: {
|
|
193
|
+
gate: 'security',
|
|
194
|
+
status: 'error',
|
|
195
|
+
violations: [],
|
|
196
|
+
baselinedCount: 0,
|
|
197
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
198
|
+
durationMs: performance.now() - start,
|
|
199
|
+
cacheHits: 0,
|
|
200
|
+
dependsOn: [],
|
|
201
|
+
},
|
|
202
|
+
movedCount: 0,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const allViolations = [];
|
|
206
|
+
for (const rule of securityRules) {
|
|
207
|
+
allViolations.push(...evaluateManifestRule(rule, inventory));
|
|
208
|
+
}
|
|
209
|
+
const moves = this.baselineStore.reconcileMoves(allViolations);
|
|
210
|
+
const newViolations = allViolations.filter((v) => !this.baselineStore.isBaselined(v.id));
|
|
211
|
+
const baselinedCount = allViolations.length - newViolations.length;
|
|
212
|
+
const rulesWithNoViolations = securityRules.filter((rule) => !allViolations.some((v) => v.ruleId === rule.id)).length;
|
|
213
|
+
return {
|
|
214
|
+
gateResult: {
|
|
215
|
+
gate: 'security',
|
|
216
|
+
status: newViolations.length > 0 ? 'red' : 'green',
|
|
217
|
+
violations: newViolations,
|
|
218
|
+
baselinedCount,
|
|
219
|
+
passCount: rulesWithNoViolations,
|
|
220
|
+
durationMs: performance.now() - start,
|
|
221
|
+
cacheHits: 0,
|
|
222
|
+
dependsOn: [],
|
|
223
|
+
},
|
|
224
|
+
movedCount: moves.length,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
async scanAll(options) {
|
|
228
|
+
const plugins = this.registry.getAllPlugins();
|
|
229
|
+
if (plugins.length === 0) {
|
|
230
|
+
throw new Error('No language plugins registered — nothing to scan.');
|
|
231
|
+
}
|
|
232
|
+
// v1 has exactly one plugin; merging is written generically so a second plugin is additive.
|
|
233
|
+
const graphs = await Promise.all(plugins.map((plugin) => plugin.scanner.scan({
|
|
234
|
+
rootDir: options.rootDir,
|
|
235
|
+
components: this.ruleset.components,
|
|
236
|
+
excludes: options.excludes,
|
|
237
|
+
})));
|
|
238
|
+
if (graphs.length === 1) {
|
|
239
|
+
const only = graphs[0];
|
|
240
|
+
if (only === undefined)
|
|
241
|
+
throw new Error('unreachable: graphs.length === 1');
|
|
242
|
+
return only;
|
|
243
|
+
}
|
|
244
|
+
// Dedup external nodes by id across plugins (Stage 5 infra) — two plugins could both see an
|
|
245
|
+
// import of the same external package name; the same `id`-keyed-Map dedup the scanner itself
|
|
246
|
+
// uses within one scan.
|
|
247
|
+
const externalNodesById = new Map();
|
|
248
|
+
for (const g of graphs)
|
|
249
|
+
for (const n of g.externalNodes)
|
|
250
|
+
externalNodesById.set(n.id, n);
|
|
251
|
+
return {
|
|
252
|
+
nodes: graphs.flatMap((g) => g.nodes),
|
|
253
|
+
edges: graphs.flatMap((g) => g.edges),
|
|
254
|
+
externalNodes: [...externalNodesById.values()],
|
|
255
|
+
externalEdges: graphs.flatMap((g) => g.externalEdges),
|
|
256
|
+
uncertain: graphs.flatMap((g) => g.uncertain),
|
|
257
|
+
scannedAt: Math.min(...graphs.map((g) => g.scannedAt)),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/** Shared by every `architecture` gate `error` path (guard-step failures, predicate exceptions) —
|
|
262
|
+
* ADR 008: `error` is categorically distinct from `red`, always halts and escalates, never enters
|
|
263
|
+
* an LLM-facing payload as prose (only `errorMessage`, a plain string). */
|
|
264
|
+
function errorGate(err, archStart) {
|
|
265
|
+
return {
|
|
266
|
+
gate: 'architecture',
|
|
267
|
+
status: 'error',
|
|
268
|
+
violations: [],
|
|
269
|
+
baselinedCount: 0,
|
|
270
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
271
|
+
durationMs: performance.now() - archStart,
|
|
272
|
+
cacheHits: 0,
|
|
273
|
+
dependsOn: ['parse'],
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function skippedGate(gate, dependsOn) {
|
|
277
|
+
return {
|
|
278
|
+
gate,
|
|
279
|
+
status: 'skipped',
|
|
280
|
+
violations: [],
|
|
281
|
+
baselinedCount: 0,
|
|
282
|
+
durationMs: 0,
|
|
283
|
+
cacheHits: 0,
|
|
284
|
+
dependsOn,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/** Shared advisory-shape builder for move-transfer counts (ADR 006) — the architecture gate's own
|
|
288
|
+
* moves and the security gate's own moves are reconciled separately (two independent
|
|
289
|
+
* `reconcileMoves` calls against disjoint violation sets, since a manifest violation's content
|
|
290
|
+
* fingerprint never collides with a graph-based one) but reported as one combined advisory,
|
|
291
|
+
* matching the single `baseline-moved` advisory shape every existing caller already expects. */
|
|
292
|
+
function movedAdvisories(count) {
|
|
293
|
+
if (count === 0)
|
|
294
|
+
return [];
|
|
295
|
+
return [{ kind: 'baseline-moved', message: `${count} ${count === 1 ? 'entry' : 'entries'} transferred (file moves).` }];
|
|
296
|
+
}
|
|
297
|
+
function deriveVerdict(gates) {
|
|
298
|
+
if (gates.some((g) => g.status === 'error'))
|
|
299
|
+
return 'error';
|
|
300
|
+
if (gates.some((g) => g.status === 'red'))
|
|
301
|
+
return 'red';
|
|
302
|
+
return 'green';
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ComponentName, RepoRelativePath, RuleId } from '../types/branded.js';
|
|
2
|
+
import type { Category } from '../types/violation.js';
|
|
3
|
+
import type { UngroundedComponent } from '../components/registry.js';
|
|
4
|
+
import type { Advisory, CheckRun, GateStatus } from '../gates/types.js';
|
|
5
|
+
import type { RuleIR } from '../types/ir.js';
|
|
6
|
+
import type { Violation } from '../types/violation.js';
|
|
7
|
+
export interface McpCheckPayload {
|
|
8
|
+
readonly verdict: 'green' | 'red' | 'error';
|
|
9
|
+
readonly gates: readonly {
|
|
10
|
+
readonly gate: 'parse' | Category;
|
|
11
|
+
readonly status: GateStatus;
|
|
12
|
+
readonly violationCount: number;
|
|
13
|
+
readonly baselinedCount: number;
|
|
14
|
+
readonly passCount?: number;
|
|
15
|
+
}[];
|
|
16
|
+
readonly violations: readonly Violation[];
|
|
17
|
+
readonly pagination?: {
|
|
18
|
+
readonly cursor: string;
|
|
19
|
+
readonly hasMore: boolean;
|
|
20
|
+
};
|
|
21
|
+
readonly advisories: readonly Advisory[];
|
|
22
|
+
/** R1 (greenfield mode): components that are green only because they matched zero files this
|
|
23
|
+
* scan — structured so an agent can branch on it without string-parsing an advisory message
|
|
24
|
+
* (`{name, selector, policy}` per IMPLEMENTATION_PLAN.md's Design Reserve spec). Verdict stays
|
|
25
|
+
* `green` (an empty greenfield component is not a failure); this field is what makes that green
|
|
26
|
+
* distinguishable from a fully-grounded one. */
|
|
27
|
+
readonly ungroundedComponents: readonly UngroundedComponent[];
|
|
28
|
+
}
|
|
29
|
+
export interface BuildCheckPayloadOptions {
|
|
30
|
+
readonly maxPerRule?: number;
|
|
31
|
+
readonly cursor?: string;
|
|
32
|
+
readonly pageSize?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Priority sort, cap-per-rule, and page the violations from a `CheckRun` into the structured-only
|
|
36
|
+
* MCP payload shape (ADR 007). Passing gates contribute counts only — never per-item text.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildMcpCheckPayload(run: CheckRun, options?: BuildCheckPayloadOptions): McpCheckPayload;
|
|
39
|
+
export interface McpExplainRulePayload {
|
|
40
|
+
readonly ruleId: RuleId;
|
|
41
|
+
readonly kind: RuleIR['kind'];
|
|
42
|
+
readonly because?: string;
|
|
43
|
+
readonly components: readonly {
|
|
44
|
+
readonly name: ComponentName;
|
|
45
|
+
readonly exampleFiles: readonly RepoRelativePath[];
|
|
46
|
+
}[];
|
|
47
|
+
readonly mermaid?: string;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/payload/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAYvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,SAAS;QACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;QAClC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;QAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;KAC7B,EAAE,CAAC;IACJ,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7E,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC;;;;oDAIgD;IAChD,QAAQ,CAAC,oBAAoB,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC/D;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,GAAE,wBAA6B,GAAG,eAAe,CA0B3G;AAwBD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,YAAY,EAAE,SAAS,gBAAgB,EAAE,CAAA;KAAE,EAAE,CAAC;IACrH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAE3B"}
|