intentdna 1.7.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/LICENSE +201 -0
  4. package/README.md +143 -194
  5. package/dist/assets/candidates.d.ts +124 -0
  6. package/dist/assets/candidates.js +1249 -0
  7. package/dist/assets/catalog.d.ts +101 -0
  8. package/dist/assets/catalog.js +311 -0
  9. package/dist/assets/evidence.d.ts +93 -0
  10. package/dist/assets/evidence.js +391 -0
  11. package/dist/assets/index.d.ts +4 -0
  12. package/dist/assets/index.js +4 -0
  13. package/dist/assets/metadata.d.ts +19 -0
  14. package/dist/assets/metadata.js +227 -0
  15. package/dist/cli/commands/assets.d.ts +65 -0
  16. package/dist/cli/commands/assets.js +2871 -0
  17. package/dist/cli/commands/auth.d.ts +322 -0
  18. package/dist/cli/commands/auth.js +1592 -0
  19. package/dist/cli/commands/cloud-auth-guidance.d.ts +2 -0
  20. package/dist/cli/commands/cloud-auth-guidance.js +4 -0
  21. package/dist/cli/commands/cloud.d.ts +1359 -0
  22. package/dist/cli/commands/cloud.js +8364 -0
  23. package/dist/cli/commands/evolve.js +18 -2
  24. package/dist/cli/commands/generate.js +25 -2
  25. package/dist/cli/commands/guard.d.ts +1 -1
  26. package/dist/cli/commands/guard.js +1 -1
  27. package/dist/cli/commands/guide.d.ts +15 -0
  28. package/dist/cli/commands/guide.js +1747 -0
  29. package/dist/cli/commands/init.d.ts +12 -0
  30. package/dist/cli/commands/init.js +95 -60
  31. package/dist/cli/commands/org.d.ts +16 -0
  32. package/dist/cli/commands/org.js +2393 -0
  33. package/dist/cli/commands/release.d.ts +59 -0
  34. package/dist/cli/commands/release.js +716 -0
  35. package/dist/cli/commands/report.d.ts +82 -0
  36. package/dist/cli/commands/report.js +1516 -0
  37. package/dist/cli/commands/run.d.ts +6 -1
  38. package/dist/cli/commands/run.js +95 -26
  39. package/dist/cli/commands/sync.d.ts +8 -1
  40. package/dist/cli/commands/sync.js +436 -141
  41. package/dist/cli/commands/templates.d.ts +64 -0
  42. package/dist/cli/commands/templates.js +2151 -1
  43. package/dist/cli/commands/workflow.d.ts +26 -0
  44. package/dist/cli/commands/workflow.js +3053 -0
  45. package/dist/cli/index.js +719 -42
  46. package/dist/compiler/cascade.js +4 -9
  47. package/dist/compiler/compile.js +1 -0
  48. package/dist/governance/evidence-capture-attribution.d.ts +12 -0
  49. package/dist/governance/evidence-capture-attribution.js +46 -0
  50. package/dist/governance/index.d.ts +2 -0
  51. package/dist/governance/index.js +1 -0
  52. package/dist/hooks/cli.d.ts +6 -0
  53. package/dist/hooks/cli.js +168 -12
  54. package/dist/hooks/enforce.d.ts +1 -0
  55. package/dist/hooks/protocol.d.ts +1 -1
  56. package/dist/hooks/protocol.js +1 -1
  57. package/dist/hooks/state.d.ts +41 -0
  58. package/dist/hooks/state.js +126 -2
  59. package/dist/index.d.ts +3 -0
  60. package/dist/index.js +3 -0
  61. package/dist/mcp/tools-state.js +2 -0
  62. package/dist/organization/index.d.ts +121 -0
  63. package/dist/organization/index.js +413 -0
  64. package/dist/runtime/claude-sync-target.d.ts +49 -0
  65. package/dist/runtime/claude-sync-target.js +280 -0
  66. package/dist/runtime/codex-adapter.d.ts +254 -0
  67. package/dist/runtime/codex-adapter.js +1204 -0
  68. package/dist/runtime/codex-sync-target.d.ts +33 -0
  69. package/dist/runtime/codex-sync-target.js +241 -0
  70. package/dist/runtime/index.d.ts +8 -0
  71. package/dist/runtime/index.js +4 -0
  72. package/dist/runtime/output-artifact-registry.d.ts +1 -1
  73. package/dist/runtime/output-artifact-registry.js +2 -0
  74. package/dist/runtime/settings-adapter.d.ts +1 -1
  75. package/dist/runtime/settings-adapter.js +1 -1
  76. package/dist/runtime/skill-adapter.d.ts +5 -1
  77. package/dist/runtime/skill-adapter.js +120 -34
  78. package/dist/runtime/sync-artifact-registry.d.ts +99 -0
  79. package/dist/runtime/sync-artifact-registry.js +194 -0
  80. package/dist/runtime/sync-target-plan.d.ts +45 -0
  81. package/dist/runtime/sync-target-plan.js +19 -0
  82. package/dist/schema/controller-registry.d.ts +8 -1
  83. package/dist/schema/controller-registry.js +8 -0
  84. package/dist/schema/types.d.ts +35 -23
  85. package/dist/schema/types.js +10 -1
  86. package/dist/schema/validate.js +22 -22
  87. package/dist/schema/validators/controllers.js +38 -20
  88. package/dist/schema/workflow-authoring-contract.d.ts +29 -0
  89. package/dist/schema/workflow-authoring-contract.js +109 -0
  90. package/dist/schema/yaml-parser.js +18 -0
  91. package/dist/templates/api-backend.dna.yaml +19 -0
  92. package/dist/templates/brainstorming-first.dna.yaml +19 -0
  93. package/dist/templates/code-cleanup.dna.yaml +19 -0
  94. package/dist/templates/code-review-pipeline.dna.yaml +18 -0
  95. package/dist/templates/documentation-writer.dna.yaml +19 -0
  96. package/dist/templates/flutter-behavior-lock.dna.yaml +19 -0
  97. package/dist/templates/flutter-refactoring-rescue.dna.yaml +19 -0
  98. package/dist/templates/flutter-rewrite-diagnosis-review.dna.yaml +210 -0
  99. package/dist/templates/flutter-rewrite-fix-review-loop.dna.yaml +260 -0
  100. package/dist/templates/flutter-rewrite-new.dna.yaml +506 -0
  101. package/dist/templates/flutter-rewrite.dna.yaml +20 -0
  102. package/dist/templates/frontend-quality.dna.yaml +19 -0
  103. package/dist/templates/full-pipeline.dna.yaml +20 -0
  104. package/dist/templates/marketplace.d.ts +92 -0
  105. package/dist/templates/marketplace.js +502 -0
  106. package/dist/templates/metadata.d.ts +25 -0
  107. package/dist/templates/metadata.js +136 -3
  108. package/dist/templates/mobile-dev.dna.yaml +19 -0
  109. package/dist/templates/multi-agent-handoff-coordination.dna.yaml +156 -0
  110. package/dist/templates/multi-perspective-review.dna.yaml +19 -0
  111. package/dist/templates/persistent-executor.dna.yaml +19 -0
  112. package/dist/templates/qa-loop.dna.yaml +18 -0
  113. package/dist/templates/release-evidence-gate.dna.yaml +131 -0
  114. package/dist/templates/requirements-gate.dna.yaml +19 -0
  115. package/dist/templates/research-orchestration.dna.yaml +19 -0
  116. package/dist/templates/root-cause-analysis.dna.yaml +19 -0
  117. package/dist/templates/safe-refactoring.dna.yaml +321 -0
  118. package/dist/templates/secure-dev.dna.yaml +19 -0
  119. package/dist/templates/subagent-parallel.dna.yaml +19 -0
  120. package/dist/templates/systematic-debugging.dna.yaml +19 -0
  121. package/dist/templates/tdd-strict.dna.yaml +19 -0
  122. package/dist/templates/ui-visual-regression-qa.dna.yaml +133 -0
  123. package/dist/templates/workflow-author.dna.yaml +302 -0
  124. package/dist/templates/workflow-blocked-scope-triage.dna.yaml +242 -0
  125. package/dist/templates/workflow-completion-audit.dna.yaml +254 -0
  126. package/dist/templates/workflow-cross-boundary-resource-approval.dna.yaml +249 -0
  127. package/dist/templates/workflow-evidence-review.dna.yaml +198 -0
  128. package/dist/templates/workflow-module-inventory.dna.yaml +257 -0
  129. package/dist/templates/workflow-runtime-smoke-review.dna.yaml +252 -0
  130. package/dist/templates/workflow-verification-command-routing.dna.yaml +278 -0
  131. package/dist/workflow/authoring-packet.d.ts +67 -0
  132. package/dist/workflow/authoring-packet.js +218 -0
  133. package/dist/workflow/draft.d.ts +159 -0
  134. package/dist/workflow/draft.js +800 -0
  135. package/dist/workflow/index.d.ts +3 -0
  136. package/dist/workflow/index.js +3 -0
  137. package/dist/workflow/suggestion-review.d.ts +65 -0
  138. package/dist/workflow/suggestion-review.js +245 -0
  139. package/package.json +1 -1
  140. package/spec/README.md +15 -48
  141. package/spec/codex-adapter-contract.md +176 -0
  142. package/spec/sync-target-plan.md +158 -0
  143. package/spec/workflow-capability-ir.md +153 -0
  144. package/spec/agent-dispatch-fix.md +0 -116
  145. package/spec/control-plane-convergence-handoff-2026-04-24.md +0 -432
  146. package/spec/flutter-rewrite-template-optimization.md +0 -301
  147. package/spec/foundation-hardening.md +0 -178
  148. package/spec/hooks-infra-harness-hardening.md +0 -741
  149. package/spec/multi-config.md +0 -172
  150. package/spec/parallel-isolation.md +0 -268
  151. package/spec/template-version-namespace-fix.md +0 -653
  152. package/spec/workflow-pipeline.md +0 -101
@@ -109,15 +109,10 @@ function prefixRecordKeys(record, ns) {
109
109
  function prefixController(controller, ns) {
110
110
  return {
111
111
  ...controller,
112
- diagnosis_workflow: `${ns}_${controller.diagnosis_workflow}`,
113
- fix_workflow: `${ns}_${controller.fix_workflow}`,
114
- roles: {
115
- analyzer: `${ns}_${controller.roles.analyzer}`,
116
- analysis_reviewer: `${ns}_${controller.roles.analysis_reviewer}`,
117
- surgeon: `${ns}_${controller.roles.surgeon}`,
118
- fix_reviewer: `${ns}_${controller.roles.fix_reviewer}`,
119
- test_runner: `${ns}_${controller.roles.test_runner}`,
120
- },
112
+ workflow: controller.workflow ? `${ns}_${controller.workflow}` : undefined,
113
+ diagnosis_workflow: controller.diagnosis_workflow ? `${ns}_${controller.diagnosis_workflow}` : undefined,
114
+ fix_workflow: controller.fix_workflow ? `${ns}_${controller.fix_workflow}` : undefined,
115
+ roles: Object.fromEntries(Object.entries(controller.roles).map(([roleKey, roleName]) => [roleKey, `${ns}_${roleName}`])),
121
116
  };
122
117
  }
123
118
  function prefixLegibilityAssets(map, ns) {
@@ -384,6 +384,7 @@ export function compileDNA(activated, cascaded) {
384
384
  workflowsIR.push({
385
385
  workflow_name: wfKey,
386
386
  namespace,
387
+ step_ids: (wf.steps ?? []).map((step) => step.id),
387
388
  step_checkpoints: wfStepCheckpoints,
388
389
  active_roles: activeRoles,
389
390
  handoff_chain: handoffChain,
@@ -0,0 +1,12 @@
1
+ import type { ConstraintIR } from "../schema/types.js";
2
+ export interface EvidenceCaptureAttributionHint {
3
+ workflowAsset?: string;
4
+ workflowId?: string;
5
+ stepId?: string;
6
+ }
7
+ export interface TrustedEvidenceCaptureAttribution {
8
+ workflowAsset: string;
9
+ workflowId: string;
10
+ stepId: string;
11
+ }
12
+ export declare function trustedEvidenceCaptureAttribution(ir: ConstraintIR, hint: EvidenceCaptureAttributionHint): TrustedEvidenceCaptureAttribution;
@@ -0,0 +1,46 @@
1
+ const UNKNOWN_ATTRIBUTION = "unknown";
2
+ function canonicalWorkflowAsset(ir) {
3
+ const sourceIds = [...new Set(ir.source_dna_ids)]
4
+ .filter((sourceId) => sourceId.length > 0)
5
+ .filter((sourceId) => !sourceId.startsWith("species:"))
6
+ .filter((sourceId) => !sourceId.startsWith("enterprise:"));
7
+ return sourceIds.length === 1 ? sourceIds[0] : undefined;
8
+ }
9
+ function attributedWorkflow(ir, workflowId) {
10
+ if (workflowId) {
11
+ return ir.workflows_ir?.find((workflow) => workflow.workflow_name === workflowId);
12
+ }
13
+ return ir.workflows_ir?.length === 1 ? ir.workflows_ir[0] : undefined;
14
+ }
15
+ function workflowStepIds(ir, workflow) {
16
+ return new Set([
17
+ ...(workflow.step_ids ?? []),
18
+ ...workflow.step_checkpoints.map((checkpoint) => checkpoint.step_id),
19
+ ...workflow.handoff_chain.map((handoff) => handoff.step_id),
20
+ ...(workflow.step_enforce_rules ?? []).map((rule) => rule.step_id),
21
+ ...(ir.verifier_specs ?? [])
22
+ .filter((spec) => spec.workflow_name === workflow.workflow_name)
23
+ .map((spec) => spec.step_id)
24
+ .filter((stepId) => typeof stepId === "string"),
25
+ ]);
26
+ }
27
+ export function trustedEvidenceCaptureAttribution(ir, hint) {
28
+ const workflow = attributedWorkflow(ir, hint.workflowId);
29
+ const invalidExplicitWorkflow = Boolean(hint.workflowId && !workflow);
30
+ if (invalidExplicitWorkflow) {
31
+ return {
32
+ workflowAsset: UNKNOWN_ATTRIBUTION,
33
+ workflowId: UNKNOWN_ATTRIBUTION,
34
+ stepId: UNKNOWN_ATTRIBUTION,
35
+ };
36
+ }
37
+ const canonicalAsset = canonicalWorkflowAsset(ir);
38
+ const workflowAsset = canonicalAsset
39
+ ? hint.workflowAsset === canonicalAsset ? hint.workflowAsset : canonicalAsset
40
+ : UNKNOWN_ATTRIBUTION;
41
+ const workflowId = workflow?.workflow_name ?? UNKNOWN_ATTRIBUTION;
42
+ const stepId = workflow && hint.stepId && workflowStepIds(ir, workflow).has(hint.stepId)
43
+ ? hint.stepId
44
+ : UNKNOWN_ATTRIBUTION;
45
+ return { workflowAsset, workflowId, stepId };
46
+ }
@@ -5,4 +5,6 @@
5
5
  */
6
6
  export type { AuditReport, RemoteDNAPolicy, PolicyContent, PolicyScope, PolicyUpdate, GovernanceConfig, GovernanceClient, GovernanceResponse, GovernanceSubscription, } from "./types.js";
7
7
  export { CASCADE_LAYER_NAMES, RUNTIME_DECISION_EVENT_SCHEMA_VERSION, validateRuntimeDecisionEvent, } from "./runtime-decision-event.js";
8
+ export { trustedEvidenceCaptureAttribution } from "./evidence-capture-attribution.js";
9
+ export type { EvidenceCaptureAttributionHint, TrustedEvidenceCaptureAttribution, } from "./evidence-capture-attribution.js";
8
10
  export type { CascadeDecisionTrace, CascadeLayerFingerprint, CascadeLayerName, CascadeLayers, EnforcementPoint, ExplicitPlaceholder, HarnessRuntimeContext, PolicyBundle, RuntimeDecision, RuntimeDecisionEvent, RuntimeDecisionEventValidationResult, RuntimeEvidenceRef, WinningConstraint, } from "./runtime-decision-event.js";
@@ -4,3 +4,4 @@
4
4
  * Exports the v1.7.1 enterprise evidence contract plus reserved remote governance interfaces.
5
5
  */
6
6
  export { CASCADE_LAYER_NAMES, RUNTIME_DECISION_EVENT_SCHEMA_VERSION, validateRuntimeDecisionEvent, } from "./runtime-decision-event.js";
7
+ export { trustedEvidenceCaptureAttribution } from "./evidence-capture-attribution.js";
@@ -47,7 +47,11 @@ export interface RunHookEventOptions {
47
47
  sessionId?: string;
48
48
  roles?: Record<string, RoleDef>;
49
49
  }
50
+ export declare function normalizeHookOutputForEvent(output: HookOutput, event: HookEvent): HookOutput;
50
51
  export declare function runHookEvent(options: RunHookEventOptions): Promise<HookOutput>;
52
+ export declare function codexHookEventForInput(rawInput: Record<string, unknown>, args: string[]): unknown;
53
+ declare function inferWorkflowAssetFromIr(ir: ConstraintIR, workflowId?: string): string | undefined;
54
+ declare function runCodexHookWithLoadedIr(rawInput: Record<string, unknown>, projectDir: string, args: string[], ir: ConstraintIR): Promise<import("../runtime/codex-adapter.js").CodexHookRunnerResult>;
51
55
  declare function recordProducedArtifacts(projectDir: string, ir: ConstraintIR, wfState: {
52
56
  workflow: string;
53
57
  current_step: string;
@@ -86,6 +90,8 @@ declare function finalizeAndResolveArtifactsForHook(projectDir: string, ir: Cons
86
90
  export declare const recordProducedArtifactsForTest: typeof recordProducedArtifacts;
87
91
  export declare const resolveWorkflowArtifactFactsForTest: typeof resolveWorkflowArtifactFacts;
88
92
  export declare const readWorkflowStateForHookTest: typeof readWorkflowStateForHook;
93
+ export declare const runCodexHookWithLoadedIrForTest: typeof runCodexHookWithLoadedIr;
94
+ export declare const inferWorkflowAssetFromIrForTest: typeof inferWorkflowAssetFromIr;
89
95
  export declare const resolveWorkflowArtifactFactsForHookTest: typeof resolveWorkflowArtifactFactsForHook;
90
96
  export declare const finalizeAndResolveArtifactsForHookTest: typeof finalizeAndResolveArtifactsForHook;
91
97
  export declare function appendStopVerifierWarnings(output: HookOutput, verifierResults: VerifierResultEntry[], currentStep?: string): HookOutput;
package/dist/hooks/cli.js CHANGED
@@ -23,10 +23,11 @@ import { fileURLToPath } from "node:url";
23
23
  import { readStdin, writeOutput, silentOutput, allowOutput, blockOutput, stopOutput } from "./protocol.js";
24
24
  import { validateHookInput } from "./schema.js";
25
25
  import { enforcePreToolUse, enforcePostToolUse, enforceUserPromptSubmit, enforceSubagentStop, enforcePreCompact, enforceNotification, enforceSessionStart, enforceStop, extractBashWritePaths, checkReflectionLimit, checkContextReadiness, checkWorkflowBoundary, } from "./enforce.js";
26
- import { appendAudit, readWorkflowState, appendTrace, appendRuntimeDecisionEvent, rotateTraces, readTraces, cleanStaleState, readSurgeonAttempts, writeSurgeonAttempts, appendSessionRead, readSessionReads, appendVerifierResult, appendCompletedArtifact, artifactIdentity, buildArtifactKey, readArtifactManifest, resolveArtifactTemplate, safePathComponent, writeArtifactManifest } from "./state.js";
26
+ import { appendAudit, readWorkflowState, appendTrace, appendRuntimeDecisionEvent, appendEvidenceCaptureEvent, rotateTraces, readTraces, cleanStaleState, readSurgeonAttempts, writeSurgeonAttempts, appendSessionRead, readSessionReads, appendVerifierResult, appendCompletedArtifact, artifactIdentity, buildArtifactKey, readArtifactManifest, resolveArtifactTemplate, safePathComponent, writeArtifactManifest, EVIDENCE_CAPTURE_SCHEMA_VERSION } from "./state.js";
27
27
  import { hookEventsForSurface } from "./event-registry.js";
28
28
  import { writeAuditEvent } from "../audit/index.js";
29
- import { RUNTIME_DECISION_EVENT_SCHEMA_VERSION } from "../governance/index.js";
29
+ import { RUNTIME_DECISION_EVENT_SCHEMA_VERSION, trustedEvidenceCaptureAttribution } from "../governance/index.js";
30
+ import { runCodexHook } from "../runtime/codex-adapter.js";
30
31
  // ── Constants ──────────────────────────────────────────────
31
32
  const DEFAULT_IR_PATH = ".dna/compiled/ir.json";
32
33
  const VALID_EVENTS = new Set(hookEventsForSurface("cli"));
@@ -150,6 +151,74 @@ function buildRuntimeDecisionEvent(params) {
150
151
  evidence_refs: [{ type: "trace", ref: params.traceId }],
151
152
  };
152
153
  }
154
+ function captureResultForHook(rawInput, decision) {
155
+ if (decision === "block")
156
+ return "blocked";
157
+ if (typeof rawInput.result === "string" && ["success", "failure", "blocked", "skipped", "unknown", "unsupported"].includes(rawInput.result)) {
158
+ return rawInput.result;
159
+ }
160
+ if (typeof rawInput.exit_code === "number")
161
+ return rawInput.exit_code === 0 ? "success" : "failure";
162
+ return "unknown";
163
+ }
164
+ function captureFactForHook(rawInput, decision, event) {
165
+ if (decision === "block")
166
+ return "blocker";
167
+ if (event === "PostToolUse" || event === "Stop" || rawInput.result || rawInput.exit_code !== undefined)
168
+ return "result";
169
+ const toolInput = typeof rawInput.tool_input === "object" && rawInput.tool_input !== null
170
+ ? rawInput.tool_input
171
+ : {};
172
+ if (typeof rawInput.command === "string" || typeof toolInput.command === "string")
173
+ return "command";
174
+ return "result";
175
+ }
176
+ function commandForHook(rawInput) {
177
+ const toolInput = typeof rawInput.tool_input === "object" && rawInput.tool_input !== null
178
+ ? rawInput.tool_input
179
+ : {};
180
+ const command = rawInput.command ?? toolInput.command;
181
+ return typeof command === "string" && command.trim().length > 0 ? command : undefined;
182
+ }
183
+ function buildClaudeEvidenceCaptureEvent(params) {
184
+ const fact = captureFactForHook(params.rawInput, params.decision, params.event);
185
+ const result = captureResultForHook(params.rawInput, params.decision);
186
+ const command = commandForHook(params.rawInput);
187
+ const toolName = typeof params.rawInput.tool_name === "string" ? params.rawInput.tool_name : "unknown tool";
188
+ const subject = command ?? `${toolName} ${params.event}`;
189
+ const attribution = trustedEvidenceCaptureAttribution(params.ir, {
190
+ workflowAsset: params.wfState?.workflow_asset,
191
+ workflowId: params.wfState?.workflow,
192
+ stepId: params.wfState?.current_step ?? params.runtimeEvent.step_id,
193
+ });
194
+ return {
195
+ schema_version: EVIDENCE_CAPTURE_SCHEMA_VERSION,
196
+ event_id: `c5:${params.runtimeEvent.event_id}`,
197
+ captured_at: params.runtimeEvent.timestamp,
198
+ project_root: params.projectDir,
199
+ source: "claude_code",
200
+ workflow_asset: attribution.workflowAsset,
201
+ workflow_id: attribution.workflowId,
202
+ run_id: params.runtimeEvent.run_id || params.runtimeEvent.session_id || "unknown",
203
+ step_id: attribution.stepId === "unknown" && !params.wfState
204
+ ? `${params.event}:direct`
205
+ : attribution.stepId,
206
+ fact,
207
+ summary: `Claude hook observed ${fact} for ${subject}: ${result}`,
208
+ command,
209
+ result,
210
+ exit_code: typeof params.rawInput.exit_code === "number" ? params.rawInput.exit_code : undefined,
211
+ duration_ms: typeof params.rawInput.duration_ms === "number" ? params.rawInput.duration_ms : undefined,
212
+ manual_intervention: fact === "manual_intervention"
213
+ ? { required: true, reason: params.reason, actor: "human" }
214
+ : undefined,
215
+ evidence_refs: [
216
+ { type: "runtime_decision_event", ref: params.runtimeEvent.event_id },
217
+ ...params.runtimeEvent.evidence_refs.map((ref) => ({ type: ref.type, ref: ref.ref })),
218
+ ],
219
+ redaction: "intentdna.c5.claude_hook_secret_redaction.v1",
220
+ };
221
+ }
153
222
  export function computeSummary(traces) {
154
223
  let blocks = 0, warns = 0;
155
224
  const toolCounts = new Map();
@@ -193,7 +262,12 @@ export function formatSummary(s) {
193
262
  async function main() {
194
263
  // Parse args
195
264
  const args = process.argv.slice(2);
196
- const event = args[0];
265
+ const eventArg = args[0];
266
+ if (eventArg === "CodexHook") {
267
+ await runCodexHookCli(args);
268
+ return;
269
+ }
270
+ const event = eventArg;
197
271
  if (!event || !VALID_EVENTS.has(event)) {
198
272
  writeOutput(silentOutput());
199
273
  return;
@@ -227,13 +301,25 @@ async function main() {
227
301
  const output = await runHookEvent({ event, ir, rawInput, projectDir, sessionId });
228
302
  writeOutput(output);
229
303
  }
304
+ export function normalizeHookOutputForEvent(output, event) {
305
+ if (!output.hookSpecificOutput)
306
+ return output;
307
+ return {
308
+ ...output,
309
+ hookSpecificOutput: {
310
+ ...output.hookSpecificOutput,
311
+ hookEventName: output.hookSpecificOutput.hookEventName ?? event,
312
+ },
313
+ };
314
+ }
230
315
  export async function runHookEvent(options) {
231
316
  const { event, ir, rawInput, projectDir, sessionId, roles } = options;
317
+ const finish = (output) => normalizeHookOutputForEvent(output, event);
232
318
  const state = {};
233
319
  const writeRuntimeDecision = async (output, result, wfState, traceId = randomUUID()) => {
234
320
  const decision = normalizeDecision(output);
235
321
  const reason = decision !== "allow" ? (output.reason ?? output.hookSpecificOutput?.additionalContext ?? "unknown") : "allowed by active policy";
236
- await appendRuntimeDecisionEvent(projectDir, buildRuntimeDecisionEvent({
322
+ const runtimeEvent = buildRuntimeDecisionEvent({
237
323
  ir,
238
324
  rawInput,
239
325
  output,
@@ -245,7 +331,18 @@ export async function runHookEvent(options) {
245
331
  decision,
246
332
  reason,
247
333
  wfState,
248
- }), sessionId);
334
+ });
335
+ await appendRuntimeDecisionEvent(projectDir, runtimeEvent, sessionId);
336
+ await appendEvidenceCaptureEvent(projectDir, buildClaudeEvidenceCaptureEvent({
337
+ ir,
338
+ rawInput,
339
+ event,
340
+ projectDir,
341
+ decision,
342
+ reason,
343
+ runtimeEvent,
344
+ wfState,
345
+ }));
249
346
  };
250
347
  let wfStateRaw = null;
251
348
  // Load workflow state for events that need it (handoff context + PreCompact preservation)
@@ -253,13 +350,14 @@ export async function runHookEvent(options) {
253
350
  const workflowState = await readWorkflowStateForHook(projectDir, event, sessionId);
254
351
  if ("output" in workflowState) {
255
352
  await writeRuntimeDecision(workflowState.output, { output: workflowState.output, trace: { matched_rule: "workflow_boundary" } }, null);
256
- return workflowState.output;
353
+ return finish(workflowState.output);
257
354
  }
258
355
  wfStateRaw = workflowState.state;
259
356
  if (wfStateRaw && wfStateRaw.active) {
260
357
  state.workflowState = {
261
358
  current_step: wfStateRaw.current_step,
262
359
  workflow: wfStateRaw.workflow,
360
+ workflow_asset: wfStateRaw.workflow_asset,
263
361
  current_role: wfStateRaw.current_role,
264
362
  completed_artifacts: wfStateRaw.completed_artifacts,
265
363
  iteration: wfStateRaw.iteration, // G4: pass iteration for state-driven rules
@@ -268,7 +366,7 @@ export async function runHookEvent(options) {
268
366
  if ("output" in artifactFacts) {
269
367
  appendArtifactResolverTrace(projectDir, event, wfStateRaw, artifactFacts.output, sessionId);
270
368
  await writeRuntimeDecision(artifactFacts.output, { output: artifactFacts.output, trace: { matched_rule: "handoff", step_id: wfStateRaw.current_step } }, wfStateRaw);
271
- return artifactFacts.output;
369
+ return finish(artifactFacts.output);
272
370
  }
273
371
  state.artifactFacts = artifactFacts.facts;
274
372
  }
@@ -298,7 +396,7 @@ export async function runHookEvent(options) {
298
396
  timestamp: new Date().toISOString(),
299
397
  }, sessionId).catch(() => { });
300
398
  await writeRuntimeDecision(gateResult.output, { output: gateResult.output, trace: { matched_rule: gateResult.matched_rule, step_id: wfStateRaw?.current_step } }, wfStateRaw, traceId);
301
- return gateResult.output;
399
+ return finish(gateResult.output);
302
400
  }
303
401
  }
304
402
  // Special handling for Stop — needs async workflow state read + session summary
@@ -306,7 +404,7 @@ export async function runHookEvent(options) {
306
404
  const workflowState = await readWorkflowStateForHook(projectDir, event, sessionId);
307
405
  if ("output" in workflowState) {
308
406
  await writeRuntimeDecision(workflowState.output, { output: workflowState.output, trace: { matched_rule: "workflow_boundary" } }, null);
309
- return workflowState.output;
407
+ return finish(workflowState.output);
310
408
  }
311
409
  const wfState = workflowState.state;
312
410
  let stopArtifactFacts = [];
@@ -315,7 +413,7 @@ export async function runHookEvent(options) {
315
413
  if ("output" in artifactFacts) {
316
414
  appendArtifactResolverTrace(projectDir, event, wfState, artifactFacts.output, sessionId);
317
415
  await writeRuntimeDecision(artifactFacts.output, { output: artifactFacts.output, trace: { matched_rule: "handoff", step_id: wfState.current_step } }, wfState);
318
- return artifactFacts.output;
416
+ return finish(artifactFacts.output);
319
417
  }
320
418
  stopArtifactFacts = artifactFacts.facts;
321
419
  }
@@ -375,7 +473,7 @@ export async function runHookEvent(options) {
375
473
  timestamp: new Date().toISOString(),
376
474
  }, sessionId).catch(() => { });
377
475
  await writeRuntimeDecision(stopOutput, { output: stopOutput, trace: { matched_rule: "validator", step_id: wfState?.current_step } }, wfState, traceId);
378
- return stopOutput;
476
+ return finish(stopOutput);
379
477
  }
380
478
  // Dispatch to enforcement engine with timing
381
479
  const start = Date.now();
@@ -488,7 +586,7 @@ export async function runHookEvent(options) {
488
586
  session_id: sessionId,
489
587
  }).catch(() => { }); // Fail-open
490
588
  }
491
- return output;
589
+ return finish(output);
492
590
  }
493
591
  // ── Dispatch ───────────────────────────────────────────────
494
592
  function dispatch(event, ir, input, state, roles) {
@@ -542,6 +640,62 @@ function dispatch(event, ir, input, state, roles) {
542
640
  return null;
543
641
  }
544
642
  }
643
+ // ── Codex Hook Entry ───────────────────────────────────────
644
+ function argValue(args, flag) {
645
+ const index = args.indexOf(flag);
646
+ return index >= 0 ? args[index + 1] : undefined;
647
+ }
648
+ function codexInstallMode(value) {
649
+ return value === "plugin_scoped" || value === "managed" || value === "none" ? value : "project_fallback";
650
+ }
651
+ export function codexHookEventForInput(rawInput, args) {
652
+ return argValue(args, "--codex-event") ?? rawInput.event;
653
+ }
654
+ function inferWorkflowAssetFromIr(ir, workflowId) {
655
+ const attribution = trustedEvidenceCaptureAttribution(ir, { workflowId });
656
+ return attribution.workflowAsset === "unknown" ? undefined : attribution.workflowAsset;
657
+ }
658
+ async function runCodexHookWithLoadedIr(rawInput, projectDir, args, ir) {
659
+ const sessionId = typeof rawInput.session_id === "string"
660
+ ? rawInput.session_id
661
+ : typeof rawInput.sessionId === "string"
662
+ ? rawInput.sessionId
663
+ : undefined;
664
+ const sessionWorkflowState = sessionId
665
+ ? await readWorkflowState(projectDir, sessionId)
666
+ : null;
667
+ const workflowState = sessionWorkflowState ?? await readWorkflowState(projectDir);
668
+ const workflowAsset = inferWorkflowAssetFromIr(ir, workflowState?.workflow);
669
+ return runCodexHook({ ...rawInput, event: codexHookEventForInput(rawInput, args) }, {
670
+ ir,
671
+ projectDir,
672
+ hookInstallMode: codexInstallMode(argValue(args, "--codex-install-mode")),
673
+ hookTrusted: true,
674
+ codexVersion: process.env.CODEX_VERSION,
675
+ workflowAsset,
676
+ workflowId: workflowState?.workflow,
677
+ stepId: workflowState?.current_step,
678
+ appendEvent: true,
679
+ });
680
+ }
681
+ async function runCodexHookCli(args) {
682
+ try {
683
+ const rawInput = await readStdin(5000);
684
+ const projectDir = typeof rawInput.cwd === "string" ? rawInput.cwd : process.cwd();
685
+ const irPath = argValue(args, "--ir") ?? DEFAULT_IR_PATH;
686
+ const ir = await loadIR(resolve(projectDir, irPath));
687
+ if (!ir) {
688
+ writeOutput(silentOutput());
689
+ return;
690
+ }
691
+ const result = await runCodexHookWithLoadedIr(rawInput, projectDir, args, ir);
692
+ writeOutput(result.output);
693
+ }
694
+ catch (err) {
695
+ process.stderr.write(`\n Intent DNA: CodexHook failed open — ${err instanceof Error ? err.message : String(err)}\n`);
696
+ writeOutput(silentOutput());
697
+ }
698
+ }
545
699
  // ── IR Loading ─────────────────────────────────────────────
546
700
  /** Expected IR schema version — must match plugin-adapter.ts */
547
701
  const EXPECTED_IR_VERSION = 1;
@@ -765,6 +919,8 @@ function appendArtifactResolverTrace(projectDir, event, wfState, output, session
765
919
  export const recordProducedArtifactsForTest = recordProducedArtifacts;
766
920
  export const resolveWorkflowArtifactFactsForTest = resolveWorkflowArtifactFacts;
767
921
  export const readWorkflowStateForHookTest = readWorkflowStateForHook;
922
+ export const runCodexHookWithLoadedIrForTest = runCodexHookWithLoadedIr;
923
+ export const inferWorkflowAssetFromIrForTest = inferWorkflowAssetFromIr;
768
924
  export const resolveWorkflowArtifactFactsForHookTest = resolveWorkflowArtifactFactsForHook;
769
925
  export const finalizeAndResolveArtifactsForHookTest = finalizeAndResolveArtifactsForHook;
770
926
  function clearBlockingVerifierCheckpoints(ir, workflowState) {
@@ -26,6 +26,7 @@ export interface EnforceState {
26
26
  workflowState?: {
27
27
  current_step: string;
28
28
  workflow: string;
29
+ workflow_asset?: string;
29
30
  current_role?: string;
30
31
  completed_artifacts?: CompletedArtifactEntry[];
31
32
  /** G4: current workflow iteration (for relax_after_iteration rules) */
@@ -4,7 +4,7 @@
4
4
  * TypeScript types for Claude Code hook I/O and stdin/stdout utilities.
5
5
  * All hooks read JSON from stdin and write JSON to stdout.
6
6
  *
7
- * Protocol reference: docs/references/cc-source-analysis.md §2
7
+ * Protocol reference: docs/archive/2026H1/references/cc-source-analysis.md §2
8
8
  */
9
9
  export type { HookEvent } from "./event-registry.js";
10
10
  /** Base fields present in all hook inputs */
@@ -4,7 +4,7 @@
4
4
  * TypeScript types for Claude Code hook I/O and stdin/stdout utilities.
5
5
  * All hooks read JSON from stdin and write JSON to stdout.
6
6
  *
7
- * Protocol reference: docs/references/cc-source-analysis.md §2
7
+ * Protocol reference: docs/archive/2026H1/references/cc-source-analysis.md §2
8
8
  */
9
9
  // ── Output Helpers ─────────────────────────────────────────
10
10
  /** Create an allow output, optionally injecting text into the conversation. */
@@ -11,9 +11,11 @@
11
11
  */
12
12
  import type { ArtifactFact, ArtifactKey, ArtifactManifest, CompletedArtifactEntry, HandoffArtifact, HandoffType, VerifierKind, VerifierSeverity, VerifierWhen } from "../schema/types.js";
13
13
  import { type RuntimeDecisionEvent } from "../governance/index.js";
14
+ export declare const EVIDENCE_CAPTURE_SCHEMA_VERSION = "intentdna.evidence_capture.v1";
14
15
  /** Workflow state written by runtime and read by hooks */
15
16
  export interface DNAWorkflowState {
16
17
  active: boolean;
18
+ workflow_asset?: string;
17
19
  workflow: string;
18
20
  current_step: string;
19
21
  current_role: string;
@@ -51,6 +53,44 @@ export interface SurgeonAttemptState {
51
53
  lesson: string;
52
54
  }>;
53
55
  }
56
+ export type EvidenceCaptureSource = "dna_hook" | "codex_cli" | "claude_code" | "dna_cli" | "manual";
57
+ export type EvidenceCaptureFact = "command" | "result" | "retry" | "manual_intervention" | "blocker" | "handoff";
58
+ export type EvidenceCaptureResult = "success" | "failure" | "blocked" | "skipped" | "unknown" | "unsupported";
59
+ export interface EvidenceCaptureRetry {
60
+ attempt: number;
61
+ max_attempts: number;
62
+ reason: string;
63
+ }
64
+ export interface EvidenceCaptureManualIntervention {
65
+ required: boolean;
66
+ reason: string;
67
+ actor: string;
68
+ }
69
+ export interface EvidenceCaptureRef {
70
+ type: string;
71
+ ref: string;
72
+ }
73
+ export interface EvidenceCaptureEvent {
74
+ schema_version: typeof EVIDENCE_CAPTURE_SCHEMA_VERSION;
75
+ event_id: string;
76
+ captured_at: string;
77
+ project_root: string;
78
+ source: EvidenceCaptureSource;
79
+ workflow_asset: string;
80
+ workflow_id: string;
81
+ run_id: string;
82
+ step_id: string;
83
+ fact: EvidenceCaptureFact;
84
+ summary: string;
85
+ command?: string;
86
+ result?: EvidenceCaptureResult;
87
+ exit_code?: number;
88
+ duration_ms?: number;
89
+ retry?: EvidenceCaptureRetry;
90
+ manual_intervention?: EvidenceCaptureManualIntervention;
91
+ evidence_refs?: EvidenceCaptureRef[];
92
+ redaction?: string;
93
+ }
54
94
  export declare function safePathComponent(value: string, label: string): string;
55
95
  /**
56
96
  * Resolve state directory path.
@@ -181,6 +221,7 @@ export interface TraceEntry {
181
221
  * Fail-open: never throws.
182
222
  */
183
223
  export declare function appendTrace(projectDir: string, entry: TraceEntry, sessionId?: string): Promise<void>;
224
+ export declare function appendEvidenceCaptureEvent(projectDir: string, event: EvidenceCaptureEvent): Promise<void>;
184
225
  export declare function appendRuntimeDecisionEvent(projectDir: string, event: RuntimeDecisionEvent, sessionId?: string): Promise<void>;
185
226
  export declare function readRuntimeDecisionEvents(projectDir: string, days?: number, sessionId?: string): Promise<RuntimeDecisionEvent[]>;
186
227
  export declare function readTraces(projectDir: string, days?: number, sessionId?: string): Promise<TraceEntry[]>;