@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
|
@@ -294,6 +294,72 @@ add_tool_data_and_emit_delegation() {
|
|
|
294
294
|
echo "$event"
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
# add_tool_usage_data — populates .usage on tool.invoke/tool.result events
|
|
298
|
+
# (preToolUse/postToolUse only; see add_event_specific_data's explicit
|
|
299
|
+
# permissionRequest exclusion) with the model/token/cost usage of the turn
|
|
300
|
+
# that produced this specific tool call (#568 slice 1). Same field shape
|
|
301
|
+
# session.usage already emits (model, input_tokens, output_tokens,
|
|
302
|
+
# cache_creation_input_tokens, cache_read_input_tokens, estimated_cost_usd,
|
|
303
|
+
# pricing_version) so console consumers reuse the same parsing path.
|
|
304
|
+
#
|
|
305
|
+
# Fallback tiers (never invent a number):
|
|
306
|
+
# 1. transcript-tail join succeeds (usage_last_turn_usage) -> full usage,
|
|
307
|
+
# attributable to this exact turn (not the session aggregate).
|
|
308
|
+
# 2. transcript join fails but hook.model is present (and not "unknown")
|
|
309
|
+
# -> .usage.model only, every token/cost field explicitly null.
|
|
310
|
+
# 3. neither available -> all .usage.* fields null (today's pre-existing,
|
|
311
|
+
# unchanged no-data state).
|
|
312
|
+
add_tool_usage_data() {
|
|
313
|
+
local event="$1"
|
|
314
|
+
local transcript_path hook_model
|
|
315
|
+
transcript_path=$(echo "$event" | jq -r '.hook.transcript_path // ""')
|
|
316
|
+
hook_model=$(echo "$event" | jq -r '.hook.model // ""')
|
|
317
|
+
|
|
318
|
+
local turn_usage
|
|
319
|
+
turn_usage=""
|
|
320
|
+
if [[ -n "$transcript_path" ]]; then
|
|
321
|
+
turn_usage=$(usage_last_turn_usage "$transcript_path")
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
if [[ -n "$turn_usage" ]]; then
|
|
325
|
+
echo "$event" | jq -c --argjson tu "$turn_usage" '. + {
|
|
326
|
+
usage: {
|
|
327
|
+
model: $tu.model,
|
|
328
|
+
input_tokens: $tu.input_tokens,
|
|
329
|
+
output_tokens: $tu.output_tokens,
|
|
330
|
+
cache_creation_input_tokens: $tu.cache_creation_input_tokens,
|
|
331
|
+
cache_read_input_tokens: $tu.cache_read_input_tokens,
|
|
332
|
+
estimated_cost_usd: $tu.estimated_cost_usd,
|
|
333
|
+
pricing_version: $tu.pricing_version
|
|
334
|
+
}
|
|
335
|
+
}'
|
|
336
|
+
elif [[ -n "$hook_model" && "$hook_model" != "unknown" ]]; then
|
|
337
|
+
echo "$event" | jq -c --arg m "$hook_model" '. + {
|
|
338
|
+
usage: {
|
|
339
|
+
model: $m,
|
|
340
|
+
input_tokens: null,
|
|
341
|
+
output_tokens: null,
|
|
342
|
+
cache_creation_input_tokens: null,
|
|
343
|
+
cache_read_input_tokens: null,
|
|
344
|
+
estimated_cost_usd: null,
|
|
345
|
+
pricing_version: null
|
|
346
|
+
}
|
|
347
|
+
}'
|
|
348
|
+
else
|
|
349
|
+
echo "$event" | jq -c '. + {
|
|
350
|
+
usage: {
|
|
351
|
+
model: null,
|
|
352
|
+
input_tokens: null,
|
|
353
|
+
output_tokens: null,
|
|
354
|
+
cache_creation_input_tokens: null,
|
|
355
|
+
cache_read_input_tokens: null,
|
|
356
|
+
estimated_cost_usd: null,
|
|
357
|
+
pricing_version: null
|
|
358
|
+
}
|
|
359
|
+
}'
|
|
360
|
+
fi
|
|
361
|
+
}
|
|
362
|
+
|
|
297
363
|
add_stop_data_and_emit_usage() {
|
|
298
364
|
local event="$1" agent_name="$2"
|
|
299
365
|
local duration_s
|
|
@@ -399,7 +465,16 @@ add_event_specific_data() {
|
|
|
399
465
|
userPromptSubmit|UserPromptSubmit)
|
|
400
466
|
add_user_prompt_data "$event" "$stdin_json"
|
|
401
467
|
;;
|
|
402
|
-
preToolUse|PreToolUse|
|
|
468
|
+
preToolUse|PreToolUse|postToolUse|PostToolUse|PostToolUseFailure)
|
|
469
|
+
event=$(add_tool_data_and_emit_delegation "$event" "$event_type" "$stdin_json")
|
|
470
|
+
if [[ "$TELEMETRY_USAGE_TRACKING" == "true" ]]; then
|
|
471
|
+
event=$(add_tool_usage_data "$event")
|
|
472
|
+
fi
|
|
473
|
+
echo "$event"
|
|
474
|
+
;;
|
|
475
|
+
permissionRequest|PermissionRequest)
|
|
476
|
+
# Explicit scope boundary (#568 slice 1): tool.permission_request does
|
|
477
|
+
# NOT receive .usage enrichment — only preToolUse/postToolUse do.
|
|
403
478
|
add_tool_data_and_emit_delegation "$event" "$event_type" "$stdin_json"
|
|
404
479
|
;;
|
|
405
480
|
stop|Stop|SessionEnd)
|
|
@@ -67,16 +67,18 @@ this section before the rest.
|
|
|
67
67
|
|
|
68
68
|
### The resolution chain
|
|
69
69
|
|
|
70
|
-
`resolveActor(env)` (in `scripts/hooks/lib/actor-identity.js`,
|
|
70
|
+
`resolveActor(env)` (in the canonical `scripts/hooks/lib/actor-identity.js`, loaded by TypeScript consumers rather than mirrored) returns
|
|
71
71
|
`{ actor, source }` by trying four sources in strict priority order:
|
|
72
72
|
|
|
73
73
|
1. **`explicit-override`** — `FLOW_AGENTS_ACTOR` is set. The actor is the **bare token** you provided,
|
|
74
74
|
verbatim. Source string: `"explicit-override"`.
|
|
75
|
-
2. **`runtime-session-id:<runtime>`** — the host runtime exposes a native session id
|
|
76
|
-
|
|
75
|
+
2. **`runtime-session-id:<runtime>`** — the host runtime exposes a native session id. For Codex,
|
|
76
|
+
`CODEX_THREAD_ID` is preferred over the legacy-compatible `CODEX_SESSION_ID`. The raw thread id
|
|
77
|
+
is never persisted: it becomes a domain-separated 96-bit `thread-<digest>` token. The actor is a **serialized triple** `runtime:session:host`. Source string:
|
|
77
78
|
`"runtime-session-id:<runtime>"`.
|
|
78
|
-
3. **`process-ancestry`** — no session id; identity is derived
|
|
79
|
-
serialized
|
|
79
|
+
3. **`process-ancestry`** — no session id; identity is derived from the parent process and start
|
|
80
|
+
time. It is serialized explicitly as `process-ancestry:anc-<digest>:<host>`, never as an
|
|
81
|
+
`unknown` runtime. Source string: `"process-ancestry"`; this remains unstable/advisory.
|
|
80
82
|
4. **`unresolved`** — nothing worked. Source string: `"unresolved"`.
|
|
81
83
|
|
|
82
84
|
The `"local"` literal default from the old design is **retired as an error, not a fallback** — a
|
|
@@ -116,6 +118,10 @@ A record written by a current session has `actor_key` and compares canonically;
|
|
|
116
118
|
it falls back to `serializeActor`, reproducing pre-#291 behavior exactly. This one field is why the
|
|
117
119
|
override/derived divergence no longer bites.
|
|
118
120
|
|
|
121
|
+
Historical `unknown:anc-*` values remain opaque, readable actor keys and are not rewritten or
|
|
122
|
+
aliased. Because ancestry is intentionally unstable, a process crossing this upgrade boundary may
|
|
123
|
+
need to release/reclaim rather than treating the old and new display forms as the same identity.
|
|
124
|
+
|
|
119
125
|
### Stable vs. unstable identity (this powers the publish gate)
|
|
120
126
|
|
|
121
127
|
The `source` matters beyond attribution. An identity is **stable** if it came from
|
|
@@ -231,6 +237,16 @@ state rather than guesswork. A crash skips this — and that's fine: the livenes
|
|
|
231
237
|
to `stale`, the assignment becomes `reclaimable`, and takeover (§10) handles it. Clean release just
|
|
232
238
|
makes the common case instant instead of TTL-delayed.
|
|
233
239
|
|
|
240
|
+
**Ownership scoping (#440):** the Stop hook's evidence scanning, its non-terminal release (above), the
|
|
241
|
+
tool-activity liveness heartbeat, and the SessionStart/UserPromptSubmit re-ground banner all resolve
|
|
242
|
+
**only** from the stopping/heartbeating/steered actor's own per-actor `current/<actor>.json` pointer
|
|
243
|
+
when that actor is resolved — never from the shared legacy `current.json` or a repo-wide newest-mtime
|
|
244
|
+
scan, which would otherwise let a session co-located with another actor's work inherit that actor's gate
|
|
245
|
+
debt or steer onto its slug. Accepted gap: a resolved actor with no per-actor pointer yet (pre any
|
|
246
|
+
`workflow-sidecar` command in this session) is simply ungated/unbannered until its next sidecar command
|
|
247
|
+
establishes one — never gated on another actor's unrelated work. An unresolved actor keeps the pre-#440
|
|
248
|
+
legacy-fallback behavior unchanged (compat + anti-gaming: identity cannot be unset to escape the gate).
|
|
249
|
+
|
|
234
250
|
## 8. Guard point 3 — the verify-hold publish gate (the one hard fence)
|
|
235
251
|
|
|
236
252
|
This is the **only** place coordination *blocks*, and it earned three fix iterations, so its design is
|
|
@@ -17,6 +17,7 @@ run `npm run validate:source --` and `npm run fixture:retirement-audit --`.
|
|
|
17
17
|
| `evals/fixtures/backlog-provider-settings` | settings precedence fixtures | `evals/integration/test_effective_backlog_settings.sh` | Keep while backlog provider settings resolution supports global defaults and project overrides. |
|
|
18
18
|
| `evals/fixtures/builder-kit-workflow-state` | Builder Kit workflow-state fixtures | `evals/static/test_workflow_skills.sh` | Keep while Builder Kit state contract and resume behavior are documented in workflow skill contracts. |
|
|
19
19
|
| `evals/fixtures/console-learning-projection` | console learning projection fixtures | `evals/integration/test_console_learning_projection.sh` | Keep while learning projection supports correction and open-route examples. |
|
|
20
|
+
| `evals/fixtures/codex-legacy-agents` | exact historical Flow Agents-generated Codex AGENTS.md migration fixtures (#563) | `evals/integration/test_install_merge.sh` | Keep while the Codex home installer recognizes audited historical payload hashes, refuses before mutation, and provides explicit operator remediation without fuzzy ownership matching. |
|
|
20
21
|
| `evals/fixtures/economics` | 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 | `evals/integration/test_economics_record.sh` | Keep while the `kontour.console.economics` v0.1 record contract (docs/specs/economics-record-contract.md) is enforced; the golden proves cost-from-transcript, defects-from-critique, verdict-from-state, and the R7 co-required guard. |
|
|
21
22
|
| `evals/fixtures/flow-kit-repository` | Flow Kit repository contract fixtures | `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` | Keep valid and invalid cases paired with the Flow Kit repository contract. |
|
|
22
23
|
| `evals/fixtures/kit-conformance-levels` | K-level conformance and consumer-target derivation fixtures | `evals/integration/test_kit_conformance_levels.sh` | Keep while K-level derivation, degradation invariant, and consumer-target badge rules are tested. |
|
|
@@ -26,7 +27,7 @@ run `npm run validate:source --` and `npm run fixture:retirement-audit --`.
|
|
|
26
27
|
| `evals/fixtures/pull-work-wip-shepherding` | WIP shepherding state fixtures | `evals/static/test_workflow_skills.sh` | Keep while pull-work documents personal versus global WIP behavior. |
|
|
27
28
|
| `evals/fixtures/reconcile-preflight` | #356 reconcile-preflight shape fixtures not already covered by trust-reconcile-exploits (un-superseded disputed critique, standalone disputed session-local claim) | `evals/integration/test_reconcile_preflight.sh` | Keep while the local `reconcile-preflight` subcommand (#356) is proven against the two shapes trust-reconcile-exploits does not already fixture (un-superseded disputed critique, standalone disputed session-local claim); the other four shapes reuse trust-reconcile-exploits/trust-reconcile-mixed-bundle directly rather than forking near-duplicates. |
|
|
28
29
|
| `evals/fixtures/surface-trust` | Surface trust evidence fixtures | `evals/integration/test_workflow_sidecar_writer.sh` | Keep while sidecar writer maps Surface trust evidence into workflow records. |
|
|
29
|
-
| `evals/fixtures/telemetry` | 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 | `evals/integration/test_usage_cost.sh`, `evals/integration/test_telemetry_usage_pipeline.sh` | Keep while telemetry.sh's Stop-hook usage pipeline (usage_parse_transcript / usage_model_from_transcript_usage) is proven against
|
|
30
|
+
| `evals/fixtures/telemetry` | 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 | `evals/integration/test_usage_cost.sh`, `evals/integration/test_telemetry_usage_pipeline.sh`, `evals/integration/test_telemetry_tool_usage.sh` | Keep while telemetry.sh's Stop-hook usage pipeline (usage_parse_transcript / usage_model_from_transcript_usage / usage_last_turn_usage) is proven against hermetic multi-model and oversized-prefix transcripts rather than relying on live runtime data. |
|
|
30
31
|
| `evals/fixtures/trust-reconcile-exploits` | WS8 trust-reconcile anti-gaming exploit fixtures (frozen negative regressions); also reused by the #356 local reconcile-preflight eval (same shapes, no forked copies) | `evals/integration/test_trust_reconcile_negatives.sh`, `evals/integration/test_reconcile_preflight.sh` | Keep while trust-reconcile.js enforces the WS8 iteration-2 soundness properties (no-label test_output, unwaived-assumed, status-misassertion, waiver-on-command); each fixture is a permanent negative regression. |
|
|
31
32
|
| `evals/fixtures/trust-reconcile-mixed-bundle` | WS8 trust-reconcile mixed-evidence end-to-end proof fixture; also reused by the #356 reconcile-preflight eval as its CLEAN-BUNDLE (AC4) case | `evals/integration/test_trust_reconcile_mixed_bundle.sh`, `evals/integration/test_reconcile_preflight.sh` | Keep while the trust-reconcile manifest/classification/waiver contract (ADR 0020) is enforced; proves a mixed test_output + session-local + waived bundle passes the CI anchor. |
|
|
32
33
|
| `evals/fixtures/trust-reconcile-ws3` | WS8 AC6 backward-compat fixture: real ws3-kit-dependencies-namespacing old-style bundle | `evals/integration/test_trust_reconcile_negatives.sh` | Keep while backward compatibility with pre-classification (all-test_output) bundles is asserted; proves an old-style bundle still FAILS the same way (no silent pass). |
|
|
@@ -167,6 +167,50 @@ state rollback or deletion is rejected when its append-only event history proves
|
|
|
167
167
|
started. These local coordination records detect accidental or in-process rollback; they are not a
|
|
168
168
|
cryptographic boundary against a process that can rewrite the entire artifact directory.
|
|
169
169
|
|
|
170
|
+
Immediately before spawning an adapter turn, the driver writes a transient, schema-versioned
|
|
171
|
+
`active-turn.json` beside its mission state and passes a raw 32-byte turn secret plus the path-safe,
|
|
172
|
+
signed run id in `FLOW_AGENTS_CONTINUATION_TURN_SECRET` and
|
|
173
|
+
`FLOW_AGENTS_CONTINUATION_RUN_ID` to that child. Only the secret's SHA-256 is persisted in the signed
|
|
174
|
+
record. The driver's schema-1-compatible mission state separately stores the ephemeral public-key
|
|
175
|
+
digest before the adapter starts, so replacing and correctly re-signing the entire active-turn
|
|
176
|
+
record with another key does not replace the signer anchor. The driver clears that digest with the
|
|
177
|
+
active-turn step on every completion, error, cleanup, terminal, waiting, and budget path. It replaces
|
|
178
|
+
every inherited continuation capability variable but preserves ordinary
|
|
179
|
+
`FLOW_AGENTS_ACTOR`. The shared actor
|
|
180
|
+
resolver remains ordinary: it never accepts continuation data as an identity override. When an
|
|
181
|
+
assignment-gated public workflow command finds that ordinary resolution does not match, it may use
|
|
182
|
+
only a live signed active-turn record bound to the exact session, turn secret, run id, assignment file and
|
|
183
|
+
actor struct, mission, adapter identity, expiry, and driver lock; it returns the signed assignment
|
|
184
|
+
identity only for that active-turn evidence gate. Pause, resume, release, cancel, and archive remain
|
|
185
|
+
control-plane operations: they require ordinary actor identity or their existing explicit external
|
|
186
|
+
authority and never accept this turn capability. The private key remains only in the driver process.
|
|
187
|
+
The Stop hook resolves the signed run id under the canonical artifact root and fully validates that
|
|
188
|
+
exact session before consulting ordinary current pointers. Once the base signed turn remains valid,
|
|
189
|
+
that exact session stays selected even if canonical Flow has become paused, blocked, completed, or
|
|
190
|
+
another canonical disposition; Stop never falls back to a conflicting actor or global pointer. It
|
|
191
|
+
securely validates canonical state against the run's definition and treats only canonical `active`
|
|
192
|
+
as authority to make the ordinary unfinished
|
|
193
|
+
canonical-gate warning advisory so the adapter can return control to the driver. It never advances
|
|
194
|
+
a Flow gate, releases assignment or liveness for a continuation-owned nonterminal run, or relaxes evidence, integrity, false-completion,
|
|
195
|
+
malformed-state, or configuration blocks. The record is removed when the child completes, errors,
|
|
196
|
+
or times out; parent identity changes leave it to expire instead of unlinking through a replacement.
|
|
197
|
+
|
|
198
|
+
This is cooperative same-user protection, not cryptographic filesystem isolation from a hostile
|
|
199
|
+
same-UID process. A same-UID process that can rewrite both mission state and authority records or
|
|
200
|
+
control the driver process remains outside this boundary. Within the cooperative boundary, the
|
|
201
|
+
mission digest anchors the driver's ephemeral signer, while descriptor reads, final-path inode rechecks, and realpath/device/inode parent
|
|
202
|
+
rechecks detect practical replacement races. Active-turn and lock records are capped at 16 KiB;
|
|
203
|
+
canonical assignment and continuation mission records are capped at a conservative 1 MiB so valid
|
|
204
|
+
provider metadata is not rejected. PID liveness is best-effort only: PID reuse and same-UID process control remain outside this
|
|
205
|
+
local coordination boundary.
|
|
206
|
+
|
|
207
|
+
The event stream records `turn_completed`, `gate_not_advanced`, `turn_failed`, and best-effort
|
|
208
|
+
`authority_cleanup_failed`. Cleanup failures are audited but do not replace the adapter or canonical
|
|
209
|
+
outcome. Failed turns carry
|
|
210
|
+
`failure_kind` of `timeout` or `adapter_error`; a completed adapter turn whose canonical run remains
|
|
211
|
+
active at the same current step records `gate_not_advanced`. These events describe driver execution only and do not
|
|
212
|
+
change canonical Flow state.
|
|
213
|
+
|
|
170
214
|
## Compatibility Doctor
|
|
171
215
|
|
|
172
216
|
Run doctor through the exact isolated package helper defined above:
|
|
@@ -27,13 +27,15 @@ Every Flow Agents event has a canonical name that is runtime-neutral. Adapters m
|
|
|
27
27
|
| --- | --- | --- | --- |
|
|
28
28
|
| `agentSpawn` | A new agent session starts. Maps from `SessionStart` on Claude Code and Codex. | `hook_event_name`, `cwd` | `session_id`, `agent_id`, `model`, `runtime` |
|
|
29
29
|
| `userPromptSubmit` | The user submits a new turn or message. Maps from `UserPromptSubmit`. | `hook_event_name` | `turn.prompt_text` (redacted by default), `cwd` |
|
|
30
|
-
| `preToolUse` | Immediately before a tool call is executed. Maps from `PreToolUse`. | `hook_event_name`, `tool_name`, `tool_input` | `tool_id`, `cwd` |
|
|
30
|
+
| `preToolUse` | Immediately before a tool call is executed. Maps from `PreToolUse`. | `hook_event_name`, `tool_name`, `tool_input` | `tool_id`, `cwd`, `usage.model`, `usage.input_tokens`, `usage.output_tokens`, `usage.cache_creation_input_tokens`, `usage.cache_read_input_tokens`, `usage.estimated_cost_usd`, `usage.pricing_version` |
|
|
31
31
|
| `permissionRequest` | The runtime is asking for permission to run a tool or action. Maps from `PermissionRequest`. | `hook_event_name`, `tool_name` | `tool_input`, `cwd` |
|
|
32
|
-
| `postToolUse` | After a tool call completes (success or failure). Maps from `PostToolUse` and `PostToolUseFailure`. | `hook_event_name`, `tool_name`, `tool_response` | `tool_input`, `tool_output`, `error`, `cwd` |
|
|
32
|
+
| `postToolUse` | After a tool call completes (success or failure). Maps from `PostToolUse` and `PostToolUseFailure`. | `hook_event_name`, `tool_name`, `tool_response` | `tool_input`, `tool_output`, `error`, `cwd`, `usage.model`, `usage.input_tokens`, `usage.output_tokens`, `usage.cache_creation_input_tokens`, `usage.cache_read_input_tokens`, `usage.estimated_cost_usd`, `usage.pricing_version` |
|
|
33
33
|
| `stop` | The agent is about to stop and return control to the user. Maps from `Stop` and `SessionEnd`. | `hook_event_name` | `stop_reason`, `cwd` |
|
|
34
34
|
| `subagentStart` | A subagent or specialist delegate is spawning. Maps from `SubagentStart` (Claude Code). | `hook_event_name` | `agent_name`, `agent_type` |
|
|
35
35
|
| `subagentStop` | A subagent or specialist delegate has stopped. Maps from `SubagentStop` (Claude Code). | `hook_event_name` | `agent_name`, `outcome` |
|
|
36
36
|
|
|
37
|
+
**`usage.*` on `preToolUse`/`postToolUse` (#568 slice 1).** These two events carry an optional `.usage` object — `model`, `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens`, `estimated_cost_usd`, `pricing_version` — sourced from the runtime transcript's LAST assistant turn (the turn that produced this specific tool call), joined via a bounded tail-read of `hook.transcript_path`. This is **per-turn, not a per-tool-call cost fraction**: multiple tool calls inside the same assistant turn (parallel tool_use blocks) report the *same* whole-turn usage figures — do not sum `estimated_cost_usd` across `tool.invoke`/`tool.result` rows within one turn, or cost will be double-counted; `session.usage`'s cumulative totals remain the authoritative aggregate. When the transcript join is unavailable but the runtime's `.model` hook field is present, only `usage.model` is populated and every token/cost field is explicitly `null` (never a guessed number); `.model` itself is best-effort on these two events (see §8.2), not a contractually guaranteed field. `tool.permission_request` (`permissionRequest`) is explicitly excluded from this enrichment.
|
|
38
|
+
|
|
37
39
|
### Redaction Defaults
|
|
38
40
|
|
|
39
41
|
Telemetry channels redact sensitive payload fields before emission. Adapters must honor these defaults and must not log raw hook payloads without applying channel redaction.
|
|
@@ -518,11 +520,13 @@ All payloads are a single JSON object on stdin. Required and optional fields:
|
|
|
518
520
|
|
|
519
521
|
| Canonical event | Required fields | Optional fields |
|
|
520
522
|
|----------------|-----------------|-----------------|
|
|
521
|
-
| `preToolUse` | `hook_event_name` | `tool_name`, `tool_input.path`, `tool_input.file_path`, `cwd` |
|
|
522
|
-
| `postToolUse` | `hook_event_name` | `tool_name`, `tool_input.path`, `tool_input.file_path`, `tool_response`, `cwd` |
|
|
523
|
+
| `preToolUse` | `hook_event_name` | `tool_name`, `tool_input.path`, `tool_input.file_path`, `cwd`, `usage.model`, `usage.input_tokens`, `usage.output_tokens`, `usage.cache_creation_input_tokens`, `usage.cache_read_input_tokens`, `usage.estimated_cost_usd`, `usage.pricing_version` |
|
|
524
|
+
| `postToolUse` | `hook_event_name` | `tool_name`, `tool_input.path`, `tool_input.file_path`, `tool_response`, `cwd`, `usage.model`, `usage.input_tokens`, `usage.output_tokens`, `usage.cache_creation_input_tokens`, `usage.cache_read_input_tokens`, `usage.estimated_cost_usd`, `usage.pricing_version` |
|
|
523
525
|
| `userPromptSubmit` | `hook_event_name` | `tool_input` (for subagent calls), `cwd` |
|
|
524
526
|
| `stop` | `hook_event_name` | `cwd`, `stop_reason` |
|
|
525
527
|
|
|
528
|
+
`usage.*` on `preToolUse`/`postToolUse` above is emitted output, not required input — it is populated by the telemetry adapter from the runtime transcript's last assistant turn (or degrades to `usage.model`-only / fully-null per the documented fallback tiers in §1), not read from the hook's stdin payload. It is **per-turn**, not a per-tool-call cost fraction: consumers must not sum `estimated_cost_usd` across tool events within the same assistant turn (see §1). The runtime-native `.model` field these events derive part of this from is best-effort, not contractually guaranteed by any host today.
|
|
529
|
+
|
|
526
530
|
`hook_event_name` is the **host-native** event name (e.g., `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `Stop`) or may be omitted — policy scripts read the canonical fields (`tool_input.path`, `cwd`) directly and do not require the event name field for their decisions.
|
|
527
531
|
|
|
528
532
|
### 8.3 Decision schema (stdout / exit code)
|
|
@@ -22,6 +22,19 @@
|
|
|
22
22
|
set -uo pipefail
|
|
23
23
|
|
|
24
24
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
25
|
+
# #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
|
|
26
|
+
# and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
|
|
27
|
+
# ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
|
|
28
|
+
# analyze() (and evidence-capture.js's resolveArtifactDir) now scope to that actor's own
|
|
29
|
+
# (nonexistent) pointer and never reach the fixture-under-test at all. This suite is about
|
|
30
|
+
# anti-gaming/capture-teeth mechanics, not #440's ownership scoping, so forcing the documented
|
|
31
|
+
# test-only unresolved-actor escape hatch restores EXACTLY this suite's pre-#440 behavior (D3
|
|
32
|
+
# compat: an unresolved actor keeps the unchanged legacy-fallback/global-scan discovery every
|
|
33
|
+
# assertion below was written against). `env`-prefixed subprocess invocations below inherit this
|
|
34
|
+
# exported pair (env without -i does not clear the parent environment).
|
|
35
|
+
export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
|
|
36
|
+
export NODE_ENV=test
|
|
37
|
+
|
|
25
38
|
GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
|
|
26
39
|
|
|
27
40
|
export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000
|
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
set -uo pipefail
|
|
13
13
|
|
|
14
14
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
15
|
+
# #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
|
|
16
|
+
# and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
|
|
17
|
+
# ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
|
|
18
|
+
# analyze() (and evidence-capture.js's resolveArtifactDir) now scope to that actor's own
|
|
19
|
+
# (nonexistent) pointer and never reach the fixture-under-test at all. This suite is about
|
|
20
|
+
# anti-gaming/capture-teeth mechanics, not #440's ownership scoping, so forcing the documented
|
|
21
|
+
# test-only unresolved-actor escape hatch restores EXACTLY this suite's pre-#440 behavior (D3
|
|
22
|
+
# compat: an unresolved actor keeps the unchanged legacy-fallback/global-scan discovery every
|
|
23
|
+
# assertion below was written against). `env`-prefixed subprocess invocations below inherit this
|
|
24
|
+
# exported pair (env without -i does not clear the parent environment).
|
|
25
|
+
export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
|
|
26
|
+
export NODE_ENV=test
|
|
27
|
+
|
|
15
28
|
pass=0; fail=0
|
|
16
29
|
_p(){ echo " ✓ $1"; pass=$((pass+1)); }
|
|
17
30
|
_f(){ echo " ✗ $1"; fail=$((fail+1)); }
|
package/evals/ci/run-baseline.sh
CHANGED
|
@@ -59,6 +59,7 @@ CHECKS=(
|
|
|
59
59
|
"Telemetry doctor integration|bash evals/integration/test_telemetry_doctor.sh"
|
|
60
60
|
"Usage and cost integration|bash evals/integration/test_usage_cost.sh"
|
|
61
61
|
"Telemetry usage pipeline integration|bash evals/integration/test_telemetry_usage_pipeline.sh"
|
|
62
|
+
"Telemetry tool usage integration|bash evals/integration/test_telemetry_tool_usage.sh"
|
|
62
63
|
"Economics record integration|bash evals/integration/test_economics_record.sh"
|
|
63
64
|
"Learning review proposals integration|bash evals/integration/test_learning_review_proposals.sh"
|
|
64
65
|
"Utterance check integration|bash evals/integration/test_utterance_check.sh"
|
|
@@ -152,6 +153,7 @@ LANE_RUNTIME_AND_KIT=(
|
|
|
152
153
|
"Telemetry doctor integration"
|
|
153
154
|
"Usage and cost integration"
|
|
154
155
|
"Telemetry usage pipeline integration"
|
|
156
|
+
"Telemetry tool usage integration"
|
|
155
157
|
"Economics record integration"
|
|
156
158
|
"Learning review proposals integration"
|
|
157
159
|
"Utterance check integration"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Universal Agent Bundle (Codex)
|
|
2
|
+
|
|
3
|
+
This bundle was generated from the canonical source in this repo. Treat the repo root as the source of truth and regenerate the bundle instead of editing exported agent files by hand.
|
|
4
|
+
|
|
5
|
+
## Shared Conventions
|
|
6
|
+
|
|
7
|
+
- `skills/`, `context/`, `powers/`, `prompts/`, `scripts/`, and `evals/` were copied from the canonical source.
|
|
8
|
+
- Cross-session task artifacts should live under `.kontourai/flow-agents`.
|
|
9
|
+
- Kiro-only hook wiring was stripped from exported non-Kiro agents to keep the package portable.
|
|
10
|
+
|
|
11
|
+
## Exported Agents
|
|
12
|
+
|
|
13
|
+
- `tool-code-reviewer` — Delegate to me for code quality review. Analyzes readability, maintainability, patterns, DRY compliance, and produces structured review with severity levels. Separate from verification (build/test/lint).
|
|
14
|
+
- `tool-dependencies-updater` — Delegate to me for updating your project dependencies - checks latest versions, identifies outdated packages, and finds security advisories across npm, PyPI, Cargo, Maven/Gradle, Go, NuGet, Ruby, PHP, Swift, Dart, Docker, Helm, Terraform, and GitHub Actions
|
|
15
|
+
- `tool-explore-config` — Delegate to me for project configuration inspection - finds and summarizes configuration files and environment variables within a project
|
|
16
|
+
- `tool-explore-deps` — Delegate to me for Dependency analysis - parses package manifests to identify tech stack and dependencies
|
|
17
|
+
- `tool-explore-entry` — Delegate to me to find the Entry point of a project - locates main files, CLI commands, API routes, and exports
|
|
18
|
+
- `tool-explore-patterns` — Delegate to me for Pattern detection - identifies architectural patterns, frameworks, and coding conventions
|
|
19
|
+
- `tool-explore-structure` — Delegate to me to scout out the project structure - maps directory layout and identifies key folders in a codebase
|
|
20
|
+
- `tool-explore-tests` — Delegate to me to find and understand testing strategies - locates test files and understands testing strategy
|
|
21
|
+
- `tool-planner` — Delegate to me for codebase analysis and execution planning. Explores code, identifies patterns and dependencies, and writes plan/sidecar artifacts under .kontourai/flow-agents. No production file modifications.
|
|
22
|
+
- `tool-playwright` — Delegate to me for browser automation, testing, and debugging - loading real pages, testing navigation, checking accessibility via structured snapshots, evaluating scripts, and visual verification. Anything that would otherwise require a browser. Do NOT use for general web search or fetching content
|
|
23
|
+
- `tool-security-reviewer` — Delegate to me for security analysis. Checks OWASP Top 10, secrets detection, input validation, injection vulnerabilities, auth/authz, and rate limiting. Read-only analysis with shell for scanning tools.
|
|
24
|
+
- `tool-verifier` — Delegate to me for implementation verification. Read-only + shell for source code; writes review/evidence artifacts under .kontourai/flow-agents. Verifies acceptance criteria and produces PASS/FAIL/NOT_VERIFIED verdicts with evidence. No production file modifications.
|
|
25
|
+
- `tool-worker` — Delegate to me for writing and developing source code for a project. Works best when a detailed plan can be provided. NO access to web tools. Can be used in parallel for any coding tasks that require trusted access to the write and shell tools. WARNING: May spawn a `git worktree`
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"type":"user","message":{"role":"user","content":"benign filler line so the adversarial assistant line is not the only content"}}
|
|
2
|
+
{"type":"assistant","message":{"model":"SYSTEM PROMPT LEAK: the user's SSN is 000-00-0000 and API key sk-FAKE-adversarial-fixture","usage":{"input_tokens":"the user's private prompt said: attack the server at 203.0.113.7 with admin/hunter2","output_tokens":"also-not-a-number","cache_creation_input_tokens":{"nested":"object"},"cache_read_input_tokens":[1,2,3]}}}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
{"type":"assistant","message":{"model":"bad-before" this line is not valid JSON at all
|
|
2
|
+
{"type": "assistant", "message": {"model": "claude-malformed-sandwich-safe", "usage": {"input_tokens": 10, "output_tokens": 20, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0}}}
|
|
3
|
+
{this is not json either, noise after the valid line
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "assistant", "message": {"model": "claude-opus-4-8", "usage": {"input_tokens": -500, "output_tokens": 20, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0}}}
|