intentdna 1.7.0 → 1.7.4

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 (47) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +26 -15
  4. package/dist/cli/commands/feedback.d.ts +2 -2
  5. package/dist/cli/commands/feedback.js +5 -5
  6. package/dist/cli/commands/sync.js +8 -5
  7. package/dist/cli/commands/verify.d.ts +32 -0
  8. package/dist/cli/commands/verify.js +173 -6
  9. package/dist/cli/index.js +3 -1
  10. package/dist/compiler/activate.js +11 -6
  11. package/dist/compiler/cascade.d.ts +3 -1
  12. package/dist/compiler/cascade.js +23 -1
  13. package/dist/compiler/compile.js +1 -0
  14. package/dist/compiler/index.d.ts +5 -1
  15. package/dist/compiler/index.js +7 -4
  16. package/dist/compiler/input-resolver.d.ts +8 -1
  17. package/dist/compiler/input-resolver.js +128 -22
  18. package/dist/compiler/provenance.d.ts +8 -0
  19. package/dist/compiler/provenance.js +127 -0
  20. package/dist/governance/index.d.ts +4 -3
  21. package/dist/governance/index.js +3 -4
  22. package/dist/governance/runtime-decision-event.d.ts +85 -0
  23. package/dist/governance/runtime-decision-event.js +231 -0
  24. package/dist/governance/types.d.ts +3 -3
  25. package/dist/governance/types.js +3 -3
  26. package/dist/hooks/cli.js +162 -13
  27. package/dist/hooks/state.d.ts +3 -10
  28. package/dist/hooks/state.js +147 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.js +1 -0
  31. package/dist/mcp/tools-observability.js +3 -3
  32. package/dist/mcp/tools-state.d.ts +1 -1
  33. package/dist/mcp/tools-state.js +17 -7
  34. package/dist/report/kernel-report.d.ts +27 -0
  35. package/dist/report/kernel-report.js +60 -19
  36. package/dist/report/kernel-signals.d.ts +5 -2
  37. package/dist/report/kernel-signals.js +84 -2
  38. package/dist/report/report-package.d.ts +9 -1
  39. package/dist/report/report-package.js +32 -27
  40. package/dist/runtime/claude-sdk.d.ts +9 -4
  41. package/dist/runtime/claude-sdk.js +9 -0
  42. package/dist/runtime/plugin-adapter.d.ts +5 -1
  43. package/dist/runtime/plugin-adapter.js +2 -0
  44. package/dist/schema/types.d.ts +51 -0
  45. package/package.json +1 -1
  46. package/spec/README.md +1 -1
  47. package/spec/schema-spec.md +78 -1
@@ -10,6 +10,21 @@
10
10
  * - attract/repel: same target accumulates, different targets independent
11
11
  * - amplify/suppress: factors multiply (1.5x × 2.0x = 3.0x)
12
12
  */
13
+ const PROTECTED_THRESHOLD_LAYERS = new Set(["species", "enterprise"]);
14
+ function originForDNA(dna) {
15
+ return {
16
+ source_dna_id: dna.id,
17
+ source_layer: dna.type,
18
+ cascade_priority: dna.cascade.priority,
19
+ protected_threshold: PROTECTED_THRESHOLD_LAYERS.has(dna.type),
20
+ };
21
+ }
22
+ function withCodonOrigins(gene, origin) {
23
+ return {
24
+ ...gene,
25
+ codons: gene.codons.map((codon) => codon.type === "threshold" ? { ...codon, origin } : { ...codon }),
26
+ };
27
+ }
13
28
  /**
14
29
  * Normalize workflow/workflows from an IntentDNA into a unified Record.
15
30
  * Validation ensures workflow and workflows are mutually exclusive.
@@ -228,6 +243,7 @@ export function cascadeDNA(layers) {
228
243
  const sorted = [...layers].sort((a, b) => a.cascade.priority - b.cascade.priority);
229
244
  const mergedGenes = {};
230
245
  const geneSourceNs = {}; // track which namespace defined each gene
246
+ const protectedThresholdGenes = new Set();
231
247
  const mergedContexts = {};
232
248
  const mergedRoles = {};
233
249
  const mergedWorkflows = {};
@@ -239,7 +255,12 @@ export function cascadeDNA(layers) {
239
255
  sourceIds.push(dna.id);
240
256
  const ns = dna.namespace;
241
257
  // Merge genes (cross-namespace: additive merge + warning)
242
- for (const [name, gene] of Object.entries(dna.genes)) {
258
+ const origin = originForDNA(dna);
259
+ for (const [name, rawGene] of Object.entries(dna.genes)) {
260
+ const gene = withCodonOrigins(rawGene, origin);
261
+ if (origin.protected_threshold && gene.codons.some((codon) => codon.type === "threshold")) {
262
+ protectedThresholdGenes.add(name);
263
+ }
243
264
  if (mergedGenes[name]) {
244
265
  const existingNs = geneSourceNs[name];
245
266
  if (ns !== existingNs) {
@@ -332,5 +353,6 @@ export function cascadeDNA(layers) {
332
353
  context_sources: contextSources,
333
354
  planning_context: planningContext,
334
355
  verifier_policy: verifierPolicy,
356
+ protected_threshold_genes: protectedThresholdGenes.size > 0 ? [...protectedThresholdGenes].sort() : undefined,
335
357
  };
336
358
  }
@@ -105,6 +105,7 @@ function geneToGates(name, gene) {
105
105
  action: "block",
106
106
  message: `DNA threshold violation: ${codon.condition} (gene: ${name})`,
107
107
  source_gene: name,
108
+ origin: codon.origin,
108
109
  });
109
110
  }
110
111
  if (codon.type === "sense" && codon.response === "escalate_to_human") {
@@ -9,10 +9,12 @@ export { cascadeDNA } from "./cascade.js";
9
9
  export { activateDNA } from "./activate.js";
10
10
  export { compileDNA } from "./compile.js";
11
11
  export { compileWorkflow } from "./workflow.js";
12
+ export { PROVENANCE_LAYERS, PROVENANCE_SCHEMA_VERSION, attachProvenance, buildCascadeLayers, buildConstraintWinners, hashObject, hashString, } from "./provenance.js";
12
13
  export type { CompileWorkflowOptions, CompileWorkflowResult, CompileWorkflowError, } from "./workflow.js";
13
14
  export type { Diagnostic, DiagnosticSeverity } from "./diagnostics.js";
14
15
  export { DNADiagnosticsError, formatDiagnostic, formatDiagnostics } from "./diagnostics.js";
15
- export { assertNoNamespaceCollisions, checkNamespaceCollisions, detectDNAConfigs, expandDNAInputFiles, loadDNAWithDiagnostics, resolveDNAInputs, resolveSpeciesReference, } from "./input-resolver.js";
16
+ export { assertNoNamespaceCollisions, checkNamespaceCollisions, detectDNAConfigs, expandDNAInputFiles, expandDNAInputs, loadDNAWithDiagnostics, resolveDNAInputs, resolveSpeciesReference, } from "./input-resolver.js";
17
+ export type { ExpandedDNAInput, ExpandDNAInputOptions } from "./input-resolver.js";
16
18
  /**
17
19
  * Load and parse a DNA file from disk.
18
20
  */
@@ -20,6 +22,8 @@ export declare function loadDNA(filePath: string): Promise<IntentDNA>;
20
22
  export interface CompileOptions {
21
23
  context?: string;
22
24
  role?: string;
25
+ cwd?: string;
26
+ enterprisePolicyDirs?: string[];
23
27
  /** Additional epigenetic markers from evolution store */
24
28
  epigenetic_markers?: EpigeneticMarker[];
25
29
  }
@@ -8,13 +8,15 @@ import { cascadeDNA } from "./cascade.js";
8
8
  import { activateDNA } from "./activate.js";
9
9
  import { compileDNA } from "./compile.js";
10
10
  import { DNADiagnosticsError, formatDiagnostics } from "./diagnostics.js";
11
- import { loadDNAWithDiagnostics } from "./input-resolver.js";
11
+ import { expandDNAInputs, loadDNAWithDiagnostics } from "./input-resolver.js";
12
+ import { attachProvenance } from "./provenance.js";
12
13
  export { cascadeDNA } from "./cascade.js";
13
14
  export { activateDNA } from "./activate.js";
14
15
  export { compileDNA } from "./compile.js";
15
16
  export { compileWorkflow } from "./workflow.js";
17
+ export { PROVENANCE_LAYERS, PROVENANCE_SCHEMA_VERSION, attachProvenance, buildCascadeLayers, buildConstraintWinners, hashObject, hashString, } from "./provenance.js";
16
18
  export { DNADiagnosticsError, formatDiagnostic, formatDiagnostics } from "./diagnostics.js";
17
- export { assertNoNamespaceCollisions, checkNamespaceCollisions, detectDNAConfigs, expandDNAInputFiles, loadDNAWithDiagnostics, resolveDNAInputs, resolveSpeciesReference, } from "./input-resolver.js";
19
+ export { assertNoNamespaceCollisions, checkNamespaceCollisions, detectDNAConfigs, expandDNAInputFiles, expandDNAInputs, loadDNAWithDiagnostics, resolveDNAInputs, resolveSpeciesReference, } from "./input-resolver.js";
18
20
  /**
19
21
  * Load and parse a DNA file from disk.
20
22
  */
@@ -33,8 +35,9 @@ export async function compileFromFiles(filePaths, contextOrOptions) {
33
35
  const opts = typeof contextOrOptions === "string"
34
36
  ? { context: contextOrOptions }
35
37
  : contextOrOptions ?? {};
38
+ const expanded = await expandDNAInputs(filePaths, { cwd: opts.cwd, enterprisePolicyDirs: opts.enterprisePolicyDirs });
36
39
  const dnas = [];
37
- for (const path of filePaths) {
40
+ for (const path of expanded.files) {
38
41
  dnas.push(await loadDNA(path));
39
42
  }
40
43
  const cascaded = cascadeDNA(dnas);
@@ -43,5 +46,5 @@ export async function compileFromFiles(filePaths, contextOrOptions) {
43
46
  cascaded.epigenetic_markers.push(...opts.epigenetic_markers);
44
47
  }
45
48
  const activated = activateDNA(cascaded, opts.context ?? null, opts.role ?? null);
46
- return compileDNA(activated, cascaded);
49
+ return attachProvenance(compileDNA(activated, cascaded), expanded.provenance);
47
50
  }
@@ -1,4 +1,4 @@
1
- import type { IntentDNA } from "../schema/types.js";
1
+ import type { DNASourceProvenance, IntentDNA } from "../schema/types.js";
2
2
  import type { Diagnostic } from "./diagnostics.js";
3
3
  export interface ResolveDNAInputOptions {
4
4
  cwd?: string;
@@ -14,7 +14,14 @@ export declare function resolveSpeciesReference(ref: string): string | null;
14
14
  export declare function detectDNAConfigs(projectDir?: string): Promise<string[]>;
15
15
  export interface ExpandDNAInputOptions {
16
16
  cwd?: string;
17
+ enterprisePolicyDirs?: string[];
17
18
  }
19
+ export interface ExpandedDNAInput {
20
+ files: string[];
21
+ provenance: DNASourceProvenance[];
22
+ diagnostics: Diagnostic[];
23
+ }
24
+ export declare function expandDNAInputs(files: string[], options?: ExpandDNAInputOptions): Promise<ExpandedDNAInput>;
18
25
  export declare function expandDNAInputFiles(files: string[], options?: ExpandDNAInputOptions): Promise<string[]>;
19
26
  export declare function checkNamespaceCollisions(configPaths: string[]): Promise<Diagnostic[]>;
20
27
  export declare function assertNoNamespaceCollisions(configPaths: string[]): Promise<void>;
@@ -1,3 +1,5 @@
1
+ import { createHash } from "node:crypto";
2
+ import { homedir } from "node:os";
1
3
  import { readdir, readFile, stat } from "node:fs/promises";
2
4
  import { dirname, resolve } from "node:path";
3
5
  import { fileURLToPath } from "node:url";
@@ -57,35 +59,139 @@ export async function detectDNAConfigs(projectDir = process.cwd()) {
57
59
  }
58
60
  return [];
59
61
  }
60
- export async function expandDNAInputFiles(files, options) {
62
+ function fingerprint(raw) {
63
+ return `sha256:${createHash("sha256").update(raw, "utf-8").digest("hex")}`;
64
+ }
65
+ function enterprisePolicyCandidates(name, cwd, options) {
66
+ const configuredDirs = [
67
+ ...(process.env.INTENTDNA_ENTERPRISE_POLICY_DIR ? [process.env.INTENTDNA_ENTERPRISE_POLICY_DIR] : []),
68
+ ...(options?.enterprisePolicyDirs ?? []),
69
+ ];
70
+ const dirs = [
71
+ ...configuredDirs.map((dir) => ({ dir, trust: "admin_shared" })),
72
+ { dir: resolve(cwd, ".dna", "policies", "enterprise"), trust: "project_local" },
73
+ { dir: resolve(homedir(), ".intentdna", "policies", "enterprise"), trust: "user_local" },
74
+ ];
75
+ const names = [`${name}.dna.yaml`, `${name}.dna.yml`, `${name}.dna.json`];
76
+ return dirs.flatMap(({ dir, trust }) => names.map((file) => ({ path: resolve(dir, file), trust })));
77
+ }
78
+ async function resolveEnterpriseReference(ref, cwd, options) {
79
+ if (!ref.startsWith("enterprise:"))
80
+ return {};
81
+ const name = ref.slice("enterprise:".length);
82
+ for (const candidate of enterprisePolicyCandidates(name, cwd, options)) {
83
+ if (await fileExists(candidate.path))
84
+ return candidate;
85
+ }
86
+ return {};
87
+ }
88
+ function resolveFileReference(ref, fromFile) {
89
+ if (!ref.startsWith("file:"))
90
+ return {};
91
+ const raw = ref.slice("file:".length);
92
+ if (!raw)
93
+ return {};
94
+ return { path: resolve(dirname(fromFile), raw), trust: "explicit_file" };
95
+ }
96
+ function sourceTrustForInput(file, ref, cwd) {
97
+ if (ref.startsWith("species:"))
98
+ return "builtin";
99
+ if (ref.startsWith("enterprise:"))
100
+ return file.includes(`${resolve(cwd, ".dna", "policies", "enterprise")}`) ? "project_local" : "admin_shared";
101
+ if (ref.startsWith("file:"))
102
+ return "explicit_file";
103
+ return "input";
104
+ }
105
+ async function readDNAWithRaw(path) {
106
+ const raw = await readFile(path, "utf-8");
107
+ return { raw, dna: parseDNAContent(path, raw) };
108
+ }
109
+ export async function expandDNAInputs(files, options) {
61
110
  const cwd = options?.cwd ?? process.cwd();
62
- const expanded = [];
111
+ const ordered = [];
63
112
  const seen = new Set();
64
- const add = (path, position) => {
65
- if (seen.has(path))
66
- return;
67
- seen.add(path);
68
- if (position === "front")
69
- expanded.unshift(path);
70
- else
71
- expanded.push(path);
72
- };
73
- for (const file of files) {
113
+ const diagnostics = [];
114
+ const provenance = new Map();
115
+ const stack = [];
116
+ const visit = async (file, ref, inheritedBy, trust) => {
74
117
  const abs = resolve(cwd, file);
75
- add(abs, "back");
118
+ if (stack.includes(abs)) {
119
+ diagnostics.push({
120
+ severity: "error",
121
+ code: "inheritance_cycle",
122
+ message: `DNA inheritance cycle detected: ${[...stack, abs].join(" -> ")}`,
123
+ file: abs,
124
+ });
125
+ return;
126
+ }
127
+ if (seen.has(abs))
128
+ return;
129
+ let loaded;
76
130
  try {
77
- const dna = await parseDNAFile(abs);
78
- for (const ref of dna.cascade?.inherits ?? []) {
79
- const speciesPath = resolveSpeciesReference(ref);
80
- if (speciesPath)
81
- add(speciesPath, "front");
82
- }
131
+ loaded = await readDNAWithRaw(abs);
83
132
  }
84
- catch {
85
- // Validation/loading reports the concrete parse error later.
133
+ catch (error) {
134
+ diagnostics.push({
135
+ severity: "error",
136
+ code: "inheritance_unresolved",
137
+ message: `Unable to resolve inherited DNA reference '${ref}': ${error instanceof Error ? error.message : String(error)}`,
138
+ file: inheritedBy ?? abs,
139
+ });
140
+ return;
86
141
  }
142
+ stack.push(abs);
143
+ for (const inheritRef of loaded.dna.cascade?.inherits ?? []) {
144
+ const speciesPath = resolveSpeciesReference(inheritRef);
145
+ if (speciesPath) {
146
+ await visit(speciesPath, inheritRef, abs, "builtin");
147
+ continue;
148
+ }
149
+ const fileRef = resolveFileReference(inheritRef, abs);
150
+ if (fileRef.path) {
151
+ await visit(fileRef.path, inheritRef, abs, fileRef.trust);
152
+ continue;
153
+ }
154
+ const enterpriseRef = await resolveEnterpriseReference(inheritRef, cwd, options);
155
+ if (enterpriseRef.path) {
156
+ await visit(enterpriseRef.path, inheritRef, abs, enterpriseRef.trust);
157
+ continue;
158
+ }
159
+ if (inheritRef.startsWith("enterprise:") || inheritRef.startsWith("file:")) {
160
+ diagnostics.push({
161
+ severity: "error",
162
+ code: "inheritance_unresolved",
163
+ message: `Unable to resolve inherited DNA reference '${inheritRef}'`,
164
+ file: abs,
165
+ path: "cascade.inherits",
166
+ });
167
+ }
168
+ }
169
+ stack.pop();
170
+ seen.add(abs);
171
+ ordered.push(abs);
172
+ provenance.set(abs, {
173
+ source_id: loaded.dna.id,
174
+ source_ref: ref,
175
+ resolved_path: abs,
176
+ fingerprint: fingerprint(loaded.raw),
177
+ type: loaded.dna.type,
178
+ cascade_priority: loaded.dna.cascade.priority,
179
+ version: loaded.dna.version,
180
+ trust: trust ?? sourceTrustForInput(abs, ref, cwd),
181
+ inherited_by: inheritedBy,
182
+ genes: Object.keys(loaded.dna.genes ?? {}).sort(),
183
+ });
184
+ };
185
+ for (const file of files) {
186
+ await visit(resolve(cwd, file), file, undefined, "input");
187
+ }
188
+ if (hasDiagnosticErrors(diagnostics)) {
189
+ throw new DNADiagnosticsError("DNA inheritance resolution failed", diagnostics);
87
190
  }
88
- return expanded;
191
+ return { files: ordered, provenance: ordered.map((file) => provenance.get(file)).filter(Boolean), diagnostics };
192
+ }
193
+ export async function expandDNAInputFiles(files, options) {
194
+ return (await expandDNAInputs(files, options)).files;
89
195
  }
90
196
  export async function checkNamespaceCollisions(configPaths) {
91
197
  const diagnostics = [];
@@ -0,0 +1,8 @@
1
+ import type { CascadeLayerProvenance, ConstraintIR, ConstraintProvenance, DNASourceProvenance, ProvenanceCascadeLayerName } from "../schema/types.js";
2
+ export declare const PROVENANCE_SCHEMA_VERSION: "intentdna.provenance.v1.7.2";
3
+ export declare const PROVENANCE_LAYERS: readonly ProvenanceCascadeLayerName[];
4
+ export declare function hashString(content: string): string;
5
+ export declare function hashObject(value: unknown): string;
6
+ export declare function buildCascadeLayers(sources: DNASourceProvenance[]): Record<ProvenanceCascadeLayerName, CascadeLayerProvenance>;
7
+ export declare function buildConstraintWinners(ir: ConstraintIR, sources: DNASourceProvenance[]): ConstraintProvenance[];
8
+ export declare function attachProvenance(ir: ConstraintIR, sources: DNASourceProvenance[]): ConstraintIR;
@@ -0,0 +1,127 @@
1
+ import { createHash } from "node:crypto";
2
+ export const PROVENANCE_SCHEMA_VERSION = "intentdna.provenance.v1.7.2";
3
+ export const PROVENANCE_LAYERS = [
4
+ "species",
5
+ "enterprise",
6
+ "project",
7
+ "personal",
8
+ "role",
9
+ "context",
10
+ "task",
11
+ ];
12
+ function stable(value) {
13
+ if (Array.isArray(value))
14
+ return `[${value.map(stable).join(",")}]`;
15
+ if (value && typeof value === "object") {
16
+ return `{${Object.entries(value)
17
+ .filter(([key]) => key !== "compiled_ir_hash" && key !== "provenance" && key !== "compiled_at")
18
+ .sort(([a], [b]) => a.localeCompare(b))
19
+ .map(([key, entry]) => `${JSON.stringify(key)}:${stable(entry)}`)
20
+ .join(",")}}`;
21
+ }
22
+ return JSON.stringify(value);
23
+ }
24
+ export function hashString(content) {
25
+ return `sha256:${createHash("sha256").update(content, "utf-8").digest("hex")}`;
26
+ }
27
+ export function hashObject(value) {
28
+ return hashString(stable(value));
29
+ }
30
+ function placeholderLayer(layer) {
31
+ return {
32
+ layer,
33
+ source_id: "unknown",
34
+ source_ref: "unknown",
35
+ fingerprint: "unknown",
36
+ status: "unknown",
37
+ };
38
+ }
39
+ export function buildCascadeLayers(sources) {
40
+ const layers = Object.fromEntries(PROVENANCE_LAYERS.map((layer) => [layer, placeholderLayer(layer)]));
41
+ for (const layer of PROVENANCE_LAYERS) {
42
+ const layerSources = sources.filter((source) => source.type === layer);
43
+ if (layerSources.length === 0)
44
+ continue;
45
+ const fingerprint = hashObject(layerSources.map((source) => ({
46
+ source_id: source.source_id,
47
+ source_ref: source.source_ref,
48
+ fingerprint: source.fingerprint,
49
+ cascade_priority: source.cascade_priority,
50
+ })));
51
+ layers[layer] = {
52
+ layer,
53
+ source_id: layerSources.map((source) => source.source_id).join("+"),
54
+ source_ref: layerSources.map((source) => source.source_ref).join(","),
55
+ fingerprint,
56
+ status: "active",
57
+ sources: layerSources.map((source) => source.source_id),
58
+ };
59
+ }
60
+ return layers;
61
+ }
62
+ function sourceForGene(sources, geneId) {
63
+ return [...sources].reverse().find((source) => source.genes?.includes(geneId));
64
+ }
65
+ function constraintId(kind, sourceGene, discriminator) {
66
+ return `${kind}:${sourceGene || "unknown"}:${hashString(discriminator).slice("sha256:".length, "sha256:".length + 12)}`;
67
+ }
68
+ function actionFor(kind, constraint) {
69
+ if (constraint.action === "escalate")
70
+ return "escalate";
71
+ if (constraint.action === "warn")
72
+ return "warn";
73
+ if (kind === "post_validator")
74
+ return "validate";
75
+ return "block";
76
+ }
77
+ function constraintFrom(kind, constraint, sources) {
78
+ const sourceGene = constraint.source_gene ?? "unknown";
79
+ const originSource = constraint.origin
80
+ ? sources.find((source) => source.source_id === constraint.origin?.source_dna_id)
81
+ : undefined;
82
+ const source = originSource ?? sourceForGene(sources, sourceGene);
83
+ const discriminator = constraint.condition ?? constraint.target ?? constraint.check ?? stable(constraint);
84
+ const sourceLayer = (constraint.origin?.source_layer ?? source?.type);
85
+ const sourceDnaId = constraint.origin?.source_dna_id ?? source?.source_id;
86
+ return {
87
+ constraint_id: constraintId(kind, sourceGene, discriminator),
88
+ source_layer: sourceLayer ?? "unknown",
89
+ source_dna_id: sourceDnaId ?? "unknown",
90
+ gene_id: sourceGene,
91
+ codon_type: kind === "tool_filter" ? "repel" : kind === "post_validator" ? "sense" : "threshold",
92
+ action: actionFor(kind, constraint),
93
+ provenance_reason: sourceDnaId && sourceLayer
94
+ ? `${kind} '${discriminator}' compiled from ${sourceLayer} DNA '${sourceDnaId}'`
95
+ : `${kind} '${discriminator}' has no resolved source DNA`,
96
+ };
97
+ }
98
+ export function buildConstraintWinners(ir, sources) {
99
+ return [
100
+ ...ir.pre_execution_gates.map((gate) => constraintFrom("pre_gate", gate, sources)),
101
+ ...ir.tool_filters.map((filter) => constraintFrom("tool_filter", filter, sources)),
102
+ ...ir.post_execution_validators.map((validator) => constraintFrom("post_validator", validator, sources)),
103
+ ];
104
+ }
105
+ export function attachProvenance(ir, sources) {
106
+ const baseIR = {
107
+ ...ir,
108
+ provenance: undefined,
109
+ compiled_ir_hash: undefined,
110
+ };
111
+ const compiledHash = hashObject(baseIR);
112
+ const enterprise = sources.find((source) => source.type === "enterprise");
113
+ const manifest = {
114
+ schema_version: PROVENANCE_SCHEMA_VERSION,
115
+ policy_bundle_id: enterprise?.source_id ?? "unknown",
116
+ policy_bundle_version: enterprise?.version ?? "unknown",
117
+ sources,
118
+ cascade_layers: buildCascadeLayers(sources),
119
+ constraint_winners: buildConstraintWinners(ir, sources),
120
+ compiled_ir_hash: compiledHash,
121
+ };
122
+ return {
123
+ ...ir,
124
+ compiled_ir_hash: compiledHash,
125
+ provenance: manifest,
126
+ };
127
+ }
@@ -1,7 +1,8 @@
1
1
  /**
2
- * Intent DNA — Remote Governance Module
2
+ * Intent DNA — Governance Module
3
3
  *
4
- * Architecture reservation for Phase 7 enterprise governance.
5
- * Currently exports type definitions only — no runtime implementation.
4
+ * Exports the v1.7.1 enterprise evidence contract plus reserved remote governance interfaces.
6
5
  */
7
6
  export type { AuditReport, RemoteDNAPolicy, PolicyContent, PolicyScope, PolicyUpdate, GovernanceConfig, GovernanceClient, GovernanceResponse, GovernanceSubscription, } from "./types.js";
7
+ export { CASCADE_LAYER_NAMES, RUNTIME_DECISION_EVENT_SCHEMA_VERSION, validateRuntimeDecisionEvent, } from "./runtime-decision-event.js";
8
+ export type { CascadeDecisionTrace, CascadeLayerFingerprint, CascadeLayerName, CascadeLayers, EnforcementPoint, ExplicitPlaceholder, HarnessRuntimeContext, PolicyBundle, RuntimeDecision, RuntimeDecisionEvent, RuntimeDecisionEventValidationResult, RuntimeEvidenceRef, WinningConstraint, } from "./runtime-decision-event.js";
@@ -1,7 +1,6 @@
1
1
  /**
2
- * Intent DNA — Remote Governance Module
2
+ * Intent DNA — Governance Module
3
3
  *
4
- * Architecture reservation for Phase 7 enterprise governance.
5
- * Currently exports type definitions only — no runtime implementation.
4
+ * Exports the v1.7.1 enterprise evidence contract plus reserved remote governance interfaces.
6
5
  */
7
- export {};
6
+ export { CASCADE_LAYER_NAMES, RUNTIME_DECISION_EVENT_SCHEMA_VERSION, validateRuntimeDecisionEvent, } from "./runtime-decision-event.js";
@@ -0,0 +1,85 @@
1
+ export declare const RUNTIME_DECISION_EVENT_SCHEMA_VERSION: "intentdna.runtime_decision_event.v1.7.1";
2
+ export declare const CASCADE_LAYER_NAMES: readonly ["species", "enterprise", "project", "personal", "role", "context", "task"];
3
+ export type ExplicitPlaceholder = "unknown" | "unsupported";
4
+ export type RuntimeDecision = "allow" | "warn" | "block" | "escalate" | "validate";
5
+ export type EnforcementPoint = "hook" | "sdk" | "ci" | "plugin_runtime" | "mcp_external_write" | ExplicitPlaceholder;
6
+ export type CascadeLayerName = typeof CASCADE_LAYER_NAMES[number];
7
+ export type RuntimeEvidenceRefType = "trace" | "audit" | "artifact" | "verifier" | "handoff" | "legacy" | ExplicitPlaceholder;
8
+ export interface PolicyBundle {
9
+ policy_bundle_id: string;
10
+ policy_bundle_version: string;
11
+ source_ref: string;
12
+ fingerprint: string;
13
+ }
14
+ export interface CascadeLayerFingerprint {
15
+ layer: CascadeLayerName;
16
+ source_id: string;
17
+ source_ref: string;
18
+ fingerprint: string;
19
+ status: "active" | ExplicitPlaceholder;
20
+ }
21
+ export type CascadeLayers = Record<CascadeLayerName, CascadeLayerFingerprint>;
22
+ export interface WinningConstraint {
23
+ constraint_id: string;
24
+ source_layer: CascadeLayerName | ExplicitPlaceholder;
25
+ source_dna_id: string;
26
+ gene_id: string;
27
+ codon_type: string;
28
+ action: RuntimeDecision;
29
+ provenance_reason: string;
30
+ }
31
+ export interface CascadeDecisionTrace {
32
+ cascade_layers: CascadeLayers;
33
+ winning_constraint: WinningConstraint;
34
+ compiled_ir_hash: string;
35
+ decision_reason: string;
36
+ }
37
+ export interface RuntimeEvidenceRef {
38
+ type: RuntimeEvidenceRefType;
39
+ ref: string;
40
+ }
41
+ export interface HarnessRuntimeContext {
42
+ agent_id: string;
43
+ agent_role: string;
44
+ agent_type: string;
45
+ session_agent: string;
46
+ harness_adapter: string;
47
+ runtime: string;
48
+ }
49
+ export interface RuntimeDecisionEvent {
50
+ schema_version: typeof RUNTIME_DECISION_EVENT_SCHEMA_VERSION;
51
+ event_id: string;
52
+ timestamp: string;
53
+ org_id: string;
54
+ team_id: string;
55
+ user_id: string;
56
+ project_id: string;
57
+ agent_id: string;
58
+ agent_role: string;
59
+ agent_type: string;
60
+ session_agent: string;
61
+ harness_adapter: string;
62
+ runtime: string;
63
+ policy_bundle_id: string;
64
+ policy_bundle_version: string;
65
+ cascade_layers: CascadeLayers;
66
+ winning_constraint: WinningConstraint;
67
+ compiled_ir_hash: string;
68
+ decision: RuntimeDecision;
69
+ decision_reason: string;
70
+ enforcement_point: EnforcementPoint;
71
+ harness_runtime_context: HarnessRuntimeContext;
72
+ session_id: string;
73
+ run_id: string;
74
+ step_id: string;
75
+ tool_name: string;
76
+ action_kind: string;
77
+ resource_ref: string;
78
+ evidence_refs: RuntimeEvidenceRef[];
79
+ }
80
+ export interface RuntimeDecisionEventValidationResult {
81
+ valid: boolean;
82
+ classification: "enterprise_evidence" | "legacy_diagnostic";
83
+ errors: string[];
84
+ }
85
+ export declare function validateRuntimeDecisionEvent(event: unknown): RuntimeDecisionEventValidationResult;