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.
- 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 +719 -42
- 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 +6 -0
- package/dist/hooks/cli.js +168 -12
- 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
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AUTHORING_PACKET_SCHEMA_VERSION, buildAuthoringPacket, type AuthoringPacket, type AuthoringPacketExample, type AuthoringPacketOptions, } from "./authoring-packet.js";
|
|
2
|
+
export { createWorkflowDraft, createWorkflowEditPlan, createWorkflowEditPlanFromWorkflow, buildWorkflowDesignPacket, workflowDraftExamples, workflowDraftToTemplateYaml, workflowDraftToYaml, type WorkflowDraft, type WorkflowDraftExample, type WorkflowDraftExampleId, type WorkflowDraftInput, type WorkflowDraftValidation, type WorkflowDraftDef, type WorkflowDesignPacket, type WorkflowEditOperation, type WorkflowEditPlan, type WorkflowEditPlanInput, type WorkflowTemplateEvidenceLink, type WorkflowTemplateLineage, type WorkflowTemplateContext, } from "./draft.js";
|
|
3
|
+
export { SUGGESTION_REVIEW_PATH, SUGGESTION_REVIEW_STALE_LOCK_MS, WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION, appendSuggestionReviewReceipt, buildSuggestionReviewReceipt, findTerminalSuggestionReceipt, normalizeReviewDecision, readSuggestionReviewReceipts, sha256Canonical, suggestionBindingDigest, type SuggestionReviewDecision, type WorkflowSuggestionForReview, type WorkflowSuggestionReviewReceipt, type WorkflowSuggestionReviewSnapshot, } from "./suggestion-review.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AUTHORING_PACKET_SCHEMA_VERSION, buildAuthoringPacket, } from "./authoring-packet.js";
|
|
2
|
+
export { createWorkflowDraft, createWorkflowEditPlan, createWorkflowEditPlanFromWorkflow, buildWorkflowDesignPacket, workflowDraftExamples, workflowDraftToTemplateYaml, workflowDraftToYaml, } from "./draft.js";
|
|
3
|
+
export { SUGGESTION_REVIEW_PATH, SUGGESTION_REVIEW_STALE_LOCK_MS, WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION, appendSuggestionReviewReceipt, buildSuggestionReviewReceipt, findTerminalSuggestionReceipt, normalizeReviewDecision, readSuggestionReviewReceipts, sha256Canonical, suggestionBindingDigest, } from "./suggestion-review.js";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export declare const WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION = "intentdna.workflow_suggestion_review_receipt.v1";
|
|
2
|
+
export declare const SUGGESTION_REVIEW_PATH: string;
|
|
3
|
+
export declare const SUGGESTION_REVIEW_STALE_LOCK_MS = 30000;
|
|
4
|
+
export type SuggestionReviewDecision = "accept" | "reject" | "defer";
|
|
5
|
+
export interface WorkflowSuggestionForReview {
|
|
6
|
+
id: string;
|
|
7
|
+
evidenceRefs?: Array<{
|
|
8
|
+
type: string;
|
|
9
|
+
ref: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export interface WorkflowSuggestionReviewSnapshot {
|
|
13
|
+
asset: string;
|
|
14
|
+
workflowId: string;
|
|
15
|
+
suggestion: WorkflowSuggestionForReview;
|
|
16
|
+
}
|
|
17
|
+
export interface WorkflowSuggestionReviewReceipt {
|
|
18
|
+
schema_version: typeof WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION;
|
|
19
|
+
receipt_id: string;
|
|
20
|
+
reviewed_at: string;
|
|
21
|
+
asset: string;
|
|
22
|
+
workflow_id: string;
|
|
23
|
+
suggestion_id: string;
|
|
24
|
+
decision: SuggestionReviewDecision;
|
|
25
|
+
suggestion_digest: string;
|
|
26
|
+
binding_digest: string;
|
|
27
|
+
evidence_refs: Array<{
|
|
28
|
+
type: string;
|
|
29
|
+
ref: string;
|
|
30
|
+
}>;
|
|
31
|
+
source: "k4_human_review";
|
|
32
|
+
}
|
|
33
|
+
export declare function sha256Canonical(value: unknown): string;
|
|
34
|
+
export declare function suggestionBindingDigest(params: {
|
|
35
|
+
asset: string;
|
|
36
|
+
workflowId: string;
|
|
37
|
+
suggestionId: string;
|
|
38
|
+
suggestionDigest: string;
|
|
39
|
+
evidenceRefs: Array<{
|
|
40
|
+
type: string;
|
|
41
|
+
ref: string;
|
|
42
|
+
}>;
|
|
43
|
+
}): string;
|
|
44
|
+
export declare function isSuggestionReviewReceipt(value: unknown): value is WorkflowSuggestionReviewReceipt;
|
|
45
|
+
export declare function normalizeReviewDecision(value: string | undefined): SuggestionReviewDecision | undefined;
|
|
46
|
+
export declare function buildSuggestionReviewReceipt(params: {
|
|
47
|
+
snapshot: WorkflowSuggestionReviewSnapshot;
|
|
48
|
+
decision: SuggestionReviewDecision;
|
|
49
|
+
reviewedAt?: string;
|
|
50
|
+
}): WorkflowSuggestionReviewReceipt;
|
|
51
|
+
export declare function readSuggestionReviewReceipts(projectDir: string): Promise<WorkflowSuggestionReviewReceipt[]>;
|
|
52
|
+
export declare function findTerminalSuggestionReceipt(params: {
|
|
53
|
+
projectDir: string;
|
|
54
|
+
asset: string;
|
|
55
|
+
workflowId: string;
|
|
56
|
+
suggestionId: string;
|
|
57
|
+
bindingDigest: string;
|
|
58
|
+
}): Promise<WorkflowSuggestionReviewReceipt | undefined>;
|
|
59
|
+
export declare function appendSuggestionReviewReceipt(params: {
|
|
60
|
+
projectDir: string;
|
|
61
|
+
receipt: WorkflowSuggestionReviewReceipt;
|
|
62
|
+
}): Promise<{
|
|
63
|
+
path: string;
|
|
64
|
+
existing?: WorkflowSuggestionReviewReceipt;
|
|
65
|
+
}>;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { constants as fsConstants } from "node:fs";
|
|
3
|
+
import { lstat, mkdir, open, rm } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
export const WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION = "intentdna.workflow_suggestion_review_receipt.v1";
|
|
6
|
+
export const SUGGESTION_REVIEW_PATH = join(".dna", "reviews", "workflow-suggestions.jsonl");
|
|
7
|
+
export const SUGGESTION_REVIEW_STALE_LOCK_MS = 30_000;
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
function canonicalJson(value) {
|
|
12
|
+
if (value === null || typeof value !== "object")
|
|
13
|
+
return JSON.stringify(value) ?? "null";
|
|
14
|
+
if (Array.isArray(value))
|
|
15
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
16
|
+
const record = value;
|
|
17
|
+
return `{${Object.keys(record)
|
|
18
|
+
.filter((key) => record[key] !== undefined)
|
|
19
|
+
.sort()
|
|
20
|
+
.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`)
|
|
21
|
+
.join(",")}}`;
|
|
22
|
+
}
|
|
23
|
+
export function sha256Canonical(value) {
|
|
24
|
+
return createHash("sha256").update(canonicalJson(value)).digest("hex");
|
|
25
|
+
}
|
|
26
|
+
export function suggestionBindingDigest(params) {
|
|
27
|
+
return sha256Canonical({
|
|
28
|
+
asset: params.asset,
|
|
29
|
+
workflowId: params.workflowId,
|
|
30
|
+
suggestionId: params.suggestionId,
|
|
31
|
+
suggestionDigest: params.suggestionDigest,
|
|
32
|
+
evidenceRefs: params.evidenceRefs.map((ref) => `${ref.type}:${ref.ref}`).sort(),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export function isSuggestionReviewReceipt(value) {
|
|
36
|
+
if (!isRecord(value))
|
|
37
|
+
return false;
|
|
38
|
+
const decision = value.decision;
|
|
39
|
+
const evidenceRefs = value.evidence_refs;
|
|
40
|
+
if (value.schema_version !== WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION ||
|
|
41
|
+
typeof value.receipt_id !== "string" ||
|
|
42
|
+
typeof value.reviewed_at !== "string" ||
|
|
43
|
+
Number.isNaN(Date.parse(value.reviewed_at)) ||
|
|
44
|
+
typeof value.asset !== "string" ||
|
|
45
|
+
typeof value.workflow_id !== "string" ||
|
|
46
|
+
typeof value.suggestion_id !== "string" ||
|
|
47
|
+
(decision !== "accept" && decision !== "reject" && decision !== "defer") ||
|
|
48
|
+
typeof value.suggestion_digest !== "string" ||
|
|
49
|
+
!/^[a-f0-9]{64}$/.test(value.suggestion_digest) ||
|
|
50
|
+
typeof value.binding_digest !== "string" ||
|
|
51
|
+
!/^[a-f0-9]{64}$/.test(value.binding_digest) ||
|
|
52
|
+
value.source !== "k4_human_review" ||
|
|
53
|
+
!Array.isArray(evidenceRefs) ||
|
|
54
|
+
!evidenceRefs.every((ref) => isRecord(ref) && typeof ref.type === "string" && typeof ref.ref === "string")) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const expectedBinding = suggestionBindingDigest({
|
|
58
|
+
asset: value.asset,
|
|
59
|
+
workflowId: value.workflow_id,
|
|
60
|
+
suggestionId: value.suggestion_id,
|
|
61
|
+
suggestionDigest: value.suggestion_digest,
|
|
62
|
+
evidenceRefs: evidenceRefs,
|
|
63
|
+
});
|
|
64
|
+
return value.binding_digest === expectedBinding &&
|
|
65
|
+
value.receipt_id === `wsr_${expectedBinding.slice(0, 16)}_${decision}`;
|
|
66
|
+
}
|
|
67
|
+
export function normalizeReviewDecision(value) {
|
|
68
|
+
const normalized = value?.trim().toLowerCase();
|
|
69
|
+
if (normalized === "accept" || normalized === "reject" || normalized === "defer")
|
|
70
|
+
return normalized;
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
export function buildSuggestionReviewReceipt(params) {
|
|
74
|
+
const reviewedAt = params.reviewedAt ?? new Date().toISOString();
|
|
75
|
+
const suggestionDigest = sha256Canonical(params.snapshot.suggestion);
|
|
76
|
+
const evidenceRefs = params.snapshot.suggestion.evidenceRefs ?? [];
|
|
77
|
+
const bindingDigest = suggestionBindingDigest({
|
|
78
|
+
asset: params.snapshot.asset,
|
|
79
|
+
workflowId: params.snapshot.workflowId,
|
|
80
|
+
suggestionId: params.snapshot.suggestion.id,
|
|
81
|
+
suggestionDigest,
|
|
82
|
+
evidenceRefs,
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
schema_version: WORKFLOW_SUGGESTION_REVIEW_SCHEMA_VERSION,
|
|
86
|
+
receipt_id: `wsr_${bindingDigest.slice(0, 16)}_${params.decision}`,
|
|
87
|
+
reviewed_at: reviewedAt,
|
|
88
|
+
asset: params.snapshot.asset,
|
|
89
|
+
workflow_id: params.snapshot.workflowId,
|
|
90
|
+
suggestion_id: params.snapshot.suggestion.id,
|
|
91
|
+
decision: params.decision,
|
|
92
|
+
suggestion_digest: suggestionDigest,
|
|
93
|
+
binding_digest: bindingDigest,
|
|
94
|
+
evidence_refs: evidenceRefs,
|
|
95
|
+
source: "k4_human_review",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function assertSafeReviewDirectory(path, stats) {
|
|
99
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
100
|
+
throw new Error(`Refusing non-directory or symlinked K4 review path: ${path}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function existingProjectLocalDirectory(path) {
|
|
104
|
+
try {
|
|
105
|
+
const stats = await lstat(path);
|
|
106
|
+
assertSafeReviewDirectory(path, stats);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT")
|
|
111
|
+
return false;
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function ensureProjectLocalDirectory(path) {
|
|
116
|
+
if (await existingProjectLocalDirectory(path))
|
|
117
|
+
return;
|
|
118
|
+
try {
|
|
119
|
+
await mkdir(path, { recursive: false });
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (!(err && typeof err === "object" && "code" in err && err.code === "EEXIST"))
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
assertSafeReviewDirectory(path, await lstat(path));
|
|
126
|
+
}
|
|
127
|
+
async function ensureSuggestionReviewDirectory(projectDir, leaf) {
|
|
128
|
+
const dnaDir = join(projectDir, ".dna");
|
|
129
|
+
await ensureProjectLocalDirectory(dnaDir);
|
|
130
|
+
const directory = join(dnaDir, leaf);
|
|
131
|
+
await ensureProjectLocalDirectory(directory);
|
|
132
|
+
return directory;
|
|
133
|
+
}
|
|
134
|
+
async function readSuggestionReviewFile(path) {
|
|
135
|
+
const handle = await open(path, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
|
|
136
|
+
try {
|
|
137
|
+
return await handle.readFile("utf-8");
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
await handle.close();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function appendSuggestionReviewFile(path, line) {
|
|
144
|
+
const handle = await open(path, fsConstants.O_WRONLY | fsConstants.O_APPEND | fsConstants.O_CREAT | fsConstants.O_NOFOLLOW, 0o600);
|
|
145
|
+
try {
|
|
146
|
+
await handle.writeFile(line, "utf-8");
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
await handle.close();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function recoverStaleSuggestionReviewLock(lockDir, now) {
|
|
153
|
+
try {
|
|
154
|
+
const stats = await lstat(lockDir);
|
|
155
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
156
|
+
throw new Error(`Refusing non-directory or symlinked K4 review lock: ${lockDir}`);
|
|
157
|
+
}
|
|
158
|
+
if (now - stats.mtimeMs < SUGGESTION_REVIEW_STALE_LOCK_MS)
|
|
159
|
+
return false;
|
|
160
|
+
await rm(lockDir, { recursive: true, force: true });
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT")
|
|
165
|
+
return true;
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function withSuggestionReviewLock(projectDir, action) {
|
|
170
|
+
const locksDir = await ensureSuggestionReviewDirectory(projectDir, "locks");
|
|
171
|
+
const lockDir = join(locksDir, "workflow-suggestion-review.lock");
|
|
172
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
173
|
+
try {
|
|
174
|
+
await mkdir(lockDir, { recursive: false });
|
|
175
|
+
try {
|
|
176
|
+
return await action();
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
await rm(lockDir, { recursive: true, force: true });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
184
|
+
if (await recoverStaleSuggestionReviewLock(lockDir, Date.now()))
|
|
185
|
+
continue;
|
|
186
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
throw err;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
throw new Error("Timed out waiting for workflow suggestion review lock");
|
|
193
|
+
}
|
|
194
|
+
export async function readSuggestionReviewReceipts(projectDir) {
|
|
195
|
+
const dnaDir = join(projectDir, ".dna");
|
|
196
|
+
if (!await existingProjectLocalDirectory(dnaDir))
|
|
197
|
+
return [];
|
|
198
|
+
const reviewsDir = join(dnaDir, "reviews");
|
|
199
|
+
if (!await existingProjectLocalDirectory(reviewsDir))
|
|
200
|
+
return [];
|
|
201
|
+
const path = join(projectDir, SUGGESTION_REVIEW_PATH);
|
|
202
|
+
try {
|
|
203
|
+
const raw = await readSuggestionReviewFile(path);
|
|
204
|
+
return raw.split("\n").filter((line) => line.trim().length > 0).flatMap((line) => {
|
|
205
|
+
try {
|
|
206
|
+
const parsed = JSON.parse(line);
|
|
207
|
+
if (isSuggestionReviewReceipt(parsed))
|
|
208
|
+
return [parsed];
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Ignore corrupt historical receipt lines; validation remains fail-closed.
|
|
212
|
+
}
|
|
213
|
+
return [];
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT")
|
|
218
|
+
return [];
|
|
219
|
+
throw err;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
export async function findTerminalSuggestionReceipt(params) {
|
|
223
|
+
const receipts = await readSuggestionReviewReceipts(params.projectDir);
|
|
224
|
+
return receipts.find((receipt) => receipt.asset === params.asset &&
|
|
225
|
+
receipt.workflow_id === params.workflowId &&
|
|
226
|
+
receipt.suggestion_id === params.suggestionId &&
|
|
227
|
+
receipt.binding_digest === params.bindingDigest);
|
|
228
|
+
}
|
|
229
|
+
export async function appendSuggestionReviewReceipt(params) {
|
|
230
|
+
return withSuggestionReviewLock(params.projectDir, async () => {
|
|
231
|
+
const existing = await findTerminalSuggestionReceipt({
|
|
232
|
+
projectDir: params.projectDir,
|
|
233
|
+
asset: params.receipt.asset,
|
|
234
|
+
workflowId: params.receipt.workflow_id,
|
|
235
|
+
suggestionId: params.receipt.suggestion_id,
|
|
236
|
+
bindingDigest: params.receipt.binding_digest,
|
|
237
|
+
});
|
|
238
|
+
if (existing)
|
|
239
|
+
return { path: join(params.projectDir, SUGGESTION_REVIEW_PATH), existing };
|
|
240
|
+
const reviewsDir = await ensureSuggestionReviewDirectory(params.projectDir, "reviews");
|
|
241
|
+
const path = join(reviewsDir, "workflow-suggestions.jsonl");
|
|
242
|
+
await appendSuggestionReviewFile(path, JSON.stringify(params.receipt) + "\n");
|
|
243
|
+
return { path };
|
|
244
|
+
});
|
|
245
|
+
}
|
package/package.json
CHANGED
package/spec/README.md
CHANGED
|
@@ -1,58 +1,25 @@
|
|
|
1
1
|
# Intent DNA — Spec Index
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Status: normative
|
|
4
4
|
|
|
5
|
-
This directory
|
|
5
|
+
This directory keeps only technical contracts still referenced by the current constitution and roadmap. Use [`../DESIGN.md`](../DESIGN.md) as the architecture authority and [`../ROADMAP.md`](../ROADMAP.md) as the milestone authority.
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
- **Canonical** — current contract or design reference.
|
|
10
|
-
- **Active reference** — still useful for current implementation and maintenance.
|
|
11
|
-
- **Completed / historical** — implementation handoff or bugfix record; use for context before changing the related area.
|
|
12
|
-
- **Deferred** — design direction captured, not currently being built.
|
|
13
|
-
|
|
14
|
-
## Specs
|
|
7
|
+
## Retained Specs
|
|
15
8
|
|
|
16
9
|
| Spec | Status | Purpose |
|
|
17
|
-
|
|
18
|
-
| [schema-spec.md](schema-spec.md) | Canonical | Intent DNA
|
|
19
|
-
| [
|
|
20
|
-
| [
|
|
21
|
-
| [
|
|
22
|
-
|
|
|
23
|
-
| [multi-config.md](multi-config.md) | Active reference | Multi-template config management, namespace conflicts, template version tracking. |
|
|
24
|
-
| [template-version-namespace-fix.md](template-version-namespace-fix.md) | Completed / historical | Template content hash and namespace-aware cleanup fix plan. |
|
|
25
|
-
| [flutter-rewrite-template-optimization.md](flutter-rewrite-template-optimization.md) | Active reference | Dogfood template optimization for behavior-lock and rescue workflows. |
|
|
26
|
-
| [agent-dispatch-fix.md](agent-dispatch-fix.md) | Completed / historical | F5 agent dispatch vulnerability repair plan. |
|
|
27
|
-
| [control-plane-convergence-handoff-2026-04-24.md](control-plane-convergence-handoff-2026-04-24.md) | Completed / historical | Control-plane convergence handoff and remaining follow-up context. |
|
|
28
|
-
|
|
29
|
-
## By implementation area
|
|
30
|
-
|
|
31
|
-
### Schema and compiler
|
|
32
|
-
|
|
33
|
-
- [schema-spec.md](schema-spec.md)
|
|
34
|
-
- [multi-config.md](multi-config.md)
|
|
35
|
-
- [template-version-namespace-fix.md](template-version-namespace-fix.md)
|
|
36
|
-
|
|
37
|
-
### Hooks and governance
|
|
38
|
-
|
|
39
|
-
- [hooks-infra-harness-hardening.md](hooks-infra-harness-hardening.md)
|
|
40
|
-
- [foundation-hardening.md](foundation-hardening.md)
|
|
41
|
-
- [parallel-isolation.md](parallel-isolation.md)
|
|
42
|
-
|
|
43
|
-
### Workflows and templates
|
|
44
|
-
|
|
45
|
-
- [workflow-pipeline.md](workflow-pipeline.md)
|
|
46
|
-
- [flutter-rewrite-template-optimization.md](flutter-rewrite-template-optimization.md)
|
|
47
|
-
- [agent-dispatch-fix.md](agent-dispatch-fix.md)
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| [`schema-spec.md`](schema-spec.md) | Canonical | Intent DNA schema, cascade, activation, RuntimeDecisionEvent, and Constraint IR contract. |
|
|
12
|
+
| [`codex-adapter-contract.md`](codex-adapter-contract.md) | Active contract | Codex CLI adapter boundary, unsupported-field handling, and provenance mapping. |
|
|
13
|
+
| [`workflow-capability-ir.md`](workflow-capability-ir.md) | Active reference | AI-native workflow capability vocabulary and mapping from workflow fields to capability requirements. |
|
|
14
|
+
| [`sync-target-plan.md`](sync-target-plan.md) | Active reference | Boundary between `dna sync` orchestration and harness-specific target artifact planning. |
|
|
15
|
+
| `README.md` | Navigation | This retained spec index. |
|
|
48
16
|
|
|
49
|
-
|
|
17
|
+
## Archived Specs
|
|
50
18
|
|
|
51
|
-
|
|
52
|
-
- [foundation-hardening.md](foundation-hardening.md)
|
|
19
|
+
Historical handoffs, completed repair plans, and deferred implementation notes moved to [`../docs/archive/2026H1/spec/`](../docs/archive/2026H1/spec/). They can provide context, but they are not current requirements unless a retained spec, ADR, or roadmap entry explicitly cites them.
|
|
53
20
|
|
|
54
|
-
## Maintenance
|
|
21
|
+
## Maintenance Rules
|
|
55
22
|
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
23
|
+
- Add a new retained spec only when `DESIGN.md`, `ROADMAP.md`, or an ADR needs a durable technical contract.
|
|
24
|
+
- Move one-time plans, repair notes, and handoffs directly to archive.
|
|
25
|
+
- Keep links from retained specs pointed at current contracts or explicit archive paths.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Codex Adapter Contract Draft
|
|
2
|
+
|
|
3
|
+
Status: draft for v1.8.0 contract freeze
|
|
4
|
+
Last updated: 2026-05-28
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
|
|
8
|
+
This contract covers only the Codex CLI adapter. Cursor, Cline, Gemini, AgentScope, PromptAdapter, and other adapters are out of scope unless `ROADMAP.md` changes.
|
|
9
|
+
|
|
10
|
+
The contract freezes the adapter boundary before implementation. It does not add a runtime skeleton, state subsystem, log subsystem, MCP subsystem, or dashboard feature.
|
|
11
|
+
|
|
12
|
+
The nearest implementation reference is OMX / `oh-my-codex@0.18.6`. OMX is not a dependency for Intent DNA; it is source/runtime evidence for how a Codex-native orchestration layer handles plugin-scoped hooks, fallback `.codex/hooks.json`, setup refresh, and hook trust state.
|
|
13
|
+
|
|
14
|
+
## Baseline assumptions
|
|
15
|
+
|
|
16
|
+
- Target runtime: Codex CLI `>= 0.134.0` for the first hook-like dogfood path.
|
|
17
|
+
- Reference implementation: OMX / `oh-my-codex@0.18.6`.
|
|
18
|
+
- Local probe requirement: adapter dogfood must record the actual `codex` executable path and version. If unavailable, set runtime version evidence to `unknown` and classify events as diagnostic until verified.
|
|
19
|
+
- Source-level completion and runtime-verified enforcement are separate claims. Fixtures may prove artifact generation, trust downgrade, and RuntimeDecisionEvent writing without local Codex; only a trusted real Codex hook execution may prove runtime enforcement.
|
|
20
|
+
- Enforcement posture: prompt files are soft guidance; permissions/rules/hooks are stronger guardrails; Codex hooks are not a complete enforcement boundary.
|
|
21
|
+
- Plugin posture: plugin-bundled hooks are supported by current docs and used by OMX, but they are non-managed hooks and must be reviewed/trusted before execution.
|
|
22
|
+
- Fallback posture: adapter-managed `.codex/hooks.json` entries can be made idempotent and trust-aware, following OMX's owned-wrapper and `hooks.state` trusted-hash pattern.
|
|
23
|
+
- Evidence posture: `.dna/compiled/codex-adapter-evidence.json` is adapter/config/probe evidence only. Primary RuntimeDecisionEvent evidence must be appended through `appendRuntimeDecisionEvent()` into `.dna/state/runtime-decisions/` and session-local runtime decision JSONL files.
|
|
24
|
+
|
|
25
|
+
## Inputs
|
|
26
|
+
|
|
27
|
+
The adapter consumes:
|
|
28
|
+
|
|
29
|
+
| Input | Required | Description |
|
|
30
|
+
|---|---:|---|
|
|
31
|
+
| `constraint_ir` | yes | Compiled Intent DNA Constraint IR. |
|
|
32
|
+
| `provenance_manifest` | yes | Policy bundle id/version, cascade layer fingerprints, compiled IR hash, and source fingerprints. |
|
|
33
|
+
| `project_root` | yes | Repository root for Codex project artifacts. |
|
|
34
|
+
| `codex_home` | optional | Codex home override for user/global config probes. |
|
|
35
|
+
| `role_context` | optional | Active Intent DNA role, workflow step, and scope. Missing values become `unknown`. |
|
|
36
|
+
| `adapter_mode` | yes | `interactive`, `exec`, or `dogfood_probe`. |
|
|
37
|
+
| `hook_install_mode` | yes | `plugin_scoped`, `project_fallback`, `managed`, or `none`. |
|
|
38
|
+
| `managed_policy` | optional | Whether the deployment can write/administer managed hooks or only project/plugin artifacts. |
|
|
39
|
+
|
|
40
|
+
## Outputs
|
|
41
|
+
|
|
42
|
+
The adapter may produce these artifacts once implementation starts:
|
|
43
|
+
|
|
44
|
+
| Artifact | Purpose | Support posture |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| Codex instruction artifact | Carries `prompt_directives` into Codex instruction loading. | Partial. Use an owned generated block/file; do not overwrite user-authored `AGENTS.md` content without a block protocol. |
|
|
47
|
+
| Codex permission/rule artifact | Narrows filesystem, network, and command execution behavior. | Partial. Maps strongest to Codex permissions/rules, with explicit unsupported gaps. |
|
|
48
|
+
| Plugin-scoped hook artifact | Packages hooks through Codex plugin metadata, matching OMX's `plugins/oh-my-codex/.codex-plugin/plugin.json` + `hooks/hooks.json` pattern. | Distribution surface. Must not be considered active enforcement until trust is verified. |
|
|
49
|
+
| Project/fallback hook artifact | Writes owned `.codex/hooks.json` entries and associated trust-state metadata when appropriate. | Stronger dogfood surface when generated entries are trusted and ownership is tracked. Preserve user hooks. |
|
|
50
|
+
| Codex exec probe command | Runs `codex exec --json` and optional `--output-schema` for dogfood validation. | Partial. Useful for automation and evidence, not enough for interactive parity alone. |
|
|
51
|
+
| Adapter evidence artifact | Writes `.dna/compiled/codex-adapter-evidence.json` with adapter/config/probe fingerprints, install-mode semantics, support status, and unsupported capabilities. | Diagnostic/config evidence only; never primary runtime evidence. |
|
|
52
|
+
| RuntimeDecisionEvent evidence | Emits Intent DNA-compatible runtime decisions through existing state writers. | Adapter-generated; not native Codex/OMX output. Enterprise classification requires trusted hook execution and complete provenance. |
|
|
53
|
+
|
|
54
|
+
## Install modes
|
|
55
|
+
|
|
56
|
+
| Mode | Writes | Trust rule | Evidence classification |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| `plugin_scoped` | Plugin manifest + plugin hooks + adapter evidence. | Plugin hook identity must be reviewed/trusted and backed by runtime execution evidence before enforcement can be claimed. | Diagnostic until verified. |
|
|
59
|
+
| `project_fallback` | Plugin artifacts, adapter evidence, owned `.codex/hooks.json`, and owned `.codex/config.toml` trust-state block. | Generated wrapper identity, `hooks.state` hash, runtime probe, runtime execution evidence, and provenance must all match. | May become enterprise evidence only when all trust inputs are complete. |
|
|
60
|
+
| `managed` | Same source-level files as fallback until a managed root/pointer is implemented. | Managed root, runner hash, project pointer, runtime probe, execution evidence, and provenance must all match; this source-level slice does not yet collect managed proof. | Diagnostic-only until managed proof fields exist and pass. |
|
|
61
|
+
| `none` | Adapter evidence only. | No runtime trust exists. | Unsupported/diagnostic only. |
|
|
62
|
+
|
|
63
|
+
## Hook architecture contract
|
|
64
|
+
|
|
65
|
+
The first implementation should copy the OMX split, not merely emit plugin hooks:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
Codex plugin install path
|
|
69
|
+
.codex-plugin/plugin.json -> hooks: ./hooks/hooks.json
|
|
70
|
+
hooks/hooks.json -> one dispatcher command
|
|
71
|
+
dispatcher -> Intent DNA Codex hook runner
|
|
72
|
+
|
|
73
|
+
Fallback/project path
|
|
74
|
+
.codex/hooks.json -> owned generated wrapper entries
|
|
75
|
+
.codex/config.toml -> hook trust state when safe and supported
|
|
76
|
+
preserve user hook entries and user trust state
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Required hook ownership rules:
|
|
80
|
+
|
|
81
|
+
1. Generated hook entries must be recognizable as Intent DNA-owned wrappers.
|
|
82
|
+
2. Refresh must strip/rewrite only Intent DNA-owned wrappers.
|
|
83
|
+
3. Refresh must preserve user hook entries.
|
|
84
|
+
4. Uninstall must remove only Intent DNA-owned wrappers and keep hook files if user hooks remain.
|
|
85
|
+
5. Trust-state writes must be tied to the generated hook identity and recorded as evidence.
|
|
86
|
+
6. Plugin-scoped hooks and fallback/project hooks must be recorded separately in evidence.
|
|
87
|
+
|
|
88
|
+
## Constraint IR mapping contract
|
|
89
|
+
|
|
90
|
+
| Constraint IR channel | Adapter behavior |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `prompt_directives` | Render to Codex instruction context. Mark as soft guidance. Preserve source/provenance comments or metadata outside the user-visible instruction body where possible. |
|
|
93
|
+
| `tool_filters` | Map filesystem/network/tool-command restrictions to permissions and `.rules` first; add hook checks for supported `PreToolUse` paths. Mark all uncovered paths `unsupported`. |
|
|
94
|
+
| `pre_execution_gates` | Prefer managed hooks when available. Otherwise use project/fallback hooks with verified trust state. Plugin hooks may carry the same gate logic but cannot be treated as active until trust is confirmed. |
|
|
95
|
+
| `post_execution_validators` | Map to `PostToolUse`, `Stop`, `codex exec --output-schema`, and adapter-side report checks. Do not claim rollback. |
|
|
96
|
+
| `context_injections` | Map static context to instruction files and event-limited dynamic context to hook output where supported. Unsupported dynamic contexts remain explicit. |
|
|
97
|
+
|
|
98
|
+
## RuntimeDecisionEvent mapping draft
|
|
99
|
+
|
|
100
|
+
Codex adapter events must satisfy the existing `RuntimeDecisionEvent` schema. Required fields may use `unknown` or `unsupported`, but such events remain diagnostic rather than enterprise-authoritative until provenance is complete.
|
|
101
|
+
|
|
102
|
+
The mapping table describes the logical source before persistence. Disk writes through `appendRuntimeDecisionEvent()` project untrusted identity, project, session, run, resource, source-ref, evidence-ref, tool, and reason fields with stable domain-separated SHA-256 labels. Controlled policy, gene, decision, and hook-action identifiers remain readable; same-call UUID/SHA evidence ids remain intact for C4/C5/trace binding. HookOutput may keep actionable user-facing text; persisted C4/C5 JSONL must not contain raw commands, local paths, session ids, identity/correlation ids, or arbitrary secret-shaped strings.
|
|
103
|
+
|
|
104
|
+
| RuntimeDecisionEvent field | Codex / adapter source |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `schema_version` | `intentdna.runtime_decision_event.v1.7.1`. |
|
|
107
|
+
| `event_id` | Adapter-generated stable id per decision. |
|
|
108
|
+
| `timestamp` | Adapter timestamp at decision emission. |
|
|
109
|
+
| `org_id`, `team_id`, `user_id`, `project_id` | Intent DNA config/provenance; projected on disk; `unknown` if not configured. |
|
|
110
|
+
| `agent_id` | Codex hook/session/subagent identity where available in `>=0.134.0`; projected on disk; otherwise adapter-generated or `unknown`. |
|
|
111
|
+
| `agent_role` | Active Intent DNA role; projected on disk; `unknown` if no role context exists. |
|
|
112
|
+
| `agent_type` | `codex_cli` or `codex_subagent` when known; projected on disk. |
|
|
113
|
+
| `session_agent` | Codex session/subagent identity when provided; projected on disk; otherwise `unknown`. |
|
|
114
|
+
| `harness_adapter` | `codex_cli`. |
|
|
115
|
+
| `runtime` | `codex_cli@<version>` when probed; `codex_cli@unknown` when unavailable. |
|
|
116
|
+
| `policy_bundle_id`, `policy_bundle_version` | Provenance manifest. |
|
|
117
|
+
| `cascade_layers` | Provenance manifest layer fingerprints; unavailable layers must be explicit `unknown` / `unsupported`. |
|
|
118
|
+
| `winning_constraint` | Adapter-selected constraint that produced the decision. |
|
|
119
|
+
| `compiled_ir_hash` | Provenance manifest compiled IR hash. |
|
|
120
|
+
| `decision` | Adapter decision: `allow`, `warn`, `block`, `escalate`, or `validate`. |
|
|
121
|
+
| `decision_reason` | Human-readable reason derived from matching constraint and Codex event context; projected on disk. |
|
|
122
|
+
| `enforcement_point` | `hook`, `plugin_runtime`, `ci`, or `unsupported` depending on source. Use `hook` for trusted project/fallback/managed hooks; use `plugin_runtime` only for trusted plugin hook execution. |
|
|
123
|
+
| `harness_runtime_context` | Mirror agent/runtime fields above. |
|
|
124
|
+
| `session_id` | Codex session id from hook/JSONL if available; projected on disk; otherwise adapter-generated run id or `unknown`. |
|
|
125
|
+
| `run_id` | Adapter run id, preferably tied to a `codex exec --json` capture or interactive session capture; projected on disk. |
|
|
126
|
+
| `step_id` | Workflow step id when running under Intent DNA workflow; otherwise `unknown`. |
|
|
127
|
+
| `tool_name` | Hook input tool name, command kind, MCP server/tool name, or `unknown`; projected on disk. |
|
|
128
|
+
| `action_kind` | Controlled hook event/action class such as `PreToolUse`, `PostToolUse`, `PermissionRequest`, `rule_check`, or `exec_final_schema`; retained on disk for decision audit. |
|
|
129
|
+
| `resource_ref` | Command, file path, MCP resource, plugin hook id, fallback hook path, or `unknown`; projected on disk. |
|
|
130
|
+
| `evidence_refs` | References to hook payload artifacts, JSONL exec events, generated config fingerprints, hook trust-state fingerprints, reports, or `unsupported` entries; projected on disk unless a C5 fact must preserve its C4 `runtime_decision_event` id binding. |
|
|
131
|
+
|
|
132
|
+
## Trust and classification rules
|
|
133
|
+
|
|
134
|
+
1. Never omit a required `RuntimeDecisionEvent` field.
|
|
135
|
+
2. Use `unknown` for unavailable-but-conceptually-mappable values.
|
|
136
|
+
3. Use `unsupported` for values Codex cannot provide or surfaces the adapter cannot intercept.
|
|
137
|
+
4. Do not classify plugin-hook decisions as active enforcement until the hook definition has been reviewed/trusted or is delivered through managed policy.
|
|
138
|
+
5. Project/fallback hook decisions may be classified as active only when the adapter proves all of: generated wrapper identity, matching `hooks.state` hash, Codex runtime probe, hook execution evidence, and complete RuntimeDecisionEvent provenance.
|
|
139
|
+
6. Any required provenance field left `unknown` / `unsupported` keeps the event diagnostic-only under the existing RuntimeDecisionEvent validation semantics.
|
|
140
|
+
7. `CodexAdapterSupportStatus` remains `supported | partial | unknown | unsupported`; diagnostic-only is a RuntimeDecisionEvent/evidence classification, not a support enum value.
|
|
141
|
+
8. `PermissionRequest`, `SubagentStart`, and `SubagentStop` remain explicitly unsupported until hook I/O fixtures are frozen and tested.
|
|
142
|
+
|
|
143
|
+
## Minimal dogfood path
|
|
144
|
+
|
|
145
|
+
The first implementation milestone after this contract should:
|
|
146
|
+
|
|
147
|
+
1. Probe `codex` availability and version.
|
|
148
|
+
2. Generate a Codex instruction artifact for one narrow role/workflow.
|
|
149
|
+
3. Generate a narrow permissions/rules artifact for the same role scope.
|
|
150
|
+
4. Generate plugin-scoped hook metadata for distribution.
|
|
151
|
+
5. Generate an owned project/fallback hook entry for one pre-execution gate, preserving user hooks.
|
|
152
|
+
6. Record generated hook identity and trust-state evidence where supported.
|
|
153
|
+
7. Run one `codex exec --json` workflow.
|
|
154
|
+
8. Emit at least one RuntimeDecisionEvent-compatible artifact with complete provenance where possible and explicit placeholders otherwise.
|
|
155
|
+
|
|
156
|
+
## Non-goals
|
|
157
|
+
|
|
158
|
+
- No implementation of other adapters.
|
|
159
|
+
- No new Intent DNA runtime/state/log/MCP infrastructure.
|
|
160
|
+
- No hard dependency on OMX unless explicitly approved later.
|
|
161
|
+
- No claim of full Claude Code hook parity.
|
|
162
|
+
- No claim that plugin-bundled hooks are guaranteed before trust review.
|
|
163
|
+
- No enterprise compliance statistics from diagnostic-only Codex events.
|
|
164
|
+
|
|
165
|
+
## Sources
|
|
166
|
+
|
|
167
|
+
- RuntimeDecisionEvent schema: `src/governance/runtime-decision-event.ts`
|
|
168
|
+
- Enterprise provenance contract: `spec/schema-spec.md#enterprise-provenance-contract-v171`
|
|
169
|
+
- Codex runtime notes: `docs/archive/2026H1/references/codex-cli-runtime-notes.md`
|
|
170
|
+
- Codex capability matrix: `docs/archive/2026H1/references/codex-adapter-capability-matrix.md`
|
|
171
|
+
- OMX package: `oh-my-codex@0.18.6`
|
|
172
|
+
- OMX reference implementation files inspected from npm package:
|
|
173
|
+
- `plugins/oh-my-codex/.codex-plugin/plugin.json`
|
|
174
|
+
- `plugins/oh-my-codex/hooks/hooks.json`
|
|
175
|
+
- `dist/config/codex-hooks.js`
|
|
176
|
+
- `dist/scripts/codex-native-hook.js`
|