@holmes-lab/holmes-kit 0.1.7 → 0.1.9
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/CHANGELOG.md +8 -0
- package/README.md +11 -7
- package/bin/holmes-mcp.js +0 -0
- package/dist/.build-id +1 -1
- package/dist/holmes/cli/agents.d.ts +50 -0
- package/dist/holmes/cli/ci-gate.d.ts +18 -0
- package/dist/holmes/cli/doctor.d.ts +44 -0
- package/dist/holmes/cli/gitignore-merge.d.ts +18 -0
- package/dist/holmes/cli/governed-precondition.d.ts +27 -0
- package/dist/holmes/cli/index.d.ts +14 -0
- package/dist/holmes/cli/index.js +23 -1
- package/dist/holmes/cli/init.d.ts +69 -0
- package/dist/holmes/cli/interactive-prompt.d.ts +9 -0
- package/dist/holmes/cli/playbook-skills.d.ts +129 -0
- package/dist/holmes/cli/roles-readme.d.ts +12 -0
- package/dist/holmes/cli/serve.d.ts +14 -0
- package/dist/holmes/cli/serve.js +70 -0
- package/dist/holmes/cli/settings-merge.d.ts +66 -0
- package/dist/holmes/config/config.d.ts +13 -0
- package/dist/holmes/context/bundler.d.ts +40 -0
- package/dist/holmes/context/render.d.ts +9 -0
- package/dist/holmes/context/tiers.d.ts +54 -0
- package/dist/holmes/context/tokens.d.ts +2 -0
- package/dist/holmes/cpg/ast-mutation.d.ts +31 -0
- package/dist/holmes/cpg/ast-mutation.js +126 -0
- package/dist/holmes/cpg/cpg-scanner.d.ts +69 -0
- package/dist/holmes/cpg/dynamic-cpg.d.ts +18 -0
- package/dist/holmes/cpg/dynamic-cpg.js +82 -0
- package/dist/holmes/cpg/hash-cache.d.ts +21 -0
- package/dist/holmes/cpg/language-parser-walk.d.ts +31 -0
- package/dist/holmes/cpg/language-parser-worker.d.ts +1 -0
- package/dist/holmes/cpg/language-parser.d.ts +116 -0
- package/dist/holmes/cpg/program-slicing.d.ts +21 -0
- package/dist/holmes/cpg/program-slicing.js +123 -0
- package/dist/holmes/cpg/scan-cache.d.ts +21 -0
- package/dist/holmes/cpg/source-path.d.ts +2 -0
- package/dist/holmes/cpg/test-files.d.ts +36 -0
- package/dist/holmes/governance/constitution-debt.d.ts +3 -0
- package/dist/holmes/governance/constitution-report.d.ts +23 -0
- package/dist/holmes/governance/constitution.d.ts +61 -0
- package/dist/holmes/governance/identity.d.ts +28 -0
- package/dist/holmes/governance/ledger-lock.d.ts +55 -0
- package/dist/holmes/governance/ledger-store.conformance.d.ts +11 -0
- package/dist/holmes/governance/ledger-store.d.ts +114 -0
- package/dist/holmes/governance/progress-ledger.d.ts +25 -0
- package/dist/holmes/governance/provenance-chain.d.ts +154 -0
- package/dist/holmes/governance/provenance-ledger.d.ts +102 -0
- package/dist/holmes/governance/provenance-schema.d.ts +21 -0
- package/dist/holmes/governance/replica-id.d.ts +20 -0
- package/dist/holmes/governance/role-policy.d.ts +52 -0
- package/dist/holmes/governance/trust-score.d.ts +32 -0
- package/dist/holmes/guardrail/anchors.d.ts +8 -0
- package/dist/holmes/guardrail/blind-spots.d.ts +32 -0
- package/dist/holmes/guardrail/decision-ledger.d.ts +29 -0
- package/dist/holmes/guardrail/executable-artifact.d.ts +1 -0
- package/dist/holmes/guardrail/governance-history.d.ts +15 -0
- package/dist/holmes/guardrail/phase.d.ts +27 -0
- package/dist/holmes/guardrail/risk-classifier.d.ts +52 -0
- package/dist/holmes/guardrail/risk-gate.d.ts +77 -0
- package/dist/holmes/guardrail/risk-types.d.ts +48 -0
- package/dist/holmes/guardrail/tspec-state.d.ts +71 -0
- package/dist/holmes/guardrail/write-target.d.ts +77 -0
- package/dist/holmes/hooks/adapters/antigravity.d.ts +42 -0
- package/dist/holmes/hooks/pre-tool-use.d.ts +144 -0
- package/dist/holmes/hooks/stop.d.ts +91 -0
- package/dist/holmes/mcp/basis.d.ts +100 -0
- package/dist/holmes/mcp/handlers.d.ts +482 -0
- package/dist/holmes/mcp/server.d.ts +2 -0
- package/dist/holmes/mcp/stdio-client.d.ts +51 -0
- package/dist/holmes/mcp/supervisor.d.ts +48 -0
- package/dist/holmes/mcp/tool-schemas.d.ts +12 -0
- package/dist/holmes/mcp/validate-args.d.ts +27 -0
- package/dist/holmes/messages/registry.d.ts +23 -0
- package/dist/holmes/project/baseline.d.ts +66 -0
- package/dist/holmes/project/change-source.d.ts +89 -0
- package/dist/holmes/project/ignore.d.ts +33 -0
- package/dist/holmes/project/root.d.ts +34 -0
- package/dist/holmes/reverse/anchor.d.ts +47 -0
- package/dist/holmes/reverse/cluster.d.ts +45 -0
- package/dist/holmes/reverse/draft.d.ts +33 -0
- package/dist/holmes/reverse/dynamic-wiring.d.ts +18 -0
- package/dist/holmes/reverse/scan.d.ts +103 -0
- package/dist/holmes/reverse/surface.d.ts +91 -0
- package/dist/holmes/reverse/test-map.d.ts +91 -0
- package/dist/holmes/review/coverage.d.ts +21 -0
- package/dist/holmes/review/findings.d.ts +49 -0
- package/dist/holmes/review/package.d.ts +26 -0
- package/dist/holmes/review/review-targets.d.ts +28 -0
- package/dist/holmes/review/scope.d.ts +13 -0
- package/dist/holmes/review/test-evidence.d.ts +31 -0
- package/dist/holmes/review/test-runner.d.ts +141 -0
- package/dist/holmes/rtm/dataflow-taint.d.ts +81 -0
- package/dist/holmes/rtm/gap-analyzer.d.ts +28 -0
- package/dist/holmes/rtm/git-changes.d.ts +33 -0
- package/dist/holmes/rtm/heatmap.d.ts +21 -0
- package/dist/holmes/rtm/incremental.d.ts +38 -0
- package/dist/holmes/rtm/localize.d.ts +36 -0
- package/dist/holmes/rtm/rtm-builder.d.ts +101 -0
- package/dist/holmes/rtm/rtm-check.d.ts +13 -0
- package/dist/holmes/rtm/rtm-graph.d.ts +88 -0
- package/dist/holmes/rtm/taint.d.ts +35 -0
- package/dist/holmes/rtm/test-scope.d.ts +85 -0
- package/dist/holmes/server/dashboard.d.ts +85 -0
- package/dist/holmes/server/dashboard.js +2188 -0
- package/dist/holmes/spec/approval-blockers.d.ts +62 -0
- package/dist/holmes/spec/breaking-change.d.ts +42 -0
- package/dist/holmes/spec/legacy-format.d.ts +93 -0
- package/dist/holmes/spec/spec-digest.d.ts +29 -0
- package/dist/holmes/spec/spec-parser.d.ts +12 -0
- package/dist/holmes/spec/spec-store.conformance.d.ts +10 -0
- package/dist/holmes/spec/spec-store.d.ts +130 -0
- package/dist/holmes/spec/spec-types.d.ts +150 -0
- package/dist/holmes/spec/validator.d.ts +65 -0
- package/package.json +2 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Spec } from '../spec/spec-parser';
|
|
2
|
+
import { ScannedFile } from '../cpg/cpg-scanner';
|
|
3
|
+
export interface RtmIssue {
|
|
4
|
+
kind: 'orphan' | 'cycle' | 'dangling' | 'duplicate-id' | 'dangling-implements' | 'wrong-kind-implements';
|
|
5
|
+
id: string;
|
|
6
|
+
detail: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function computeBlastRadius(specs: Spec[], targetId: string): {
|
|
9
|
+
impactedSpecCount: number;
|
|
10
|
+
hitsFoundational: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare function rtmCheck(specs: Spec[]): RtmIssue[];
|
|
13
|
+
export declare function checkImplements(scanned: ScannedFile[], specs: Spec[]): RtmIssue[];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The RTM graph. **NOT PERSISTED — read this before assuming otherwise.**
|
|
3
|
+
*
|
|
4
|
+
* Every one of the seven handlers that touches a graph (`rtm_impact`, `rtm_reindex`,
|
|
5
|
+
* `context_bundle`, `review_scope`, `review_prepare`, `risk_check`, `test_run`) constructs
|
|
6
|
+
* `new RtmGraph()` with no path, so the store is `:memory:`, built from scratch on each call and
|
|
7
|
+
* discarded when the call returns. Nothing writes `.ax/rtm.sqlite`.
|
|
8
|
+
*
|
|
9
|
+
* The surrounding machinery reads as though a persistent graph exists — `applyIncremental`,
|
|
10
|
+
* `rtm_reindex`, a `.gitignore` entry for `.ax/rtm.sqlite` — and it does not. I misread exactly this
|
|
11
|
+
* and reasoned from a persistent graph that was never there, so it is stated here rather than left
|
|
12
|
+
* to be inferred from seven constructor calls.
|
|
13
|
+
*
|
|
14
|
+
* This is a DELIBERATE position, not an omission (ADR-011): the graph is a derived index whose four
|
|
15
|
+
* inputs all come from git-tracked files, so rebuilding is always correct, a past commit's `.md` +
|
|
16
|
+
* source reconstructs that commit's graph for free, and staleness cannot occur. Persisting is
|
|
17
|
+
* deferred until graph build exceeds ~1 s per call, at which point ADR-011 lists the safety
|
|
18
|
+
* machinery that has to land with it.
|
|
19
|
+
*
|
|
20
|
+
* CONSEQUENCE FOR `rtm_reindex`: it calls `buildRtm` (a full build at HEAD) and only then
|
|
21
|
+
* `applyIncremental`, which removes and re-adds the changed files' subgraphs from that same scan.
|
|
22
|
+
* The result is identical to the full build, so the incremental pass is currently redundant work
|
|
23
|
+
* rather than a saving. It becomes meaningful the moment a persisted graph exists.
|
|
24
|
+
*/
|
|
25
|
+
export declare class RtmGraph {
|
|
26
|
+
private readonly db;
|
|
27
|
+
constructor(dbPath?: string);
|
|
28
|
+
private nodeStmt?;
|
|
29
|
+
private edgeStmt?;
|
|
30
|
+
addNode(id: string, kind: string, sourcePath?: string): void;
|
|
31
|
+
addEdge(src: string, dst: string, rel: string, sourcePath?: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* @implements A-SPEC-139
|
|
34
|
+
* Run `fn` inside ONE SQLite transaction, so a build commits once instead of once per insert.
|
|
35
|
+
* Returns fn's value; on a throw it rolls back and re-throws — a failed build leaves no half-graph
|
|
36
|
+
* a caller could mistake for a complete one (stricter than the previous partial-insert behavior).
|
|
37
|
+
* better-sqlite3 nests via savepoints, so calling this inside an outer transaction is safe.
|
|
38
|
+
*/
|
|
39
|
+
transaction<T>(fn: () => T): T;
|
|
40
|
+
reachable(fromId: string): string[];
|
|
41
|
+
incoming(toId: string): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Callers of a symbol — `calls` edges only, walked backwards. Impact propagation needs exactly
|
|
44
|
+
* this and not `incoming`, which would also drag in `implements` and `depends_on` and turn a
|
|
45
|
+
* "who calls me" question into "what is attached to me in any way at all".
|
|
46
|
+
*/
|
|
47
|
+
callersOf(id: string): string[];
|
|
48
|
+
/** How many distinct symbols call this one. The hub signal for bounded propagation (REQ-127). */
|
|
49
|
+
callerCount(id: string): number;
|
|
50
|
+
/**
|
|
51
|
+
* Specs this code node anchors, plus their transitive `depends_on` ancestors.
|
|
52
|
+
*
|
|
53
|
+
* Deliberately NOT `reachable`, which follows every relation. Once call edges exist, a generic
|
|
54
|
+
* forward walk from a CODE node crosses `calls` too and collects the specs of everything the
|
|
55
|
+
* symbol CALLS — silently answering "what does this depend on" while claiming to answer "what
|
|
56
|
+
* breaks if I change this". Adversarial review caught exactly that: changing a caller reported the
|
|
57
|
+
* callee's spec. Impact walks callers BACKWARD; only anchors are followed forward.
|
|
58
|
+
*/
|
|
59
|
+
specsOf(codeId: string): string[];
|
|
60
|
+
/**
|
|
61
|
+
* Neighbours with the relation that connects them, so a traversal can price a `calls` hop
|
|
62
|
+
* differently from a spec-chain hop. Same ordering guarantee as `neighbors`.
|
|
63
|
+
*
|
|
64
|
+
* A node reachable by several relations appears once per relation; callers take the cheapest.
|
|
65
|
+
*/
|
|
66
|
+
neighborsWithRel(id: string): Array<{
|
|
67
|
+
id: string;
|
|
68
|
+
rel: string;
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* This node's `depends_on` PARENTS — outgoing only, so it climbs the spec chain without descending
|
|
72
|
+
* into siblings. A shared parent (one REQ under which many slices hang) is a bidirectional hub;
|
|
73
|
+
* following it in both directions walks from any slice into every other one.
|
|
74
|
+
*/
|
|
75
|
+
parentsOf(id: string): string[];
|
|
76
|
+
/** Nodes exactly one edge away in EITHER direction, sorted ascending and deduped. */
|
|
77
|
+
neighbors(id: string): string[];
|
|
78
|
+
removeBySource(sourcePath: string): void;
|
|
79
|
+
codeNodeIds(qn: string): string[];
|
|
80
|
+
callReachable(fromId: string): string[];
|
|
81
|
+
/** @implements A-SPEC-138 — every CODE node id, for the taint pass to match source/sink names against. */
|
|
82
|
+
allCodeNodeIds(): string[];
|
|
83
|
+
/** @implements A-SPEC-138 — direct calls-only callees of a node (one hop), for BFS path assembly. */
|
|
84
|
+
callees(fromId: string): string[];
|
|
85
|
+
nodeCount(): number;
|
|
86
|
+
edgeCount(): number;
|
|
87
|
+
close(): void;
|
|
88
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RtmGraph } from './rtm-graph';
|
|
2
|
+
/**
|
|
3
|
+
* Call-graph taint REACHABILITY (REQ-138). This is a SCREENING signal, not a data-flow proof: it
|
|
4
|
+
* reports call paths from a source-named function to a sink-named function, so a security review has
|
|
5
|
+
* candidate paths to start from. It does NOT track tainted data (no def-use, no parameter/return
|
|
6
|
+
* propagation) and does NOT model sanitizers — so it over-reports (a call path that never carries
|
|
7
|
+
* tainted data) and can under-report (flow through a non-call channel). Every consumer must carry the
|
|
8
|
+
* honesty envelope (see `TAINT_LIMITS`) and phrase findings as "reaches", never "vulnerable".
|
|
9
|
+
*/
|
|
10
|
+
export interface TaintConfig {
|
|
11
|
+
sources: string[];
|
|
12
|
+
sinks: string[];
|
|
13
|
+
maxPaths?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface TaintPair {
|
|
16
|
+
source: string;
|
|
17
|
+
sink: string;
|
|
18
|
+
path: string[];
|
|
19
|
+
}
|
|
20
|
+
/** The limits every taint report must disclose — this is reachability, not data-flow. */
|
|
21
|
+
export declare const TAINT_LIMITS: readonly ["name-based matching", "no def-use", "no sanitizers", "call-edge-only"];
|
|
22
|
+
/**
|
|
23
|
+
* A small, conservative default source/sink set. Patterns are case-insensitive substrings on a node's
|
|
24
|
+
* qualified name. Deliberately narrow (precision over recall) and overridable by config.
|
|
25
|
+
*/
|
|
26
|
+
export declare const DEFAULT_TAINT_CONFIG: TaintConfig;
|
|
27
|
+
/**
|
|
28
|
+
* Source→sink call-reachability pairs over the graph. Deterministic: sources and sinks are iterated
|
|
29
|
+
* in the graph's sorted node order, pairs are deduped by (source, sink) and sorted, and capped at
|
|
30
|
+
* `maxPaths` with `truncated` reporting the remainder. Pure except the graph read.
|
|
31
|
+
*/
|
|
32
|
+
export declare function taintReachability(graph: RtmGraph, cfg: TaintConfig): {
|
|
33
|
+
pairs: TaintPair[];
|
|
34
|
+
truncated: number;
|
|
35
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Spec } from '../spec/spec-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Intelligent regression test-scope (target-architecture §5, differentiator ③) — SAFE by default.
|
|
4
|
+
*
|
|
5
|
+
* Decides HOW MUCH to re-test for a change. Adversarial review (C1/C2/C3/H1) proved the first cut was
|
|
6
|
+
* unsound in production, so this version is rebuilt around one rule: NEVER report a narrower scope than
|
|
7
|
+
* can be justified. When the impact analysis is uncertain or the test↔spec mapping is incomplete, it
|
|
8
|
+
* escalates to `full` — a false "safe" (skipping a test that would have caught a regression) is the
|
|
9
|
+
* only unacceptable outcome; over-running tests is merely slower.
|
|
10
|
+
*
|
|
11
|
+
* unit — impacted specs map to anchored tests, low downstream blast, no coverage gaps
|
|
12
|
+
* partial — moderate downstream blast
|
|
13
|
+
* full — foundational REQ reached, wide blast, a coverage gap, OR impacted specs with NO
|
|
14
|
+
* resolvable anchored tests (can't narrow safely) OR no analysis at all
|
|
15
|
+
*
|
|
16
|
+
* Key fixes vs. the first cut:
|
|
17
|
+
* - C1: impacted spec ids are stripped of the graph's `SPEC:` node-id prefix before use.
|
|
18
|
+
* - C2: impacted TEST files come from a SEPARATE test-file @implements scan (scanTestAnchors), because
|
|
19
|
+
* the CPG scanner deliberately excludes test files from the production symbol graph.
|
|
20
|
+
* - C3/H1: the tier is driven by downstream BLAST RADIUS + coverage gaps + test resolvability, not by
|
|
21
|
+
* the ancestor-chain length (which is ~constant depth, not breadth) — and defaults to `full`.
|
|
22
|
+
*/
|
|
23
|
+
export type RegressionTier = 'unit' | 'partial' | 'full';
|
|
24
|
+
export interface TestScopeThresholds {
|
|
25
|
+
partialBlast?: number;
|
|
26
|
+
fullBlast?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface TestScope {
|
|
29
|
+
tier: RegressionTier;
|
|
30
|
+
impactedSpecs: string[];
|
|
31
|
+
impactedTestFiles: string[];
|
|
32
|
+
blastRadius: number;
|
|
33
|
+
hitsFoundational: boolean;
|
|
34
|
+
coverageGaps: string[];
|
|
35
|
+
reason: string;
|
|
36
|
+
/** Changed source files that resolved into NO lane (A-SPEC-130) — nonempty forces `full`. */
|
|
37
|
+
unresolvedFiles: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @implements A-SPEC-130
|
|
41
|
+
* Lane-3 self-selection and the unresolved remainder, threaded into the tier decision. Optional and
|
|
42
|
+
* additive: every existing five-argument caller is untouched, and an empty extras changes nothing.
|
|
43
|
+
*/
|
|
44
|
+
export interface TestScopeExtras {
|
|
45
|
+
/** Changed files that ARE test files: they join the selected set of any non-full tier. */
|
|
46
|
+
changedTestFiles?: string[];
|
|
47
|
+
/** Changed scannable sources no lane resolved: tier becomes `full`, reason names them. */
|
|
48
|
+
unresolvedFiles?: string[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @implements A-SPEC-130
|
|
52
|
+
* Three-lane resolution for changed files. Impact propagation is symbol-keyed, so three classes of
|
|
53
|
+
* changed file used to vanish before the tier decision (measured 2026-08-06: five changed sources,
|
|
54
|
+
* zero changed symbols, tier "nothing to re-test", noop passed:true):
|
|
55
|
+
*
|
|
56
|
+
* lane 1 symbols changed -> the existing symbol path owns it; not accounted here
|
|
57
|
+
* lane 2 scanned, 0 symbols, -> its `implementsSpecs` join the impacted set directly — the
|
|
58
|
+
* readable @implements anchor was always on disk; only the symbol keying dropped it
|
|
59
|
+
* lane 3 a test file -> selects ITSELF (the symbol scan excludes tests by design)
|
|
60
|
+
* else scannable source -> UNRESOLVED: the graph cannot see it, the tier must widen
|
|
61
|
+
*
|
|
62
|
+
* Docs, specs, playbooks and anything under `.ax/` never qualify as unresolved — a documentation
|
|
63
|
+
* change must not trigger a full regression. Pure set arithmetic over signals already in memory.
|
|
64
|
+
*/
|
|
65
|
+
export interface ChangedFileAccount {
|
|
66
|
+
anchorImpactedSpecs: string[];
|
|
67
|
+
changedTestFiles: string[];
|
|
68
|
+
unresolvedFiles: string[];
|
|
69
|
+
}
|
|
70
|
+
export declare function accountChangedFiles(changedFiles: string[], scanEntry: (rel: string) => {
|
|
71
|
+
implementsSpecs: string[];
|
|
72
|
+
symbolCount: number;
|
|
73
|
+
} | undefined): ChangedFileAccount;
|
|
74
|
+
/** Frameworks this counter understands, for diagnostics and tests. */
|
|
75
|
+
export declare const SUPPORTED_TEST_FRAMEWORKS: string[];
|
|
76
|
+
export declare function countTestCases(source: string, filePath?: string): number;
|
|
77
|
+
/** A-SPEC ids anchored by a file, counting only standalone comment-line markers outside literals. */
|
|
78
|
+
export declare function extractAnchors(source: string): string[];
|
|
79
|
+
/**
|
|
80
|
+
* Scan the repo for TEST files and the A-SPEC ids they @implement. Separate from the CPG scan (which
|
|
81
|
+
* excludes tests), so the test↔spec edges actually exist for scoping. Returns repo-relative POSIX
|
|
82
|
+
* paths → the impacted-spec ids they anchor. Pure-ish (fs read only); resilient to unreadable files.
|
|
83
|
+
*/
|
|
84
|
+
export declare function scanTestAnchors(root: string): Record<string, string[]>;
|
|
85
|
+
export declare function computeTestScope(impactedSpecsRaw: string[], testAnchors: Record<string, string[]>, specs: Spec[], coverageGaps?: string[], cfg?: TestScopeThresholds, extras?: TestScopeExtras): TestScope;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as http from 'node:http';
|
|
2
|
+
export interface DashboardOptions {
|
|
3
|
+
root: string;
|
|
4
|
+
port?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface DashboardServerHandle {
|
|
7
|
+
server: http.Server;
|
|
8
|
+
url: string;
|
|
9
|
+
port: number;
|
|
10
|
+
stop: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export interface GraphNode {
|
|
13
|
+
id: string;
|
|
14
|
+
type: 'spec' | 'code';
|
|
15
|
+
kind: string;
|
|
16
|
+
label: string;
|
|
17
|
+
covered?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface GraphEdge {
|
|
20
|
+
from: string;
|
|
21
|
+
to: string;
|
|
22
|
+
rel: 'implements' | 'depends_on' | 'calls' | 'contains' | 'verifies';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Start a lightweight standalone Node.js HTTP server for interactive dashboard & RTM visualization.
|
|
26
|
+
*
|
|
27
|
+
* @implements A-SPEC-215
|
|
28
|
+
* @implements A-SPEC-219
|
|
29
|
+
*/
|
|
30
|
+
export declare function startDashboardServer(options: DashboardOptions): Promise<DashboardServerHandle>;
|
|
31
|
+
/**
|
|
32
|
+
* One end-to-end 6-stage trace row: REQ -> H-SPEC -> A-SPEC -> T-SPEC -> File -> AST Symbol.
|
|
33
|
+
*
|
|
34
|
+
* Every stage is nullable ON PURPOSE. A stage that does not exist in the repository is reported as
|
|
35
|
+
* `null` and named in `missingStages`; it is never back-filled with a synthesized spec id or with a
|
|
36
|
+
* placeholder file/symbol, because a traceability matrix that invents its own evidence cannot be
|
|
37
|
+
* audited against the repository it claims to describe.
|
|
38
|
+
*
|
|
39
|
+
* @implements A-SPEC-219
|
|
40
|
+
*/
|
|
41
|
+
export interface PipelineRow {
|
|
42
|
+
reqId: string;
|
|
43
|
+
reqTitle: string;
|
|
44
|
+
hspecId: string | null;
|
|
45
|
+
aspecId: string | null;
|
|
46
|
+
tspecId: string | null;
|
|
47
|
+
fileId: string | null;
|
|
48
|
+
symbolId: string | null;
|
|
49
|
+
symbolLine: number | null;
|
|
50
|
+
/** How many of the 6 stages are backed by a real artifact (1..6; REQ itself always counts). */
|
|
51
|
+
stagesComplete: number;
|
|
52
|
+
/** Human-readable names of the stages with no artifact, in pipeline order. */
|
|
53
|
+
missingStages: string[];
|
|
54
|
+
/** COVERED only when all 6 stages resolve to a real artifact. */
|
|
55
|
+
status: 'COVERED' | 'UNCOVERED';
|
|
56
|
+
findingsCount: number;
|
|
57
|
+
criticalCount: number;
|
|
58
|
+
/**
|
|
59
|
+
* false when no findings ledger exists. `findingsCount: 0` then means "not scanned", never
|
|
60
|
+
* "scanned and clean", and the audit lens must render the two differently.
|
|
61
|
+
*/
|
|
62
|
+
findingsScanned: boolean;
|
|
63
|
+
mutantCount: number;
|
|
64
|
+
/**
|
|
65
|
+
* `null` — never a number. A mutation SCORE requires executing the test suite once per mutant;
|
|
66
|
+
* this endpoint only generates mutants statically, so it has no basis for a score and says so
|
|
67
|
+
* rather than reporting a constant that reads as a measurement.
|
|
68
|
+
*/
|
|
69
|
+
mutationScore: null;
|
|
70
|
+
mutationScoreMeasured: false;
|
|
71
|
+
}
|
|
72
|
+
export declare function isCanonicalStatus(status: unknown): boolean;
|
|
73
|
+
/** `A-SPEC-219.1` -> `A-SPEC`, `REQ-021` -> `REQ`. */
|
|
74
|
+
export declare function specKindOf(id: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* Build the 6-stage pipeline matrix from the repository's real specs, scanned files and findings.
|
|
77
|
+
*
|
|
78
|
+
* Pure and exported so the truthfulness invariants can be asserted directly, without an HTTP round
|
|
79
|
+
* trip: no row may name an artifact that the inputs do not contain, and no symbol may be dropped.
|
|
80
|
+
*
|
|
81
|
+
* @implements A-SPEC-219
|
|
82
|
+
*/
|
|
83
|
+
export declare function buildPipelineRows(specs: any[], files: any[], allFindings: any[], options?: {
|
|
84
|
+
findingsScanned?: boolean;
|
|
85
|
+
}): PipelineRow[];
|