intentdna 1.7.5 → 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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/LICENSE +201 -0
- package/README.md +143 -194
- package/dist/assets/candidates.d.ts +124 -0
- package/dist/assets/candidates.js +1249 -0
- package/dist/assets/catalog.d.ts +101 -0
- package/dist/assets/catalog.js +311 -0
- package/dist/assets/evidence.d.ts +93 -0
- package/dist/assets/evidence.js +391 -0
- package/dist/assets/index.d.ts +4 -0
- package/dist/assets/index.js +4 -0
- package/dist/assets/metadata.d.ts +19 -0
- package/dist/assets/metadata.js +227 -0
- package/dist/cli/commands/assets.d.ts +65 -0
- package/dist/cli/commands/assets.js +2871 -0
- package/dist/cli/commands/auth.d.ts +322 -0
- package/dist/cli/commands/auth.js +1592 -0
- package/dist/cli/commands/cloud-auth-guidance.d.ts +2 -0
- package/dist/cli/commands/cloud-auth-guidance.js +4 -0
- package/dist/cli/commands/cloud.d.ts +1359 -0
- package/dist/cli/commands/cloud.js +8364 -0
- package/dist/cli/commands/evolve.js +18 -2
- package/dist/cli/commands/generate.js +25 -2
- package/dist/cli/commands/guard.d.ts +1 -1
- package/dist/cli/commands/guard.js +1 -1
- package/dist/cli/commands/guide.d.ts +15 -0
- package/dist/cli/commands/guide.js +1747 -0
- package/dist/cli/commands/init.d.ts +12 -0
- package/dist/cli/commands/init.js +95 -60
- package/dist/cli/commands/org.d.ts +16 -0
- package/dist/cli/commands/org.js +2393 -0
- package/dist/cli/commands/release.d.ts +59 -0
- package/dist/cli/commands/release.js +716 -0
- package/dist/cli/commands/report.d.ts +82 -0
- package/dist/cli/commands/report.js +1516 -0
- package/dist/cli/commands/run.d.ts +6 -1
- package/dist/cli/commands/run.js +95 -26
- package/dist/cli/commands/sync.d.ts +8 -1
- package/dist/cli/commands/sync.js +436 -141
- package/dist/cli/commands/templates.d.ts +64 -0
- package/dist/cli/commands/templates.js +2151 -1
- package/dist/cli/commands/workflow.d.ts +26 -0
- package/dist/cli/commands/workflow.js +3053 -0
- package/dist/cli/index.js +703 -36
- package/dist/compiler/cascade.js +4 -9
- package/dist/compiler/compile.js +1 -0
- package/dist/governance/evidence-capture-attribution.d.ts +12 -0
- package/dist/governance/evidence-capture-attribution.js +46 -0
- package/dist/governance/index.d.ts +2 -0
- package/dist/governance/index.js +1 -0
- package/dist/hooks/cli.d.ts +5 -0
- package/dist/hooks/cli.js +149 -5
- package/dist/hooks/enforce.d.ts +1 -0
- package/dist/hooks/protocol.d.ts +1 -1
- package/dist/hooks/protocol.js +1 -1
- package/dist/hooks/state.d.ts +41 -0
- package/dist/hooks/state.js +126 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/mcp/tools-state.js +2 -0
- package/dist/organization/index.d.ts +121 -0
- package/dist/organization/index.js +413 -0
- package/dist/runtime/claude-sync-target.d.ts +49 -0
- package/dist/runtime/claude-sync-target.js +280 -0
- package/dist/runtime/codex-adapter.d.ts +254 -0
- package/dist/runtime/codex-adapter.js +1204 -0
- package/dist/runtime/codex-sync-target.d.ts +33 -0
- package/dist/runtime/codex-sync-target.js +241 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/output-artifact-registry.d.ts +1 -1
- package/dist/runtime/output-artifact-registry.js +2 -0
- package/dist/runtime/settings-adapter.d.ts +1 -1
- package/dist/runtime/settings-adapter.js +1 -1
- package/dist/runtime/skill-adapter.d.ts +5 -1
- package/dist/runtime/skill-adapter.js +120 -34
- package/dist/runtime/sync-artifact-registry.d.ts +99 -0
- package/dist/runtime/sync-artifact-registry.js +194 -0
- package/dist/runtime/sync-target-plan.d.ts +45 -0
- package/dist/runtime/sync-target-plan.js +19 -0
- package/dist/schema/controller-registry.d.ts +8 -1
- package/dist/schema/controller-registry.js +8 -0
- package/dist/schema/types.d.ts +35 -23
- package/dist/schema/types.js +10 -1
- package/dist/schema/validate.js +22 -22
- package/dist/schema/validators/controllers.js +38 -20
- package/dist/schema/workflow-authoring-contract.d.ts +29 -0
- package/dist/schema/workflow-authoring-contract.js +109 -0
- package/dist/schema/yaml-parser.js +18 -0
- package/dist/templates/api-backend.dna.yaml +19 -0
- package/dist/templates/brainstorming-first.dna.yaml +19 -0
- package/dist/templates/code-cleanup.dna.yaml +19 -0
- package/dist/templates/code-review-pipeline.dna.yaml +18 -0
- package/dist/templates/documentation-writer.dna.yaml +19 -0
- package/dist/templates/flutter-behavior-lock.dna.yaml +19 -0
- package/dist/templates/flutter-refactoring-rescue.dna.yaml +19 -0
- package/dist/templates/flutter-rewrite-diagnosis-review.dna.yaml +210 -0
- package/dist/templates/flutter-rewrite-fix-review-loop.dna.yaml +260 -0
- package/dist/templates/flutter-rewrite-new.dna.yaml +506 -0
- package/dist/templates/flutter-rewrite.dna.yaml +20 -0
- package/dist/templates/frontend-quality.dna.yaml +19 -0
- package/dist/templates/full-pipeline.dna.yaml +20 -0
- package/dist/templates/marketplace.d.ts +92 -0
- package/dist/templates/marketplace.js +502 -0
- package/dist/templates/metadata.d.ts +25 -0
- package/dist/templates/metadata.js +136 -3
- package/dist/templates/mobile-dev.dna.yaml +19 -0
- package/dist/templates/multi-agent-handoff-coordination.dna.yaml +156 -0
- package/dist/templates/multi-perspective-review.dna.yaml +19 -0
- package/dist/templates/persistent-executor.dna.yaml +19 -0
- package/dist/templates/qa-loop.dna.yaml +18 -0
- package/dist/templates/release-evidence-gate.dna.yaml +131 -0
- package/dist/templates/requirements-gate.dna.yaml +19 -0
- package/dist/templates/research-orchestration.dna.yaml +19 -0
- package/dist/templates/root-cause-analysis.dna.yaml +19 -0
- package/dist/templates/safe-refactoring.dna.yaml +321 -0
- package/dist/templates/secure-dev.dna.yaml +19 -0
- package/dist/templates/subagent-parallel.dna.yaml +19 -0
- package/dist/templates/systematic-debugging.dna.yaml +19 -0
- package/dist/templates/tdd-strict.dna.yaml +19 -0
- package/dist/templates/ui-visual-regression-qa.dna.yaml +133 -0
- package/dist/templates/workflow-author.dna.yaml +302 -0
- package/dist/templates/workflow-blocked-scope-triage.dna.yaml +242 -0
- package/dist/templates/workflow-completion-audit.dna.yaml +254 -0
- package/dist/templates/workflow-cross-boundary-resource-approval.dna.yaml +249 -0
- package/dist/templates/workflow-evidence-review.dna.yaml +198 -0
- package/dist/templates/workflow-module-inventory.dna.yaml +257 -0
- package/dist/templates/workflow-runtime-smoke-review.dna.yaml +252 -0
- package/dist/templates/workflow-verification-command-routing.dna.yaml +278 -0
- package/dist/workflow/authoring-packet.d.ts +67 -0
- package/dist/workflow/authoring-packet.js +218 -0
- package/dist/workflow/draft.d.ts +159 -0
- package/dist/workflow/draft.js +800 -0
- package/dist/workflow/index.d.ts +3 -0
- package/dist/workflow/index.js +3 -0
- package/dist/workflow/suggestion-review.d.ts +65 -0
- package/dist/workflow/suggestion-review.js +245 -0
- package/package.json +1 -1
- package/spec/README.md +15 -48
- package/spec/codex-adapter-contract.md +176 -0
- package/spec/sync-target-plan.md +158 -0
- package/spec/workflow-capability-ir.md +153 -0
- package/spec/agent-dispatch-fix.md +0 -116
- package/spec/control-plane-convergence-handoff-2026-04-24.md +0 -432
- package/spec/flutter-rewrite-template-optimization.md +0 -301
- package/spec/foundation-hardening.md +0 -178
- package/spec/hooks-infra-harness-hardening.md +0 -741
- package/spec/multi-config.md +0 -172
- package/spec/parallel-isolation.md +0 -268
- package/spec/template-version-namespace-fix.md +0 -653
- package/spec/workflow-pipeline.md +0 -101
package/dist/compiler/cascade.js
CHANGED
|
@@ -109,15 +109,10 @@ function prefixRecordKeys(record, ns) {
|
|
|
109
109
|
function prefixController(controller, ns) {
|
|
110
110
|
return {
|
|
111
111
|
...controller,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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) {
|
package/dist/compiler/compile.js
CHANGED
|
@@ -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";
|
package/dist/governance/index.js
CHANGED
|
@@ -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";
|
package/dist/hooks/cli.d.ts
CHANGED
|
@@ -49,6 +49,9 @@ export interface RunHookEventOptions {
|
|
|
49
49
|
}
|
|
50
50
|
export declare function normalizeHookOutputForEvent(output: HookOutput, event: HookEvent): HookOutput;
|
|
51
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>;
|
|
52
55
|
declare function recordProducedArtifacts(projectDir: string, ir: ConstraintIR, wfState: {
|
|
53
56
|
workflow: string;
|
|
54
57
|
current_step: string;
|
|
@@ -87,6 +90,8 @@ declare function finalizeAndResolveArtifactsForHook(projectDir: string, ir: Cons
|
|
|
87
90
|
export declare const recordProducedArtifactsForTest: typeof recordProducedArtifacts;
|
|
88
91
|
export declare const resolveWorkflowArtifactFactsForTest: typeof resolveWorkflowArtifactFacts;
|
|
89
92
|
export declare const readWorkflowStateForHookTest: typeof readWorkflowStateForHook;
|
|
93
|
+
export declare const runCodexHookWithLoadedIrForTest: typeof runCodexHookWithLoadedIr;
|
|
94
|
+
export declare const inferWorkflowAssetFromIrForTest: typeof inferWorkflowAssetFromIr;
|
|
90
95
|
export declare const resolveWorkflowArtifactFactsForHookTest: typeof resolveWorkflowArtifactFactsForHook;
|
|
91
96
|
export declare const finalizeAndResolveArtifactsForHookTest: typeof finalizeAndResolveArtifactsForHook;
|
|
92
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
|
|
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;
|
|
@@ -245,7 +319,7 @@ export async function runHookEvent(options) {
|
|
|
245
319
|
const writeRuntimeDecision = async (output, result, wfState, traceId = randomUUID()) => {
|
|
246
320
|
const decision = normalizeDecision(output);
|
|
247
321
|
const reason = decision !== "allow" ? (output.reason ?? output.hookSpecificOutput?.additionalContext ?? "unknown") : "allowed by active policy";
|
|
248
|
-
|
|
322
|
+
const runtimeEvent = buildRuntimeDecisionEvent({
|
|
249
323
|
ir,
|
|
250
324
|
rawInput,
|
|
251
325
|
output,
|
|
@@ -257,7 +331,18 @@ export async function runHookEvent(options) {
|
|
|
257
331
|
decision,
|
|
258
332
|
reason,
|
|
259
333
|
wfState,
|
|
260
|
-
})
|
|
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
|
+
}));
|
|
261
346
|
};
|
|
262
347
|
let wfStateRaw = null;
|
|
263
348
|
// Load workflow state for events that need it (handoff context + PreCompact preservation)
|
|
@@ -272,6 +357,7 @@ export async function runHookEvent(options) {
|
|
|
272
357
|
state.workflowState = {
|
|
273
358
|
current_step: wfStateRaw.current_step,
|
|
274
359
|
workflow: wfStateRaw.workflow,
|
|
360
|
+
workflow_asset: wfStateRaw.workflow_asset,
|
|
275
361
|
current_role: wfStateRaw.current_role,
|
|
276
362
|
completed_artifacts: wfStateRaw.completed_artifacts,
|
|
277
363
|
iteration: wfStateRaw.iteration, // G4: pass iteration for state-driven rules
|
|
@@ -554,6 +640,62 @@ function dispatch(event, ir, input, state, roles) {
|
|
|
554
640
|
return null;
|
|
555
641
|
}
|
|
556
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
|
+
}
|
|
557
699
|
// ── IR Loading ─────────────────────────────────────────────
|
|
558
700
|
/** Expected IR schema version — must match plugin-adapter.ts */
|
|
559
701
|
const EXPECTED_IR_VERSION = 1;
|
|
@@ -777,6 +919,8 @@ function appendArtifactResolverTrace(projectDir, event, wfState, output, session
|
|
|
777
919
|
export const recordProducedArtifactsForTest = recordProducedArtifacts;
|
|
778
920
|
export const resolveWorkflowArtifactFactsForTest = resolveWorkflowArtifactFacts;
|
|
779
921
|
export const readWorkflowStateForHookTest = readWorkflowStateForHook;
|
|
922
|
+
export const runCodexHookWithLoadedIrForTest = runCodexHookWithLoadedIr;
|
|
923
|
+
export const inferWorkflowAssetFromIrForTest = inferWorkflowAssetFromIr;
|
|
780
924
|
export const resolveWorkflowArtifactFactsForHookTest = resolveWorkflowArtifactFactsForHook;
|
|
781
925
|
export const finalizeAndResolveArtifactsForHookTest = finalizeAndResolveArtifactsForHook;
|
|
782
926
|
function clearBlockingVerifierCheckpoints(ir, workflowState) {
|
package/dist/hooks/enforce.d.ts
CHANGED
|
@@ -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) */
|
package/dist/hooks/protocol.d.ts
CHANGED
|
@@ -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 */
|
package/dist/hooks/protocol.js
CHANGED
|
@@ -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. */
|
package/dist/hooks/state.d.ts
CHANGED
|
@@ -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[]>;
|
package/dist/hooks/state.js
CHANGED
|
@@ -13,6 +13,8 @@ import { readFile, writeFile, rename, mkdir, appendFile, unlink, readdir, stat }
|
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
import { join, dirname } from "node:path";
|
|
15
15
|
import { CASCADE_LAYER_NAMES, RUNTIME_DECISION_EVENT_SCHEMA_VERSION } from "../governance/index.js";
|
|
16
|
+
// ── Types ──────────────────────────────────────────────────
|
|
17
|
+
export const EVIDENCE_CAPTURE_SCHEMA_VERSION = "intentdna.evidence_capture.v1";
|
|
16
18
|
// ── Constants ──────────────────────────────────────────────
|
|
17
19
|
const WORKFLOW_FILE = "workflow.json";
|
|
18
20
|
const DEFAULT_STALENESS_MS = 2 * 60 * 60 * 1000; // 2 hours
|
|
@@ -408,6 +410,7 @@ export async function appendVerifierResult(projectDir, result, sessionId) {
|
|
|
408
410
|
}
|
|
409
411
|
const TRACE_DIR = "trace";
|
|
410
412
|
const RUNTIME_DECISION_DIR = "runtime-decisions";
|
|
413
|
+
const EVIDENCE_CAPTURE_DIR = join("evidence", "capture");
|
|
411
414
|
const MAX_TRACE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
412
415
|
const TRACE_RETENTION_DAYS = 7;
|
|
413
416
|
/**
|
|
@@ -475,15 +478,135 @@ function datedJsonlFileName(prefix, date) {
|
|
|
475
478
|
function decisionFileName(date) {
|
|
476
479
|
return datedJsonlFileName("runtime-decision", date);
|
|
477
480
|
}
|
|
481
|
+
function evidenceCaptureFileName(date) {
|
|
482
|
+
return `${date}.jsonl`;
|
|
483
|
+
}
|
|
484
|
+
function privacyDigest(domain, value) {
|
|
485
|
+
const material = value && value.trim().length > 0 ? value : "unknown";
|
|
486
|
+
return createHash("sha256")
|
|
487
|
+
.update(`intentdna.privacy.${domain}\0${material}`)
|
|
488
|
+
.digest("hex");
|
|
489
|
+
}
|
|
490
|
+
const OPAQUE_REFERENCE = /^(?:(?:[a-z][a-z0-9:-]*:)?sha256:[a-f0-9]{64}|[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})$/i;
|
|
491
|
+
const PROJECTED_REFERENCE = /^intentdna-[a-z0-9-]+:sha256:[a-f0-9]{64}$/i;
|
|
492
|
+
const RUNTIME_EVIDENCE_REF_TYPES = new Set(["trace", "audit", "artifact", "verifier", "handoff", "legacy", "unknown", "unsupported"]);
|
|
493
|
+
const CAPTURE_EVIDENCE_REF_TYPES = new Set([...RUNTIME_EVIDENCE_REF_TYPES, "runtime_decision_event", "completion_check", "git_commit"]);
|
|
494
|
+
function projectedValue(domain, value) {
|
|
495
|
+
const material = value && value.trim().length > 0 ? value : "unknown";
|
|
496
|
+
if (material === "unknown" || material === "unsupported")
|
|
497
|
+
return material;
|
|
498
|
+
if (material.startsWith(`intentdna-${domain}:sha256:`) && PROJECTED_REFERENCE.test(material))
|
|
499
|
+
return material;
|
|
500
|
+
return `intentdna-${domain}:sha256:${privacyDigest(domain, material)}`;
|
|
501
|
+
}
|
|
502
|
+
function projectedSessionDirName(sessionId) {
|
|
503
|
+
return `session-sha256-${privacyDigest("session-dir", sessionId)}`;
|
|
504
|
+
}
|
|
505
|
+
function projectedRuntimeEvidenceRef(ref) {
|
|
506
|
+
const type = RUNTIME_EVIDENCE_REF_TYPES.has(ref.type) ? ref.type : "unknown";
|
|
507
|
+
return {
|
|
508
|
+
type,
|
|
509
|
+
ref: OPAQUE_REFERENCE.test(ref.ref) ? ref.ref : projectedValue(`c4-evidence-ref-${type}`, ref.ref),
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function projectedCaptureEvidenceRef(ref) {
|
|
513
|
+
const type = CAPTURE_EVIDENCE_REF_TYPES.has(ref.type) ? ref.type : "unknown";
|
|
514
|
+
if (type === "runtime_decision_event" || OPAQUE_REFERENCE.test(ref.ref))
|
|
515
|
+
return { type, ref: ref.ref };
|
|
516
|
+
return {
|
|
517
|
+
type,
|
|
518
|
+
ref: projectedValue(`c5-evidence-ref-${type}`, ref.ref),
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function dateFromIso(value) {
|
|
522
|
+
return typeof value === "string" && /^\d{4}-\d{2}-\d{2}T/.test(value)
|
|
523
|
+
? value.slice(0, 10)
|
|
524
|
+
: new Date().toISOString().slice(0, 10);
|
|
525
|
+
}
|
|
526
|
+
function redactEvidenceCaptureText(value) {
|
|
527
|
+
return value
|
|
528
|
+
.replace(/(authorization:\s*Bearer\s+)[^\s'"]+/gi, "$1<redacted>")
|
|
529
|
+
.replace(/((?:INTENTDNA_API_TOKEN|INTENTDNA_SUPABASE_USER_JWT|SUPABASE_ACCESS_TOKEN|SUPABASE_SERVICE_ROLE_KEY|INTENTDNA_TOKEN_PEPPER|SUPABASE_SECRET_KEYS)=)(?:"[^"]*"|'[^']*'|[^\s'"]+)/gi, "$1<redacted>")
|
|
530
|
+
.replace(/idna_[A-Za-z0-9_-]+/g, "idna_<redacted>")
|
|
531
|
+
.replace(/sbp_[A-Za-z0-9_-]+/g, "sbp_<redacted>")
|
|
532
|
+
.replace(/eyJ[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+){2}/g, "<jwt-redacted>");
|
|
533
|
+
}
|
|
534
|
+
function redactEvidenceCaptureEvent(event) {
|
|
535
|
+
return {
|
|
536
|
+
...event,
|
|
537
|
+
project_root: projectedValue("c5-project-root", event.project_root),
|
|
538
|
+
run_id: projectedValue("c5-run-id", event.run_id),
|
|
539
|
+
summary: projectedValue("c5-summary", redactEvidenceCaptureText(event.summary)),
|
|
540
|
+
command: event.command ? projectedValue("c5-command", redactEvidenceCaptureText(event.command)) : undefined,
|
|
541
|
+
retry: event.retry ? { ...event.retry, reason: projectedValue("c5-retry-reason", redactEvidenceCaptureText(event.retry.reason)) } : undefined,
|
|
542
|
+
manual_intervention: event.manual_intervention
|
|
543
|
+
? { ...event.manual_intervention, reason: projectedValue("c5-manual-reason", redactEvidenceCaptureText(event.manual_intervention.reason)) }
|
|
544
|
+
: undefined,
|
|
545
|
+
evidence_refs: event.evidence_refs?.map(projectedCaptureEvidenceRef),
|
|
546
|
+
redaction: "intentdna.c5.persistent_projection.v1",
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function projectRuntimeDecisionEventForDisk(event) {
|
|
550
|
+
return {
|
|
551
|
+
...event,
|
|
552
|
+
org_id: projectedValue("c4-org-id", event.org_id),
|
|
553
|
+
team_id: projectedValue("c4-team-id", event.team_id),
|
|
554
|
+
user_id: projectedValue("c4-user-id", event.user_id),
|
|
555
|
+
project_id: projectedValue("c4-project-id", event.project_id),
|
|
556
|
+
agent_id: projectedValue("c4-agent-id", event.agent_id),
|
|
557
|
+
agent_role: projectedValue("c4-agent-role", event.agent_role),
|
|
558
|
+
agent_type: projectedValue("c4-agent-type", event.agent_type),
|
|
559
|
+
session_agent: projectedValue("c4-session-agent", event.session_agent),
|
|
560
|
+
cascade_layers: Object.fromEntries(CASCADE_LAYER_NAMES.map((layer) => {
|
|
561
|
+
const entry = event.cascade_layers[layer];
|
|
562
|
+
return [layer, {
|
|
563
|
+
...entry,
|
|
564
|
+
source_ref: projectedValue(`c4-cascade-${layer}-source-ref`, entry.source_ref),
|
|
565
|
+
}];
|
|
566
|
+
})),
|
|
567
|
+
winning_constraint: {
|
|
568
|
+
...event.winning_constraint,
|
|
569
|
+
provenance_reason: projectedValue("c4-winning-provenance-reason", event.winning_constraint.provenance_reason),
|
|
570
|
+
},
|
|
571
|
+
decision_reason: projectedValue("c4-decision-reason", event.decision_reason),
|
|
572
|
+
harness_runtime_context: {
|
|
573
|
+
...event.harness_runtime_context,
|
|
574
|
+
agent_id: projectedValue("c4-agent-id", event.harness_runtime_context.agent_id),
|
|
575
|
+
agent_role: projectedValue("c4-agent-role", event.harness_runtime_context.agent_role),
|
|
576
|
+
agent_type: projectedValue("c4-agent-type", event.harness_runtime_context.agent_type),
|
|
577
|
+
session_agent: projectedValue("c4-session-agent", event.harness_runtime_context.session_agent),
|
|
578
|
+
},
|
|
579
|
+
session_id: projectedValue("c4-session-id", event.session_id),
|
|
580
|
+
run_id: projectedValue("c4-run-id", event.run_id),
|
|
581
|
+
step_id: projectedValue("c4-step-id", event.step_id),
|
|
582
|
+
tool_name: projectedValue("c4-tool-name", event.tool_name),
|
|
583
|
+
resource_ref: projectedValue("c4-resource-ref", event.resource_ref),
|
|
584
|
+
evidence_refs: event.evidence_refs.map(projectedRuntimeEvidenceRef),
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
export async function appendEvidenceCaptureEvent(projectDir, event) {
|
|
588
|
+
try {
|
|
589
|
+
const sanitized = redactEvidenceCaptureEvent(event);
|
|
590
|
+
const line = JSON.stringify(sanitized) + "\n";
|
|
591
|
+
const date = dateFromIso(sanitized.captured_at);
|
|
592
|
+
const captureDir = join(projectDir, ".dna", EVIDENCE_CAPTURE_DIR);
|
|
593
|
+
await mkdir(captureDir, { recursive: true });
|
|
594
|
+
await appendFile(join(captureDir, evidenceCaptureFileName(date)), line, "utf-8");
|
|
595
|
+
}
|
|
596
|
+
catch {
|
|
597
|
+
// Fail-open: evidence capture write failure never affects hook execution
|
|
598
|
+
}
|
|
599
|
+
}
|
|
478
600
|
export async function appendRuntimeDecisionEvent(projectDir, event, sessionId) {
|
|
479
601
|
try {
|
|
480
|
-
const
|
|
602
|
+
const projected = projectRuntimeDecisionEventForDisk(event);
|
|
603
|
+
const line = JSON.stringify(projected) + "\n";
|
|
481
604
|
const date = new Date().toISOString().slice(0, 10);
|
|
482
605
|
const globalDir = join(projectDir, ".dna", "state", RUNTIME_DECISION_DIR);
|
|
483
606
|
await mkdir(globalDir, { recursive: true });
|
|
484
607
|
await appendFile(join(globalDir, decisionFileName(date)), line, "utf-8");
|
|
485
608
|
if (sessionId) {
|
|
486
|
-
const sessionDir = resolveStateDir(projectDir, sessionId);
|
|
609
|
+
const sessionDir = resolveStateDir(projectDir, projectedSessionDirName(sessionId));
|
|
487
610
|
await mkdir(sessionDir, { recursive: true });
|
|
488
611
|
await appendFile(join(sessionDir, "runtime-decisions.jsonl"), line, "utf-8");
|
|
489
612
|
}
|
|
@@ -572,6 +695,7 @@ function normalizeRuntimeDecisionEvent(value) {
|
|
|
572
695
|
export async function readRuntimeDecisionEvents(projectDir, days = 1, sessionId) {
|
|
573
696
|
const entries = [];
|
|
574
697
|
if (sessionId) {
|
|
698
|
+
entries.push(...await readRuntimeDecisionFile(join(resolveStateDir(projectDir, projectedSessionDirName(sessionId)), "runtime-decisions.jsonl")));
|
|
575
699
|
entries.push(...await readRuntimeDecisionFile(join(resolveStateDir(projectDir, sessionId), "runtime-decisions.jsonl")));
|
|
576
700
|
}
|
|
577
701
|
else {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/mcp/tools-state.js
CHANGED
|
@@ -104,6 +104,7 @@ export function createStateTools(projectDir) {
|
|
|
104
104
|
type: "object",
|
|
105
105
|
properties: {
|
|
106
106
|
workflow: { type: "string", description: "Workflow name" },
|
|
107
|
+
workflow_asset: { type: "string", description: "Workflow asset id/name for local evidence attribution" },
|
|
107
108
|
current_step: { type: "string", description: "Current step ID" },
|
|
108
109
|
current_role: { type: "string", description: "Current role name" },
|
|
109
110
|
iteration: { type: "number", description: "Current iteration number" },
|
|
@@ -119,6 +120,7 @@ export function createStateTools(projectDir) {
|
|
|
119
120
|
const existing = await readWorkflowState(projectDir, sessionId, 0);
|
|
120
121
|
const state = {
|
|
121
122
|
active: typeof args.active === "boolean" ? args.active : true,
|
|
123
|
+
workflow_asset: typeof args.workflow_asset === "string" ? args.workflow_asset : existing?.workflow_asset,
|
|
122
124
|
workflow: String(args.workflow),
|
|
123
125
|
current_step: String(args.current_step),
|
|
124
126
|
current_role: String(args.current_role),
|