@kontourai/flow-agents 3.9.0 → 3.10.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/.github/workflows/ci.yml +8 -0
- package/CHANGELOG.md +17 -0
- package/README.md +1 -1
- package/build/src/cli/assignment-provider.js +4 -18
- package/build/src/cli/continuation-adapter.d.ts +10 -8
- package/build/src/cli/continuation-adapter.js +22 -4
- package/build/src/cli/validate-workflow-artifacts.js +21 -1
- package/build/src/cli/workflow-sidecar.js +15 -20
- package/build/src/cli/workflow.js +58 -11
- package/build/src/continuation-driver.d.ts +27 -3
- package/build/src/continuation-driver.js +97 -14
- package/build/src/index.d.ts +2 -2
- package/build/src/index.js +1 -1
- package/build/src/tools/build-universal-bundles.js +52 -25
- package/build/src/tools/validate-source-tree.js +5 -2
- package/context/scripts/hooks/lib/continuation-turn-authority.js +386 -0
- package/context/scripts/hooks/stop-goal-fit.js +244 -73
- package/context/scripts/hooks/workflow-steering.js +24 -15
- package/context/scripts/telemetry/lib/pricing.sh +18 -6
- package/context/scripts/telemetry/lib/transport.sh +139 -37
- package/context/scripts/telemetry/lib/usage.sh +282 -32
- package/context/scripts/telemetry/lib/usage_model_guard.sh +42 -0
- package/context/scripts/telemetry/telemetry.sh +76 -1
- package/docs/coordination-guide.md +21 -5
- package/docs/fixture-ownership.md +2 -1
- package/docs/public-workflow-cli.md +44 -0
- package/docs/spec/runtime-hook-surface.md +8 -4
- package/evals/acceptance/prove-capture-teeth-declared.sh +13 -0
- package/evals/acceptance/prove-capture-teeth.sh +13 -0
- package/evals/ci/run-baseline.sh +2 -0
- package/evals/fixtures/codex-legacy-agents/5273878130bdafc8a024a650bb5b66c9b003f1f859b5dc6e5b588cbf4ab23228.md +25 -0
- package/evals/fixtures/telemetry/usage-transcript-adversarial.jsonl +2 -0
- package/evals/fixtures/telemetry/usage-transcript-malformed-sandwich.jsonl +3 -0
- package/evals/fixtures/telemetry/usage-transcript-negative-tokens.jsonl +1 -0
- package/evals/fixtures/telemetry/usage-transcript-oversized-prefix.jsonl +201 -0
- package/evals/fixtures/telemetry/usage-transcript-oversized-tokens.jsonl +1 -0
- package/evals/fixtures/telemetry/usage-transcript-prefixed-secret-lower.jsonl +1 -0
- package/evals/fixtures/telemetry/usage-transcript-prefixed-secret-upper.jsonl +1 -0
- package/evals/fixtures/telemetry/usage-transcript-secret-model-jwt.jsonl +1 -0
- package/evals/fixtures/telemetry/usage-transcript-secret-model.jsonl +1 -0
- package/evals/fixtures/telemetry/usage-transcript-torn-trailing.jsonl +2 -0
- package/evals/integration/test_actor_identity.sh +63 -0
- package/evals/integration/test_assignment_provider_local_file.sh +34 -0
- package/evals/integration/test_builder_entry_enforcement.sh +5 -1
- package/evals/integration/test_bundle_install.sh +106 -17
- package/evals/integration/test_bundle_lifecycle.sh +17 -3
- package/evals/integration/test_captured_fail_reconciliation.sh +11 -0
- package/evals/integration/test_ci_actor_identity.sh +2 -2
- package/evals/integration/test_command_log_concurrency.sh +11 -0
- package/evals/integration/test_command_log_fork_classification.sh +11 -0
- package/evals/integration/test_command_log_integrity.sh +11 -0
- package/evals/integration/test_current_json_per_actor.sh +416 -21
- package/evals/integration/test_enforcer_expects_driven.sh +11 -0
- package/evals/integration/test_ensure_session_ownership_guard.sh +39 -0
- package/evals/integration/test_evidence_capture_hook.sh +25 -6
- package/evals/integration/test_fixture_retirement_audit.sh +2 -2
- package/evals/integration/test_flowdef_union_floor_regression.sh +11 -0
- package/evals/integration/test_gate_bypass_chain.sh +11 -0
- package/evals/integration/test_gate_lockdown.sh +10 -0
- package/evals/integration/test_goal_fit_ghost_session.sh +11 -0
- package/evals/integration/test_goal_fit_hook.sh +257 -9
- package/evals/integration/test_goal_fit_rederive.sh +11 -0
- package/evals/integration/test_install_merge.sh +141 -3
- package/evals/integration/test_liveness_conflict_injection.sh +39 -3
- package/evals/integration/test_liveness_heartbeat.sh +46 -9
- package/evals/integration/test_phase_map_and_gate_claim.sh +10 -1
- package/evals/integration/test_public_workflow_cli.sh +6 -6
- package/evals/integration/test_session_resume_roundtrip.sh +30 -0
- package/evals/integration/test_stop_hook_release.sh +111 -11
- package/evals/integration/test_telemetry_tool_usage.sh +394 -0
- package/evals/integration/test_verify_hold.sh +64 -1
- package/evals/integration/test_workflow_sidecar_writer.sh +10 -1
- package/evals/integration/test_workflow_steering_hook.sh +20 -4
- package/evals/run.sh +2 -0
- package/evals/static/test_universal_bundles.sh +123 -0
- package/package.json +1 -1
- package/packaging/README.md +21 -0
- package/packaging/codex-legacy-agents-fingerprints.json +33 -0
- package/scripts/README.md +2 -1
- package/scripts/audit-codex-legacy-agents.js +43 -0
- package/scripts/classify-codex-legacy-agents.js +71 -0
- package/scripts/hooks/evidence-capture.js +18 -6
- package/scripts/hooks/lib/actor-identity.js +62 -29
- package/scripts/hooks/lib/continuation-turn-authority.js +386 -0
- package/scripts/hooks/lib/current-pointer.js +114 -12
- package/scripts/hooks/lib/liveness-heartbeat.js +15 -12
- package/scripts/hooks/stop-goal-fit.js +244 -73
- package/scripts/hooks/workflow-steering.js +24 -15
- package/scripts/install-codex-home.sh +8 -7
- package/scripts/telemetry/lib/pricing.sh +18 -6
- package/scripts/telemetry/lib/transport.sh +71 -0
- package/scripts/telemetry/lib/usage.sh +282 -32
- package/scripts/telemetry/lib/usage_model_guard.sh +42 -0
- package/scripts/telemetry/telemetry.sh +76 -1
- package/src/cli/assignment-provider.ts +5 -26
- package/src/cli/builder-flow-runtime.test.mjs +93 -6
- package/src/cli/continuation-adapter.ts +33 -7
- package/src/cli/continuation-driver.test.mjs +741 -2
- package/src/cli/public-api.test.mjs +1 -0
- package/src/cli/validate-workflow-artifacts.ts +19 -1
- package/src/cli/workflow-sidecar.ts +18 -23
- package/src/cli/workflow.ts +71 -11
- package/src/continuation-driver.ts +125 -19
- package/src/index.ts +4 -0
- package/src/tools/build-universal-bundles.ts +61 -25
- package/src/tools/validate-source-tree.ts +5 -2
|
@@ -4,11 +4,19 @@ import { randomUUID } from "node:crypto";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { inspectBuilderFlowSession, syncBuilderFlowSession } from "./builder-flow-runtime.js";
|
|
6
6
|
import { atomicWriteJson, ensureSafeDirectory } from "./lib/fs.js";
|
|
7
|
+
export class ContinuationAdapterTimeoutError extends Error {
|
|
8
|
+
code = "CONTINUATION_ADAPTER_TIMEOUT";
|
|
9
|
+
constructor(timeoutMs) {
|
|
10
|
+
super(`continuation adapter timed out after ${timeoutMs}ms`);
|
|
11
|
+
this.name = "ContinuationAdapterTimeoutError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
7
14
|
export async function runContinuationDriver(input) {
|
|
8
15
|
assertMaxTurns(input.maxTurns);
|
|
9
16
|
const now = input.now ?? (() => new Date());
|
|
10
17
|
const waitForBarrier = input.waitForBarrier ?? (async () => "pending");
|
|
11
18
|
const authorizeTurn = input.authorizeTurn ?? (async () => { });
|
|
19
|
+
const issueTurnAuthority = input.issueTurnAuthority;
|
|
12
20
|
const adapterCommandIdentity = input.adapterCommandIdentity ?? null;
|
|
13
21
|
let snapshot = validateSnapshot(await input.runtime.inspect());
|
|
14
22
|
let state = loadOrCreateState(input.store, snapshot, input.maxTurns, adapterCommandIdentity, now);
|
|
@@ -25,10 +33,10 @@ export async function runContinuationDriver(input) {
|
|
|
25
33
|
const barrier = state.pending_barrier;
|
|
26
34
|
const readiness = await waitForBarrier(barrier);
|
|
27
35
|
if (readiness === "pending") {
|
|
28
|
-
state = saveState(input.store, state, { status: "waiting" }, now);
|
|
36
|
+
state = saveState(input.store, state, { status: "waiting", active_turn_step: null, active_turn_public_key_digest: null }, now);
|
|
29
37
|
return { outcome: "waiting", turns_started: state.turns_started, snapshot, barrier };
|
|
30
38
|
}
|
|
31
|
-
state = saveState(input.store, state, { status: "active", pending_barrier: null }, now);
|
|
39
|
+
state = saveState(input.store, state, { status: "active", active_turn_step: null, active_turn_public_key_digest: null, pending_barrier: null }, now);
|
|
32
40
|
appendEvent(input.store, state, snapshot, "resumed", now, { barrier });
|
|
33
41
|
}
|
|
34
42
|
snapshot = validateSnapshot(await input.runtime.synchronize());
|
|
@@ -39,17 +47,25 @@ export async function runContinuationDriver(input) {
|
|
|
39
47
|
if (initialOutcome === "failed")
|
|
40
48
|
return finishFailed(input.store, state, snapshot, now);
|
|
41
49
|
if (initialOutcome === "waiting") {
|
|
42
|
-
state = saveState(input.store, state, { status: "waiting" }, now);
|
|
50
|
+
state = saveState(input.store, state, { status: "waiting", active_turn_step: null, active_turn_public_key_digest: null }, now);
|
|
43
51
|
return { outcome: "waiting", turns_started: state.turns_started, snapshot };
|
|
44
52
|
}
|
|
45
53
|
while (state.turns_started < input.maxTurns) {
|
|
46
54
|
await authorizeTurn();
|
|
47
55
|
const iteration = state.turns_started + 1;
|
|
48
|
-
state = saveState(input.store, state, {
|
|
56
|
+
state = saveState(input.store, state, {
|
|
57
|
+
status: "active",
|
|
58
|
+
turns_started: iteration,
|
|
59
|
+
active_turn_step: snapshot.current_step,
|
|
60
|
+
active_turn_public_key_digest: null,
|
|
61
|
+
}, now);
|
|
49
62
|
appendEvent(input.store, state, snapshot, "turn_started", now);
|
|
50
63
|
let result;
|
|
64
|
+
let request;
|
|
65
|
+
let authority;
|
|
66
|
+
let terminalized = false;
|
|
51
67
|
try {
|
|
52
|
-
|
|
68
|
+
request = Object.freeze({
|
|
53
69
|
schema_version: "1.0",
|
|
54
70
|
run_id: snapshot.run_id,
|
|
55
71
|
definition_id: snapshot.definition_id,
|
|
@@ -57,23 +73,61 @@ export async function runContinuationDriver(input) {
|
|
|
57
73
|
iteration,
|
|
58
74
|
max_turns: input.maxTurns,
|
|
59
75
|
next_action: snapshot.next_action ? structuredClone(snapshot.next_action) : null,
|
|
60
|
-
})
|
|
76
|
+
});
|
|
77
|
+
authority = issueTurnAuthority ? await issueTurnAuthority(request) : undefined;
|
|
78
|
+
if (authority) {
|
|
79
|
+
state = saveState(input.store, state, { active_turn_public_key_digest: authority.publicKeyDigest }, now);
|
|
80
|
+
}
|
|
81
|
+
result = validateTurnResult(await input.runtime.execute(request, authority ? {
|
|
82
|
+
continuationTurnSecret: authority.turnSecret,
|
|
83
|
+
continuationRunId: authority.runId,
|
|
84
|
+
} : undefined));
|
|
61
85
|
}
|
|
62
86
|
catch (error) {
|
|
63
|
-
|
|
87
|
+
const summary = boundedErrorMessage(error);
|
|
88
|
+
appendEvent(input.store, state, snapshot, "turn_failed", now, { summary, failure_kind: error instanceof ContinuationAdapterTimeoutError ? "timeout" : "adapter_error" });
|
|
64
89
|
snapshot = validateSnapshot(await input.runtime.synchronize());
|
|
65
90
|
assertMissionIdentity(state, snapshot);
|
|
66
91
|
const outcome = canonicalOutcome(snapshot);
|
|
67
|
-
if (outcome === "done")
|
|
92
|
+
if (outcome === "done") {
|
|
93
|
+
terminalized = true;
|
|
68
94
|
return finishDone(input.store, state, snapshot, now);
|
|
69
|
-
|
|
95
|
+
}
|
|
96
|
+
if (outcome === "failed") {
|
|
97
|
+
terminalized = true;
|
|
70
98
|
return finishFailed(input.store, state, snapshot, now);
|
|
99
|
+
}
|
|
71
100
|
if (outcome === "waiting") {
|
|
72
101
|
state = saveState(input.store, state, { status: "waiting" }, now);
|
|
73
102
|
return { outcome: "waiting", turns_started: state.turns_started, snapshot };
|
|
74
103
|
}
|
|
75
104
|
continue;
|
|
76
105
|
}
|
|
106
|
+
finally {
|
|
107
|
+
let cleanupFailure;
|
|
108
|
+
try {
|
|
109
|
+
if (authority && !authority.cleanup())
|
|
110
|
+
cleanupFailure = "continuation turn authority cleanup returned false";
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
cleanupFailure = boundedErrorMessage(error);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
if (!terminalized)
|
|
117
|
+
state = saveState(input.store, state, {
|
|
118
|
+
active_turn_step: null,
|
|
119
|
+
active_turn_public_key_digest: null,
|
|
120
|
+
}, now);
|
|
121
|
+
if (cleanupFailure) {
|
|
122
|
+
try {
|
|
123
|
+
appendEvent(input.store, state, snapshot, "authority_cleanup_failed", now, { summary: cleanupFailure });
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Audit is best effort. A cleanup extension must not replace the adapter outcome.
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
77
131
|
appendEvent(input.store, state, snapshot, "turn_completed", now, { summary: result.summary });
|
|
78
132
|
if (result.status === "wait") {
|
|
79
133
|
state = saveState(input.store, state, { status: "waiting", pending_barrier: result.barrier }, now);
|
|
@@ -87,6 +141,9 @@ export async function runContinuationDriver(input) {
|
|
|
87
141
|
}
|
|
88
142
|
snapshot = validateSnapshot(await input.runtime.synchronize());
|
|
89
143
|
assertMissionIdentity(state, snapshot);
|
|
144
|
+
if (snapshot.status === "active" && snapshot.current_step === request.current_step) {
|
|
145
|
+
appendEvent(input.store, state, snapshot, "gate_not_advanced", now, { summary: "adapter completed without canonical gate advancement" });
|
|
146
|
+
}
|
|
90
147
|
const outcome = canonicalOutcome(snapshot);
|
|
91
148
|
if (outcome === "done")
|
|
92
149
|
return finishDone(input.store, state, snapshot, now);
|
|
@@ -97,7 +154,11 @@ export async function runContinuationDriver(input) {
|
|
|
97
154
|
return { outcome: "waiting", turns_started: state.turns_started, snapshot };
|
|
98
155
|
}
|
|
99
156
|
}
|
|
100
|
-
state = saveState(input.store, state, {
|
|
157
|
+
state = saveState(input.store, state, {
|
|
158
|
+
status: "budget_exhausted",
|
|
159
|
+
active_turn_step: null,
|
|
160
|
+
active_turn_public_key_digest: null,
|
|
161
|
+
}, now);
|
|
101
162
|
appendEvent(input.store, state, snapshot, "budget_exhausted", now);
|
|
102
163
|
return { outcome: "budget_exhausted", turns_started: state.turns_started, snapshot };
|
|
103
164
|
}
|
|
@@ -115,6 +176,7 @@ export async function driveBuilderFlowSession(input) {
|
|
|
115
176
|
store: createFileContinuationStore(sessionDir),
|
|
116
177
|
...(input.waitForBarrier ? { waitForBarrier: input.waitForBarrier } : {}),
|
|
117
178
|
...(input.authorizeTurn ? { authorizeTurn: input.authorizeTurn } : {}),
|
|
179
|
+
...(input.issueTurnAuthority ? { issueTurnAuthority: input.issueTurnAuthority } : {}),
|
|
118
180
|
...(input.now ? { now: input.now } : {}),
|
|
119
181
|
});
|
|
120
182
|
}
|
|
@@ -125,10 +187,11 @@ export async function withContinuationDriverLock(sessionDirInput, body) {
|
|
|
125
187
|
ensureSafeDirectory(sessionDir, locksDir);
|
|
126
188
|
const token = randomUUID();
|
|
127
189
|
const lockFile = path.join(locksDir, `${process.pid}-${token}.lock`);
|
|
128
|
-
const
|
|
190
|
+
const lease = { pid: process.pid, token, created_at: new Date().toISOString() };
|
|
191
|
+
const owner = { schema_version: "1.0", ...lease };
|
|
129
192
|
acquireDriverLock(locksDir, lockFile, owner);
|
|
130
193
|
try {
|
|
131
|
-
return await body();
|
|
194
|
+
return await body(lease);
|
|
132
195
|
}
|
|
133
196
|
finally {
|
|
134
197
|
releaseDriverLock(lockFile, token);
|
|
@@ -274,6 +337,8 @@ function loadOrCreateState(store, snapshot, maxTurns, adapterCommandIdentity, no
|
|
|
274
337
|
adapter_command_identity: adapterCommandIdentity,
|
|
275
338
|
status: "active",
|
|
276
339
|
turns_started: 0,
|
|
340
|
+
active_turn_step: null,
|
|
341
|
+
active_turn_public_key_digest: null,
|
|
277
342
|
pending_barrier: null,
|
|
278
343
|
updated_at: now().toISOString(),
|
|
279
344
|
};
|
|
@@ -285,12 +350,22 @@ function canonicalOutcome(snapshot) {
|
|
|
285
350
|
return snapshot.disposition;
|
|
286
351
|
}
|
|
287
352
|
function finishDone(store, state, snapshot, now) {
|
|
288
|
-
const done = saveState(store, state, {
|
|
353
|
+
const done = saveState(store, state, {
|
|
354
|
+
status: "done",
|
|
355
|
+
active_turn_step: null,
|
|
356
|
+
active_turn_public_key_digest: null,
|
|
357
|
+
pending_barrier: null,
|
|
358
|
+
}, now);
|
|
289
359
|
appendEvent(store, done, snapshot, "done", now);
|
|
290
360
|
return { outcome: "done", turns_started: done.turns_started, snapshot };
|
|
291
361
|
}
|
|
292
362
|
function finishFailed(store, state, snapshot, now) {
|
|
293
|
-
const failed = saveState(store, state, {
|
|
363
|
+
const failed = saveState(store, state, {
|
|
364
|
+
status: "failed",
|
|
365
|
+
active_turn_step: null,
|
|
366
|
+
active_turn_public_key_digest: null,
|
|
367
|
+
pending_barrier: null,
|
|
368
|
+
}, now);
|
|
294
369
|
return { outcome: "failed", turns_started: failed.turns_started, snapshot };
|
|
295
370
|
}
|
|
296
371
|
function saveState(store, current, patch, now) {
|
|
@@ -309,6 +384,7 @@ function appendEvent(store, state, snapshot, type, now, extra = {}) {
|
|
|
309
384
|
at: now().toISOString(),
|
|
310
385
|
...(extra.barrier ? { barrier: extra.barrier } : {}),
|
|
311
386
|
...(extra.summary ? { summary: extra.summary } : {}),
|
|
387
|
+
...(extra.failure_kind ? { failure_kind: extra.failure_kind } : {}),
|
|
312
388
|
});
|
|
313
389
|
}
|
|
314
390
|
function validateSnapshot(value) {
|
|
@@ -364,6 +440,13 @@ function validateState(state) {
|
|
|
364
440
|
throw new Error("continuation driver turns_started must be a non-negative integer");
|
|
365
441
|
if (state.turns_started > state.max_turns)
|
|
366
442
|
throw new Error("continuation driver turns_started cannot exceed max_turns");
|
|
443
|
+
if (state.active_turn_step !== undefined && state.active_turn_step !== null && (typeof state.active_turn_step !== "string" || state.active_turn_step.length === 0)) {
|
|
444
|
+
throw new Error("continuation driver active_turn_step must be a non-empty string or null");
|
|
445
|
+
}
|
|
446
|
+
if (state.active_turn_public_key_digest !== undefined && state.active_turn_public_key_digest !== null
|
|
447
|
+
&& (typeof state.active_turn_public_key_digest !== "string" || !/^[a-f0-9]{64}$/.test(state.active_turn_public_key_digest))) {
|
|
448
|
+
throw new Error("continuation driver active_turn_public_key_digest must be a SHA-256 hex digest or null");
|
|
449
|
+
}
|
|
367
450
|
if (!new Set(["active", "waiting", "done", "failed", "budget_exhausted"]).has(state.status))
|
|
368
451
|
throw new Error("continuation driver state status is invalid");
|
|
369
452
|
if (state.status === "budget_exhausted" && state.turns_started !== state.max_turns) {
|
package/build/src/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export { BUILDER_BUILD_FLOW_ID, BUILDER_BUILD_FLOW_RELATIVE_PATH, BuilderBuildRu
|
|
|
2
2
|
export type { BuilderBuildRunResult, BuilderBuildRunIdentityMismatch, BuilderBuildTrustBundleEvidenceInput, EvaluateBuilderBuildRunInput, LoadBuilderBuildRunInput, StartBuilderBuildRunInput, } from "./builder-flow-run-adapter.js";
|
|
3
3
|
export { archiveBuilderFlowSession, cancelBuilderFlowSession, pauseBuilderFlowSession, recoverBuilderFlowSession, releaseBuilderFlowAssignment, resumeBuilderFlowSession, startBuilderFlowSession, syncBuilderFlowSession, } from "./builder-flow-runtime.js";
|
|
4
4
|
export type { BuilderFlowAgentLifecycleInput, BuilderFlowAuthorizedLifecycleInput, BuilderFlowSessionInput, BuilderFlowSessionResult } from "./builder-flow-runtime.js";
|
|
5
|
-
export { createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
|
|
6
|
-
export type { ContinuationBarrier, ContinuationDriverEvent, ContinuationDriverOutcome, ContinuationDriverState, ContinuationRuntimePort, ContinuationSnapshot, ContinuationStateStore, ContinuationTurnRequest, ContinuationTurnResult, DriveBuilderFlowSessionInput, RunContinuationDriverInput, } from "./continuation-driver.js";
|
|
5
|
+
export { ContinuationAdapterTimeoutError, createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
|
|
6
|
+
export type { ContinuationBarrier, ContinuationDriverEvent, ContinuationDriverLockLease, ContinuationDriverOutcome, ContinuationDriverState, ContinuationRuntimePort, ContinuationSnapshot, ContinuationStateStore, ContinuationTurnAuthority, ContinuationTurnContext, ContinuationTurnRequest, ContinuationTurnResult, DriveBuilderFlowSessionInput, RunContinuationDriverInput, } from "./continuation-driver.js";
|
|
7
7
|
export { builderLifecycleAuthorizationPayload, loadBuilderLifecycleAuthorization } from "./builder-lifecycle-authority.js";
|
|
8
8
|
export type { BuilderLifecycleAuthorization } from "./builder-lifecycle-authority.js";
|
|
9
9
|
export { defaultArtifactRootForRead, defaultCodexHome, defaultTelemetryDirForRead, defaultTelemetryDirsForRead, durableFlowAgentsRoot, durableInstallRecordPath, DURABLE_FLOW_AGENTS_DIR, FLOW_AGENTS_RUNTIME_DIR, FLOW_AGENTS_RUNTIME_SUBDIR, firstExistingPath, flowAgentsArtifactRoot, KONTOURAI_DIR, legacyTelemetryDataDir, LEGACY_TELEMETRY_DIR, telemetryDataDir, } from "./lib/local-artifact-root.js";
|
package/build/src/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import * as path from "node:path";
|
|
|
15
15
|
import { loadJson as _loadJson, writeJson as _writeJson } from "./cli/workflow-sidecar.js";
|
|
16
16
|
export { BUILDER_BUILD_FLOW_ID, BUILDER_BUILD_FLOW_RELATIVE_PATH, BuilderBuildRunInputError, BuilderBuildRunIdentityError, evaluateBuilderBuildRun, loadBuilderBuildRun, resolveBuilderBuildFlowDefinitionPath, startBuilderBuildRun, } from "./builder-flow-run-adapter.js";
|
|
17
17
|
export { archiveBuilderFlowSession, cancelBuilderFlowSession, pauseBuilderFlowSession, recoverBuilderFlowSession, releaseBuilderFlowAssignment, resumeBuilderFlowSession, startBuilderFlowSession, syncBuilderFlowSession, } from "./builder-flow-runtime.js";
|
|
18
|
-
export { createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
|
|
18
|
+
export { ContinuationAdapterTimeoutError, createFileContinuationStore, driveBuilderFlowSession, runContinuationDriver, withContinuationDriverLock, } from "./continuation-driver.js";
|
|
19
19
|
// Pure serialization contract used by external lifecycle authorities when
|
|
20
20
|
// signing requests. This does not load, create, or mutate a Flow run.
|
|
21
21
|
export { builderLifecycleAuthorizationPayload, loadBuilderLifecycleAuthorization } from "./builder-lifecycle-authority.js";
|
|
@@ -293,13 +293,30 @@ function appendExportNote(body, note) {
|
|
|
293
293
|
function generatedAgentsSummary(agents) {
|
|
294
294
|
return agents.slice().sort((a, b) => a.name.localeCompare(b.name)).map((spec) => `- \`${spec.name}\` — ${String(spec.description ?? "").trim()}`).join("\n");
|
|
295
295
|
}
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
const BUNDLE_CAPABILITIES = {
|
|
297
|
+
"base": { label: "Base", installHint: "bash install.sh /path/to/workspace", instructionPath: "AGENTS.md", taskDir: runtimeTaskDir },
|
|
298
|
+
"kiro": { label: "Kiro", installHint: "bash install.sh $HOME/.flow-agents", instructionPath: "AGENTS.md", taskDir: runtimeTaskDir },
|
|
299
|
+
"claude-code": { label: "Claude Code", installHint: "bash install.sh /path/to/workspace", instructionPath: "CLAUDE.md", taskDir: manifest.claude_code.task_dir },
|
|
300
|
+
"codex": { label: "Codex", installHint: "bash install.sh /path/to/workspace", taskDir: manifest.codex.task_dir },
|
|
301
|
+
"opencode": { label: "opencode", installHint: "bash install.sh /path/to/workspace", instructionPath: "AGENTS.md", taskDir: manifest.opencode.task_dir },
|
|
302
|
+
"pi": { label: "pi", installHint: "bash install.sh /path/to/workspace", instructionPath: "AGENTS.md", taskDir: manifest.pi.task_dir },
|
|
303
|
+
};
|
|
304
|
+
function renderOperationalInstructions(capability) {
|
|
305
|
+
return `# Flow Agents\n\nUse the installed Flow Agents skills and runtime integrations for delivery work. Keep cross-session task artifacts under \`${capability.taskDir}\`.\n`;
|
|
298
306
|
}
|
|
299
307
|
const CODEX_LIVE_HOOKS_README = `\n## Running with hooks active (live)\n\n\`install.sh\` lays the bundle into a workspace, but a live Codex session needs a \`CODEX_HOME\` that has both the bundle's hooks/scripts AND your real credentials. Use the dedicated installer, which defaults to \`CODEX_HOME\` when set and otherwise \`~/.codex\`, flattens the config to the home root, and copies your auth from \`~/.codex\` when installing elsewhere:\n\n\`\`\`bash\nbash scripts/install-codex-home.sh\ncodex exec --dangerously-bypass-hook-trust -C /path/to/project \"<prompt>\"\n\`\`\`\n\nPass a positional destination to install into an explicit alternate Codex home.\n\nThe goal-fit Stop hook then enforces by default (\`FLOW_AGENTS_GOAL_FIT_MODE=block\`); set it to \`warn\` or \`off\` to override.\n`;
|
|
300
308
|
function exportTargetReadme(label, installHint, extra = "") {
|
|
301
309
|
return `# ${label} Bundle\n\nGenerated from the canonical source in this repository.\n\n## Install\n\n\`\`\`bash\n${installHint}\n\`\`\`\n\nThe install ships the full standalone base (skills, agents, powers) plus the\nFlow Kits. Kit depth is activated through the Kit Catalog, not at install time.\n\n## Contents\n\n- Harness-specific agents\n- Shared skills\n- Shared context, powers, prompts, scripts, and evals\n${extra}`;
|
|
302
310
|
}
|
|
311
|
+
function renderBundleReadme(capability, agents, extra = "") {
|
|
312
|
+
const inventory = `\n## Exported agents\n\nThe following agent definitions were generated from the canonical agent specifications in this repository. This inventory is documentation, not agent instructions.\n\n${generatedAgentsSummary(agents)}\n`;
|
|
313
|
+
return exportTargetReadme(capability.label, capability.installHint, `${inventory}${extra}`);
|
|
314
|
+
}
|
|
315
|
+
function writeBundlePolicy(bundle, capability, agents, readmeExtra = "") {
|
|
316
|
+
writeText(path.join(bundle, "README.md"), renderBundleReadme(capability, agents, readmeExtra));
|
|
317
|
+
if (capability.instructionPath)
|
|
318
|
+
writeText(path.join(bundle, capability.instructionPath), renderOperationalInstructions(capability));
|
|
319
|
+
}
|
|
303
320
|
function mapClaudeTools(allowedTools) {
|
|
304
321
|
const ordered = [];
|
|
305
322
|
for (const tool of Array.isArray(allowedTools) ? allowedTools : []) {
|
|
@@ -451,48 +468,59 @@ function copySharedContent(targetRoot, targetName, token) {
|
|
|
451
468
|
}
|
|
452
469
|
for (const dir of manifest.optional_copy_dirs ?? [])
|
|
453
470
|
copyTree(path.join(root, dir), path.join(targetRoot, dir), targetName, token);
|
|
454
|
-
writeText(path.join(targetRoot, "build/package.json"), `${JSON.stringify({
|
|
471
|
+
writeText(path.join(targetRoot, "build/package.json"), `${JSON.stringify({
|
|
472
|
+
name: "@kontourai/flow-agents",
|
|
473
|
+
version: pkgVersion,
|
|
474
|
+
type: "module",
|
|
475
|
+
}, null, 2)}\n`);
|
|
455
476
|
const commonBuilt = path.join(root, "build/src/tools/common.js");
|
|
456
477
|
if (fs.existsSync(commonBuilt))
|
|
457
478
|
writeText(path.join(targetRoot, "scripts/common.mjs"), readText(commonBuilt));
|
|
458
479
|
copyTree(path.join(root, "build/src"), path.join(targetRoot, "build/src"), targetName, token);
|
|
459
480
|
}
|
|
460
|
-
function installScript(label, defaultDestDisplay, token, destFallbackShell, mergeConfig, stampConfig) {
|
|
461
|
-
const replaceBlock = token ? `\nexport DEST\nfind "$DEST" -type f \\( -name '*.json' -o -name '*.md' -o -name '*.sh' -o -name '*.js' -o -name '*.ts' -o -name '*.yaml' -o -name '*.yml' \\) -print0 | xargs -0 perl -0pi -e 's#${token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}#$ENV{DEST}#g'` : "";
|
|
481
|
+
function installScript(label, capability, defaultDestDisplay, token, destFallbackShell, mergeConfig, stampConfig) {
|
|
482
|
+
const replaceBlock = token ? `\nexport DEST\nfind "$DEST" \\( -path "$DEST/AGENTS.md" -o -path "$DEST/CLAUDE.md" \\) -prune -o -type f \\( -name '*.json' -o -name '*.md' -o -name '*.sh' -o -name '*.js' -o -name '*.ts' -o -name '*.yaml' -o -name '*.yml' \\) -print0 | xargs -0 perl -0pi -e 's#${token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}#$ENV{DEST}#g'` : "";
|
|
462
483
|
const destFallback = destFallbackShell ? `\nif [[ -z "$DEST" ]]; then\n DEST="${destFallbackShell}"\nfi` : "";
|
|
463
484
|
const destRequired = !destFallbackShell;
|
|
464
|
-
const requiredCheck = destRequired ? `if [[ -z "$DEST" ]]; then\n usage\n exit 2\nfi\n` : "";
|
|
485
|
+
const requiredCheck = `${destRequired ? `if [[ -z "$DEST" ]]; then\n usage\n exit 2\nfi\n` : ""}while [[ "$DEST" != "/" && "$DEST" == */ ]]; do\n DEST="\${DEST%/}"\ndone\n`;
|
|
465
486
|
const usageDest = destRequired ? "/path/to/workspace" : defaultDestDisplay;
|
|
466
487
|
const mergeBlock = mergeConfig
|
|
467
488
|
? `\nif command -v node >/dev/null 2>&1; then\n node "$DEST/scripts/install-merge.js" --config "$DEST/${mergeConfig.configRelPath}" --managed-hooks "$SRC/${mergeConfig.managedConfigRelPath}" --version "${mergeConfig.version}" --install-record "$DEST/${durableInstallRecordRel}" --runtime "${mergeConfig.runtime}" || true\nfi`
|
|
468
489
|
: stampConfig
|
|
469
490
|
? `\nif command -v node >/dev/null 2>&1; then\n node "$DEST/scripts/install-merge.js" --stamp-only --version "${stampConfig.version}" --install-record "$DEST/${durableInstallRecordRel}" --runtime "${stampConfig.runtime}" || true\nfi`
|
|
470
491
|
: "";
|
|
471
|
-
|
|
492
|
+
// Excluding both discovery filenames protects any existing filesystem
|
|
493
|
+
// object, including during Kiro's --delete sync. Required guidance is then
|
|
494
|
+
// published with a no-overwrite hard link from a destination-local temp file.
|
|
495
|
+
const instructionBlock = capability.instructionPath
|
|
496
|
+
? `\nif [[ ! -e "$DEST/${capability.instructionPath}" && ! -L "$DEST/${capability.instructionPath}" ]]; then\n instruction_tmp="$(mktemp "$DEST/.flow-agents-instructions.XXXXXX")"\n cp "$SRC/${capability.instructionPath}" "$instruction_tmp"\n if ! ln "$instruction_tmp" "$DEST/${capability.instructionPath}" 2>/dev/null; then\n if [[ ! -e "$DEST/${capability.instructionPath}" && ! -L "$DEST/${capability.instructionPath}" ]]; then\n rm -f "$instruction_tmp"\n echo "install.sh: could not safely install ${capability.instructionPath}" >&2\n exit 1\n fi\n fi\n rm -f "$instruction_tmp"\nfi`
|
|
497
|
+
: "";
|
|
498
|
+
return `#!/usr/bin/env bash\nset -euo pipefail\n\nusage() {\n cat >&2 <<'EOF'\nusage: bash install.sh ${usageDest} [options]\n\nOptions:\n --telemetry-sink NAME local-files, local-kontour-console,\n kontour-hosted-console, user-hosted-console,\n or legacy aliases. May be repeated.\n --console-url URL Persist Console telemetry base URL.\n --console-endpoint URL Persist full Console telemetry records endpoint URL.\n --console-token-file PATH\n Read Console telemetry bearer token from a file.\n --console-tenant ID Persist Console tenant identifier.\nEOF\n}\n\nDEST=""\nDEST_SET=0\nCONSOLE_CONFIG_ARGS=()\nwhile [[ $# -gt 0 ]]; do\n case "$1" in\n --telemetry-sink|--telemetry-sinks|--console-url|--console-endpoint|--console-endpoint-url|--console-token-file|--console-tenant|--console-tenant-id)\n [[ $# -ge 2 ]] || { echo "install.sh: $1 requires a value" >&2; exit 2; }\n CONSOLE_CONFIG_ARGS+=("$1" "$2")\n shift 2\n ;;\n --help|-h)\n usage\n exit 0\n ;;\n -*)\n echo "install.sh: unknown option: $1" >&2\n usage\n exit 2\n ;;\n *)\n if [[ "$DEST_SET" -eq 1 ]]; then\n echo "install.sh: unexpected argument: $1" >&2\n usage\n exit 2\n fi\n DEST="$1"\n DEST_SET=1\n shift\n ;;\n esac\ndone${destFallback}\n${requiredCheck}SRC="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"\n\nmkdir -p "$DEST"\nrsync -a ${token ? "--delete " : ""}--exclude='/AGENTS.md' --exclude='/CLAUDE.md' ${mergeConfig ? `--exclude="${mergeConfig.configRelPath}" ` : ""}"$SRC"/ "$DEST"/${instructionBlock}${replaceBlock}${mergeBlock}\nif [[ \${#CONSOLE_CONFIG_ARGS[@]} -gt 0 || -n "\${FLOW_AGENTS_TELEMETRY_SINK:-}" || -n "\${FLOW_AGENTS_TELEMETRY_SINKS:-}" || -n "\${FLOW_AGENTS_CONSOLE_URL:-}" || -n "\${CONSOLE_TELEMETRY_URL:-}" || -n "\${CONSOLE_URL:-}" || -n "\${FLOW_AGENTS_CONSOLE_TOKEN_FILE:-}" || -n "\${CONSOLE_TELEMETRY_TOKEN_FILE:-}" ]]; then\n bash "$DEST/scripts/telemetry/install-console-config.sh" "$DEST/scripts/telemetry/telemetry.conf" "\${CONSOLE_CONFIG_ARGS[@]}"\nfi\necho "Installed ${label} bundle ${token ? "to" : "into"} $DEST"\n`;
|
|
472
499
|
}
|
|
473
500
|
function buildBase(agents) {
|
|
501
|
+
const capability = BUNDLE_CAPABILITIES["base"];
|
|
474
502
|
const bundle = path.join(dist, "base");
|
|
475
503
|
resetDir(bundle);
|
|
476
504
|
copySharedContent(bundle, "base", "<bundle-root>");
|
|
477
505
|
writeText(path.join(bundle, runtimeTaskDir, ".gitkeep"), "");
|
|
478
|
-
|
|
479
|
-
writeText(path.join(bundle, "
|
|
480
|
-
writeText(path.join(bundle, "install.sh"), installScript("Base", "/path/to/workspace", undefined, undefined, undefined, { runtime: "base", version: pkgVersion }));
|
|
506
|
+
writeBundlePolicy(bundle, capability, agents);
|
|
507
|
+
writeText(path.join(bundle, "install.sh"), installScript("Base", capability, "/path/to/workspace", undefined, undefined, undefined, { runtime: "base", version: pkgVersion }));
|
|
481
508
|
fs.chmodSync(path.join(bundle, "install.sh"), 0o755);
|
|
482
509
|
}
|
|
483
510
|
function buildKiro(agents) {
|
|
511
|
+
const capability = BUNDLE_CAPABILITIES["kiro"];
|
|
484
512
|
const bundle = path.join(dist, "kiro");
|
|
485
513
|
const token = manifest.kiro.path_token;
|
|
486
514
|
resetDir(bundle);
|
|
487
515
|
copySharedContent(bundle, "kiro", token);
|
|
488
516
|
for (const spec of agents)
|
|
489
517
|
writeText(path.join(bundle, "agents", `${spec.name}.json`), sanitizeText(`${JSON.stringify(sanitizeAgentJson(spec), null, 2)}\n`, "kiro", token));
|
|
490
|
-
|
|
491
|
-
writeText(path.join(bundle, "
|
|
492
|
-
writeText(path.join(bundle, "install.sh"), installScript("Kiro", "$HOME/.flow-agents", token, '${FLOW_AGENTS_DEST:-$HOME/.flow-agents}', undefined, { runtime: "kiro", version: pkgVersion }));
|
|
518
|
+
writeBundlePolicy(bundle, capability, agents);
|
|
519
|
+
writeText(path.join(bundle, "install.sh"), installScript("Kiro", capability, "$HOME/.flow-agents", token, '${FLOW_AGENTS_DEST:-$HOME/.flow-agents}', undefined, { runtime: "kiro", version: pkgVersion }));
|
|
493
520
|
fs.chmodSync(path.join(bundle, "install.sh"), 0o755);
|
|
494
521
|
}
|
|
495
522
|
function buildClaudeCode(agents) {
|
|
523
|
+
const capability = BUNDLE_CAPABILITIES["claude-code"];
|
|
496
524
|
const bundle = path.join(dist, "claude-code");
|
|
497
525
|
resetDir(bundle);
|
|
498
526
|
copySharedContent(bundle, "claude-code", "<bundle-root>");
|
|
@@ -503,12 +531,12 @@ function buildClaudeCode(agents) {
|
|
|
503
531
|
writeText(path.join(bundle, ".claude/skills", name, "SKILL.md"), sanitizeText(readText(src), "claude-code", "<bundle-root>"));
|
|
504
532
|
}
|
|
505
533
|
writeText(path.join(bundle, ".claude/settings.json"), exportClaudeSettings());
|
|
506
|
-
|
|
507
|
-
writeText(path.join(bundle, "
|
|
508
|
-
writeText(path.join(bundle, "install.sh"), installScript("Claude Code", "/path/to/workspace", undefined, undefined, { configRelPath: ".claude/settings.json", managedConfigRelPath: ".claude/settings.json", runtime: "claude-code", version: pkgVersion }));
|
|
534
|
+
writeBundlePolicy(bundle, capability, agents);
|
|
535
|
+
writeText(path.join(bundle, "install.sh"), installScript("Claude Code", capability, "/path/to/workspace", undefined, undefined, { configRelPath: ".claude/settings.json", managedConfigRelPath: ".claude/settings.json", runtime: "claude-code", version: pkgVersion }));
|
|
509
536
|
fs.chmodSync(path.join(bundle, "install.sh"), 0o755);
|
|
510
537
|
}
|
|
511
538
|
function buildCodex(agents) {
|
|
539
|
+
const capability = BUNDLE_CAPABILITIES["codex"];
|
|
512
540
|
const bundle = path.join(dist, "codex");
|
|
513
541
|
const excluded = new Set(manifest.codex.excluded_agents ?? []);
|
|
514
542
|
const targetAgents = agents.filter((spec) => !excluded.has(spec.name));
|
|
@@ -526,9 +554,8 @@ function buildCodex(agents) {
|
|
|
526
554
|
for (const { name, src } of collectAllSkills())
|
|
527
555
|
exportSkillPackage(src, path.join(skillsRoot, name), "codex");
|
|
528
556
|
validateExportedSkillPackages(skillsRoot);
|
|
529
|
-
|
|
530
|
-
writeText(path.join(bundle, "
|
|
531
|
-
writeText(path.join(bundle, "install.sh"), installScript("Codex", "/path/to/workspace", undefined, undefined, { configRelPath: ".codex/hooks.json", managedConfigRelPath: ".codex/hooks.json", runtime: "codex", version: pkgVersion }));
|
|
557
|
+
writeBundlePolicy(bundle, capability, targetAgents, CODEX_LIVE_HOOKS_README);
|
|
558
|
+
writeText(path.join(bundle, "install.sh"), installScript("Codex", capability, "/path/to/workspace", undefined, undefined, { configRelPath: ".codex/hooks.json", managedConfigRelPath: ".codex/hooks.json", runtime: "codex", version: pkgVersion }));
|
|
532
559
|
fs.chmodSync(path.join(bundle, "install.sh"), 0o755);
|
|
533
560
|
}
|
|
534
561
|
function exportOpencodeAgent(spec) {
|
|
@@ -696,6 +723,7 @@ function exportOpencodeConfig() {
|
|
|
696
723
|
}, null, 2)}\n`;
|
|
697
724
|
}
|
|
698
725
|
function buildOpencode(agents) {
|
|
726
|
+
const capability = BUNDLE_CAPABILITIES["opencode"];
|
|
699
727
|
const bundle = path.join(dist, "opencode");
|
|
700
728
|
resetDir(bundle);
|
|
701
729
|
copySharedContent(bundle, "opencode", "<bundle-root>");
|
|
@@ -708,9 +736,8 @@ function buildOpencode(agents) {
|
|
|
708
736
|
}
|
|
709
737
|
writeText(path.join(bundle, ".opencode/plugins/flow-agents.js"), exportOpencodePlugin());
|
|
710
738
|
writeText(path.join(bundle, "opencode.json"), exportOpencodeConfig());
|
|
711
|
-
|
|
712
|
-
writeText(path.join(bundle, "
|
|
713
|
-
writeText(path.join(bundle, "install.sh"), installScript("opencode", "/path/to/workspace", undefined, undefined, { configRelPath: "opencode.json", managedConfigRelPath: "opencode.json", runtime: "opencode", version: pkgVersion }));
|
|
739
|
+
writeBundlePolicy(bundle, capability, agents);
|
|
740
|
+
writeText(path.join(bundle, "install.sh"), installScript("opencode", capability, "/path/to/workspace", undefined, undefined, { configRelPath: "opencode.json", managedConfigRelPath: "opencode.json", runtime: "opencode", version: pkgVersion }));
|
|
714
741
|
fs.chmodSync(path.join(bundle, "install.sh"), 0o755);
|
|
715
742
|
}
|
|
716
743
|
function exportPiExtension() {
|
|
@@ -809,6 +836,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
809
836
|
`;
|
|
810
837
|
}
|
|
811
838
|
function buildPi(agents) {
|
|
839
|
+
const capability = BUNDLE_CAPABILITIES["pi"];
|
|
812
840
|
const bundle = path.join(dist, "pi");
|
|
813
841
|
resetDir(bundle);
|
|
814
842
|
copySharedContent(bundle, "pi", "<bundle-root>");
|
|
@@ -819,9 +847,8 @@ function buildPi(agents) {
|
|
|
819
847
|
writeText(path.join(bundle, ".pi/skills", name, "SKILL.md"), sanitizeText(readText(src), "pi", "<bundle-root>"));
|
|
820
848
|
}
|
|
821
849
|
writeText(path.join(bundle, ".pi/extensions/flow-agents.ts"), exportPiExtension());
|
|
822
|
-
|
|
823
|
-
writeText(path.join(bundle, "
|
|
824
|
-
writeText(path.join(bundle, "install.sh"), installScript("pi", "/path/to/workspace", undefined, undefined, undefined, { runtime: "pi", version: pkgVersion }));
|
|
850
|
+
writeBundlePolicy(bundle, capability, agents);
|
|
851
|
+
writeText(path.join(bundle, "install.sh"), installScript("pi", capability, "/path/to/workspace", undefined, undefined, undefined, { runtime: "pi", version: pkgVersion }));
|
|
825
852
|
fs.chmodSync(path.join(bundle, "install.sh"), 0o755);
|
|
826
853
|
}
|
|
827
854
|
function buildCatalog(agents) {
|
|
@@ -32,6 +32,7 @@ const mirroredFiles = new Map([
|
|
|
32
32
|
// fails `npm run validate:source` instead of silently accumulating.
|
|
33
33
|
["scripts/hooks/config-protection.js", { mirror: "context/scripts/hooks/config-protection.js", allowedDifferences: [] }],
|
|
34
34
|
["scripts/hooks/lib/config-protection-remedies.js", { mirror: "context/scripts/hooks/lib/config-protection-remedies.js", allowedDifferences: [] }],
|
|
35
|
+
["scripts/hooks/lib/continuation-turn-authority.js", { mirror: "context/scripts/hooks/lib/continuation-turn-authority.js", allowedDifferences: [] }],
|
|
35
36
|
["scripts/hooks/lib/kit-catalog.js", { mirror: "context/scripts/hooks/lib/kit-catalog.js", allowedDifferences: [] }],
|
|
36
37
|
["scripts/hooks/lib/runnable-command.js", { mirror: "context/scripts/hooks/lib/runnable-command.js", allowedDifferences: [] }],
|
|
37
38
|
["scripts/hooks/stop-goal-fit.js", { mirror: "context/scripts/hooks/stop-goal-fit.js", allowedDifferences: [] }],
|
|
@@ -83,10 +84,11 @@ const hookFilePolicies = new Map([
|
|
|
83
84
|
["scripts/hooks/utterance-check.js", { category: "policy hook", requiredNeedles: ["Utterance Check Hook", "FLOW_AGENTS_UTTERANCE_CHECK_ENABLED"] }],
|
|
84
85
|
["scripts/hooks/workflow-steering.js", { category: "policy hook", requiredNeedles: ["Workflow Steering Hook"] }],
|
|
85
86
|
["scripts/hooks/desktop-notify.sh", { category: "local notification helper", requiredNeedles: ["desktop-notify.sh", "osascript"] }],
|
|
86
|
-
["scripts/hooks/lib/actor-identity.js", { category: "shared hook library", requiredNeedles: ["resolveActor", "FLOW_AGENTS_ACTOR"] }],
|
|
87
|
+
["scripts/hooks/lib/actor-identity.js", { category: "shared hook library", requiredNeedles: ["resolveActor", "FLOW_AGENTS_ACTOR", "CODEX_THREAD_ID", "flow-agents:codex-thread:v1:"] }],
|
|
87
88
|
["scripts/hooks/lib/audit-transport.sh", { category: "shared hook library", requiredNeedles: ["audit_emit"] }],
|
|
88
89
|
["scripts/hooks/lib/codex-exit-code.js", { category: "shared hook library", requiredNeedles: ["extractExitCodeFromBanner", "readExitCodeFromRollout"] }],
|
|
89
90
|
["scripts/hooks/lib/config-protection-remedies.js", { category: "shared hook library", requiredNeedles: ["SANCTIONED_REMEDIES", "REMEDY_COMMAND_CANDIDATES"] }],
|
|
91
|
+
["scripts/hooks/lib/continuation-turn-authority.js", { category: "shared hook library", requiredNeedles: ["issueActiveTurnAuthority", "validateActiveTurnAuthority", "validateSignedActiveTurnAssignmentAuthority"] }],
|
|
90
92
|
["scripts/hooks/lib/current-pointer.js", { category: "shared hook library", requiredNeedles: ["readCurrentPointer", "perActorCurrentFile"] }],
|
|
91
93
|
["scripts/hooks/lib/hook-flags.js", { category: "shared hook library", requiredNeedles: ["isHookEnabled"] }],
|
|
92
94
|
["scripts/hooks/lib/kit-catalog.js", { category: "shared hook library", requiredNeedles: ["readKitManifests", "workflowTriggersFor"] }],
|
|
@@ -105,6 +107,7 @@ const fixtureOwnerPolicies = new Map([
|
|
|
105
107
|
["evals/fixtures/backlog-provider-settings", { owners: ["evals/integration/test_effective_backlog_settings.sh"], classification: "settings precedence fixtures" }],
|
|
106
108
|
["evals/fixtures/builder-kit-workflow-state", { owners: ["evals/static/test_workflow_skills.sh"], classification: "Builder Kit workflow-state fixtures" }],
|
|
107
109
|
["evals/fixtures/console-learning-projection", { owners: ["evals/integration/test_console_learning_projection.sh"], classification: "console learning projection fixtures" }],
|
|
110
|
+
["evals/fixtures/codex-legacy-agents", { owners: ["evals/integration/test_install_merge.sh"], classification: "exact historical Flow Agents-generated Codex AGENTS.md migration fixtures (#563)" }],
|
|
108
111
|
["evals/fixtures/economics", { owners: ["evals/integration/test_economics_record.sh"], classification: "per-run kit-economics record fixtures (#349): a transcript with .message.usage blocks, state.json/acceptance.json/critique.json join sources, a session.usage event, and the golden expected kontour.console.economics record" }],
|
|
109
112
|
["evals/fixtures/flow-kit-repository", { owners: ["evals/integration/test_flow_kit_repository.sh", "evals/integration/test_local_flow_kit_install.sh", "evals/integration/test_runtime_adapter_activation.sh", "evals/integration/test_activate_npx_context.sh", "evals/integration/test_flow_kit_install_git.sh", "evals/static/test_workflow_skills.sh"], classification: "Flow Kit repository contract fixtures" }],
|
|
110
113
|
["evals/fixtures/kit-conformance-levels", { owners: ["evals/integration/test_kit_conformance_levels.sh"], classification: "K-level conformance and consumer-target derivation fixtures" }],
|
|
@@ -113,7 +116,7 @@ const fixtureOwnerPolicies = new Map([
|
|
|
113
116
|
["evals/fixtures/pull-work-provider", { owners: ["evals/integration/test_pull_work_provider.sh"], classification: "work item provider normalization fixtures" }],
|
|
114
117
|
["evals/fixtures/pull-work-wip-shepherding", { owners: ["evals/static/test_workflow_skills.sh"], classification: "WIP shepherding state fixtures" }],
|
|
115
118
|
["evals/fixtures/surface-trust", { owners: ["evals/integration/test_workflow_sidecar_writer.sh"], classification: "Surface trust evidence fixtures" }],
|
|
116
|
-
["evals/fixtures/telemetry", { owners: ["evals/integration/test_usage_cost.sh", "evals/integration/test_telemetry_usage_pipeline.sh"], classification: "hermetic Stop-hook usage transcript fixture (#defect-2026-07 telemetry-usage-cost-extraction): a multi-model JSONL transcript with .message.model + .message.usage token blocks proving real token/cost/model extraction end-to-end" }],
|
|
119
|
+
["evals/fixtures/telemetry", { owners: ["evals/integration/test_usage_cost.sh", "evals/integration/test_telemetry_usage_pipeline.sh", "evals/integration/test_telemetry_tool_usage.sh"], classification: "hermetic Stop-hook usage transcript fixture (#defect-2026-07 telemetry-usage-cost-extraction): a multi-model JSONL transcript with .message.model + .message.usage token blocks proving real token/cost/model extraction end-to-end; also reused by the #568 slice 1 per-tool-call usage-enrichment eval (test_telemetry_tool_usage.sh), which adds usage-transcript-oversized-prefix.jsonl to prove the bounded tail-read" }],
|
|
117
120
|
["evals/fixtures/reconcile-preflight", { owners: ["evals/integration/test_reconcile_preflight.sh"], classification: "#356 reconcile-preflight shape fixtures not already covered by trust-reconcile-exploits (un-superseded disputed critique, standalone disputed session-local claim)" }],
|
|
118
121
|
["evals/fixtures/trust-reconcile-exploits", { owners: ["evals/integration/test_trust_reconcile_negatives.sh", "evals/integration/test_reconcile_preflight.sh"], classification: "WS8 trust-reconcile anti-gaming exploit fixtures (frozen negative regressions); also reused by the #356 local reconcile-preflight eval (same shapes, no forked copies)" }],
|
|
119
122
|
["evals/fixtures/trust-reconcile-mixed-bundle", { owners: ["evals/integration/test_trust_reconcile_mixed_bundle.sh", "evals/integration/test_reconcile_preflight.sh"], classification: "WS8 trust-reconcile mixed-evidence end-to-end proof fixture; also reused by the #356 reconcile-preflight eval as its CLEAN-BUNDLE (AC4) case" }],
|