@kontourai/flow-agents 3.3.0 → 3.4.1
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/add-to-project.yml +15 -0
- package/.github/workflows/ci.yml +161 -0
- package/CHANGELOG.md +48 -0
- package/CONTEXT.md +5 -1
- package/README.md +19 -8
- package/build/src/builder-flow-run-adapter.d.ts +80 -0
- package/build/src/builder-flow-run-adapter.js +241 -0
- package/build/src/builder-flow-runtime.d.ts +16 -0
- package/build/src/builder-flow-runtime.js +290 -0
- package/build/src/cli/builder-run.d.ts +1 -0
- package/build/src/cli/builder-run.js +27 -0
- package/build/src/cli/effective-backlog-settings.js +70 -2
- package/build/src/cli/init.d.ts +34 -0
- package/build/src/cli/init.js +341 -61
- package/build/src/cli/kit.js +55 -12
- package/build/src/cli/pull-work-provider.js +346 -5
- package/build/src/cli/skill-drift-check.d.ts +1 -0
- package/build/src/cli/skill-drift-check.js +165 -0
- package/build/src/cli/telemetry-doctor.d.ts +37 -0
- package/build/src/cli/telemetry-doctor.js +53 -6
- package/build/src/cli/validate-hook-influence.js +37 -7
- package/build/src/cli/workflow-sidecar.d.ts +93 -8
- package/build/src/cli/workflow-sidecar.js +1175 -158
- package/build/src/cli.js +5 -0
- package/build/src/flow-kit/validate.d.ts +54 -34
- package/build/src/flow-kit/validate.js +237 -26
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/lib/console-connect-options.d.ts +97 -0
- package/build/src/lib/console-connect-options.js +199 -0
- package/build/src/lib/console-telemetry-validate.d.ts +49 -0
- package/build/src/lib/console-telemetry-validate.js +91 -0
- package/build/src/lib/flow-resolver.d.ts +56 -3
- package/build/src/lib/flow-resolver.js +151 -11
- package/build/src/lib/fs.d.ts +17 -0
- package/build/src/lib/fs.js +172 -0
- package/build/src/lib/local-artifact-root.d.ts +44 -1
- package/build/src/lib/local-artifact-root.js +131 -3
- package/build/src/runtime-adapters.d.ts +39 -3
- package/build/src/runtime-adapters.js +77 -31
- package/build/src/tools/build-universal-bundles.js +40 -2
- package/build/src/tools/codex-agent-routing.d.ts +2 -0
- package/build/src/tools/codex-agent-routing.js +49 -0
- package/build/src/tools/generate-context-map.js +1 -0
- package/build/src/tools/validate-source-tree.js +27 -1
- package/context/scripts/hooks/lib/kit-catalog.js +235 -0
- package/context/scripts/hooks/lib/runnable-command.js +177 -0
- package/context/scripts/hooks/stop-goal-fit.js +278 -48
- package/context/scripts/hooks/workflow-steering.js +121 -21
- package/context/scripts/package.json +3 -0
- package/context/scripts/telemetry/install-console-config.sh +25 -4
- package/context/scripts/telemetry/lib/config.sh +102 -12
- package/context/scripts/telemetry/lib/pricing.sh +50 -0
- package/context/scripts/telemetry/lib/session.sh +3 -0
- package/context/scripts/telemetry/lib/transport.sh +87 -0
- package/context/scripts/telemetry/lib/usage.sh +205 -4
- package/context/scripts/telemetry/telemetry.conf +6 -0
- package/context/scripts/telemetry/telemetry.sh +48 -0
- package/context/settings/workspace-backlog-provider-settings.example.json +48 -0
- package/docs/agent-usage-feedback-loop.md +35 -0
- package/docs/architecture-engine-and-kits.md +110 -0
- package/docs/context-map.md +2 -0
- package/docs/decisions/embeddable-engine.md +152 -0
- package/docs/decisions/index.md +3 -1
- package/docs/decisions/trust-ledger-retention.md +88 -0
- package/docs/decisions/workflow-enforcement.md +31 -9
- package/docs/fixture-ownership.md +3 -0
- package/docs/implementing-trust-reconciliation.md +129 -0
- package/docs/index.md +19 -9
- package/docs/integrations/flow-agents-console.md +167 -0
- package/docs/kit-authoring-guide.md +52 -21
- package/docs/spec/builder-flow-runtime.md +80 -0
- package/docs/spec/runtime-hook-surface.md +45 -1
- package/docs/specs/economics-record-contract.md +270 -0
- package/docs/specs/harness-capability-matrix.md +74 -0
- package/docs/specs/learning-review-proposals-contract.md +340 -0
- package/docs/specs/routing-efficiency-review.md +59 -0
- package/docs/verifiable-trust.md +74 -25
- package/docs/workflow-usage-guide.md +10 -0
- package/evals/acceptance/prove-capture-teeth.sh +132 -0
- package/evals/ci/antigaming-suite.sh +1 -0
- package/evals/ci/run-baseline.sh +72 -4
- package/evals/fixtures/economics/acceptance.json +12 -0
- package/evals/fixtures/economics/agents/tool-worker-1/events.jsonl +2 -0
- package/evals/fixtures/economics/agents/tool-worker-2/events.jsonl +2 -0
- package/evals/fixtures/economics/agents/tool-worker-3/events.jsonl +2 -0
- package/evals/fixtures/economics/agents/tool-worker-4/events.jsonl +1 -0
- package/evals/fixtures/economics/agents/tool-worker-5/events.jsonl +2 -0
- package/evals/fixtures/economics/critique.json +22 -0
- package/evals/fixtures/economics/expected-record.json +71 -0
- package/evals/fixtures/economics/session-usage-event.json +1 -0
- package/evals/fixtures/economics/state.json +11 -0
- package/evals/fixtures/economics/transcript.jsonl +3 -0
- package/evals/fixtures/hook-influence/cases.json +7 -7
- package/evals/fixtures/learning-review-proposals/balanced/economics.jsonl +6 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/economics.jsonl +5 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-1/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-2/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-3/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-4/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-5/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/economics.jsonl +6 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.json +30 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.md +66 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-5/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-6/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/repeat-window/economics.jsonl +6 -0
- package/evals/fixtures/learning-review-proposals/under-threshold/economics.jsonl +3 -0
- package/evals/fixtures/telemetry/usage-transcript-sample.jsonl +4 -0
- package/evals/fixtures/trust-reconcile-exploits/mcp-degrade.json +42 -0
- package/evals/integration/test_builder_entry_enforcement.sh +241 -0
- package/evals/integration/test_builder_step_producers.sh +18 -10
- package/evals/integration/test_bundle_install.sh +172 -0
- package/evals/integration/test_console_tenant_isolation.sh +167 -0
- package/evals/integration/test_critique_supersession_roundtrip.sh +4 -1
- package/evals/integration/test_dual_emit_flow_step.sh +10 -4
- package/evals/integration/test_economics_record.sh +674 -0
- package/evals/integration/test_effective_backlog_settings.sh +1 -1
- package/evals/integration/test_evidence_capture_hook.sh +17 -2
- package/evals/integration/test_exemption_usage_review.sh +198 -0
- package/evals/integration/test_fixture_retirement_audit.sh +2 -2
- package/evals/integration/test_flow_kit_install_git.sh +83 -0
- package/evals/integration/test_flowdef_session_activation.sh +0 -1
- package/evals/integration/test_flowdef_session_history_preservation.sh +13 -3
- package/evals/integration/test_gate_lockdown.sh +7 -0
- package/evals/integration/test_gate_review_inquiry_records.sh +9 -1
- package/evals/integration/test_goal_fit_hook.sh +2031 -0
- package/evals/integration/test_hook_category_behaviors.sh +8 -1
- package/evals/integration/test_hook_influence_cases.sh +25 -1
- package/evals/integration/test_install_merge.sh +227 -2
- package/evals/integration/test_kit_conformance_levels.sh +6 -6
- package/evals/integration/test_learning_review_proposals.sh +329 -0
- package/evals/integration/test_liveness_conflict_injection.sh +26 -22
- package/evals/integration/test_liveness_console_relay.sh +166 -0
- package/evals/integration/test_liveness_heartbeat.sh +17 -17
- package/evals/integration/test_liveness_worktree_root.sh +575 -0
- package/evals/integration/test_phase_map_and_gate_claim.sh +6 -1
- package/evals/integration/test_publish_delivery.sh +331 -1
- package/evals/integration/test_pull_work_board.sh +200 -0
- package/evals/integration/test_pull_work_provider.sh +1 -1
- package/evals/integration/test_record_check.sh +378 -0
- package/evals/integration/test_routing_efficiency.sh +71 -0
- package/evals/integration/test_runtime_adapter_activation.sh +28 -0
- package/evals/integration/test_session_resume_roundtrip.sh +16 -19
- package/evals/integration/test_skill_drift_check.sh +870 -0
- package/evals/integration/test_telemetry.sh +445 -0
- package/evals/integration/test_telemetry_doctor.sh +66 -0
- package/evals/integration/test_telemetry_usage_pipeline.sh +228 -0
- package/evals/integration/test_trust_reconcile_negatives.sh +30 -13
- package/evals/integration/test_trust_reconcile_trailer_diagnostic.sh +247 -0
- package/evals/integration/test_usage_cost.sh +61 -0
- package/evals/integration/test_workflow_sidecar_writer.sh +1395 -0
- package/evals/integration/test_workflow_steering_hook.sh +157 -16
- package/evals/integration/test_workspace_settings.sh +176 -0
- package/evals/lib/env.sh +26 -0
- package/evals/lib/node.sh +8 -0
- package/evals/run.sh +29 -0
- package/evals/static/test_ci_integration_coverage.sh +115 -0
- package/evals/static/test_declared_scope_forms_documented.sh +114 -0
- package/evals/static/test_universal_bundles.sh +34 -0
- package/evals/static/test_validate_source_kit_asset_scope.sh +259 -0
- package/evals/static/test_workflow_skills.sh +1 -1
- package/kits/builder/flows/build.flow.json +9 -18
- package/kits/builder/flows/publish-learn.flow.json +5 -1
- package/kits/builder/kit.json +120 -0
- package/kits/builder/skills/deliver/SKILL.md +42 -0
- package/kits/builder/skills/evidence-gate/SKILL.md +12 -0
- package/kits/builder/skills/execute-plan/SKILL.md +9 -0
- package/kits/builder/skills/learning-review/SKILL.md +51 -0
- package/kits/builder/skills/plan-work/SKILL.md +17 -20
- package/kits/builder/skills/pull-work/SKILL.md +21 -0
- package/kits/builder/skills/release-readiness/SKILL.md +12 -0
- package/kits/knowledge/kit.json +9 -0
- package/kits/veritas-governance/docs/README.md +35 -7
- package/kits/veritas-governance/fixtures/exemption-review/mixed-fresh-stale.DECLARED.json +14 -0
- package/kits/veritas-governance/kit.json +14 -0
- package/kits/veritas-governance/skills/exemption-usage-review/SKILL.md +128 -0
- package/kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs +231 -0
- package/package.json +2 -2
- package/packaging/manifest.json +29 -0
- package/schemas/backlog-provider-settings.schema.json +13 -0
- package/schemas/workflow-state.schema.json +44 -0
- package/scripts/README.md +4 -0
- package/scripts/check-content-boundary.cjs +8 -1
- package/scripts/ci/trust-reconcile.js +136 -0
- package/scripts/hooks/codex-hook-adapter.js +77 -2
- package/scripts/hooks/evidence-capture.js +38 -5
- package/scripts/hooks/lib/codex-exit-code.js +316 -0
- package/scripts/hooks/lib/kit-catalog.js +235 -0
- package/scripts/hooks/lib/liveness-write.js +28 -1
- package/scripts/hooks/lib/local-artifact-paths.js +97 -1
- package/scripts/hooks/lib/runnable-command.js +177 -0
- package/scripts/hooks/lib/skill-drift.js +350 -0
- package/scripts/hooks/stop-goal-fit.js +278 -48
- package/scripts/hooks/workflow-steering.js +121 -21
- package/scripts/install-codex-home.sh +97 -47
- package/scripts/install-merge.js +72 -14
- package/scripts/install-owned-files.js +178 -0
- package/scripts/liveness/relay.sh +84 -0
- package/scripts/telemetry/economics-record.schema.json +145 -0
- package/scripts/telemetry/economics-record.sh +331 -0
- package/scripts/telemetry/install-console-config.sh +25 -4
- package/scripts/telemetry/learning-review-decide.sh +124 -0
- package/scripts/telemetry/learning-review-proposals.schema.json +161 -0
- package/scripts/telemetry/learning-review-proposals.sh +484 -0
- package/scripts/telemetry/lib/config.sh +102 -12
- package/scripts/telemetry/lib/pricing.sh +14 -6
- package/scripts/telemetry/lib/session.sh +3 -0
- package/scripts/telemetry/lib/transport.sh +133 -15
- package/scripts/telemetry/lib/usage.sh +121 -28
- package/scripts/telemetry/routing-efficiency.sh +0 -0
- package/scripts/telemetry/telemetry.conf +6 -0
- package/scripts/telemetry/telemetry.sh +48 -0
- package/src/builder-flow-run-adapter.ts +357 -0
- package/src/builder-flow-runtime.ts +348 -0
- package/src/cli/builder-flow-run-adapter.test.mjs +495 -0
- package/src/cli/builder-flow-runtime.test.mjs +213 -0
- package/src/cli/builder-run.ts +28 -0
- package/src/cli/codex-agent-routing.test.mjs +44 -0
- package/src/cli/codex-exit-code.test.mjs +207 -0
- package/src/cli/console-connect-options.test.mjs +329 -0
- package/src/cli/console-telemetry-validate.test.mjs +157 -0
- package/src/cli/effective-backlog-settings.ts +68 -2
- package/src/cli/flow-resolver-composition.test.mjs +101 -0
- package/src/cli/init.test.mjs +161 -0
- package/src/cli/init.ts +407 -62
- package/src/cli/kit-metadata-security.test.mjs +443 -0
- package/src/cli/kit.ts +50 -12
- package/src/cli/pull-work-provider.ts +377 -3
- package/src/cli/sidecar-pure-helpers.test.mjs +64 -0
- package/src/cli/skill-drift-check.ts +196 -0
- package/src/cli/telemetry-doctor.test.mjs +53 -0
- package/src/cli/telemetry-doctor.ts +50 -7
- package/src/cli/validate-hook-influence.ts +37 -6
- package/src/cli/workflow-sidecar.ts +1150 -151
- package/src/cli.ts +5 -0
- package/src/flow-kit/validate.ts +277 -38
- package/src/index.ts +19 -0
- package/src/lib/console-connect-options.ts +261 -0
- package/src/lib/console-telemetry-validate.ts +88 -0
- package/src/lib/flow-resolver.ts +153 -10
- package/src/lib/fs.ts +160 -0
- package/src/lib/local-artifact-root.ts +129 -3
- package/src/runtime-adapters.ts +113 -33
- package/src/tools/build-universal-bundles.ts +36 -2
- package/src/tools/codex-agent-routing.ts +48 -0
- package/src/tools/generate-context-map.ts +1 -0
- package/src/tools/validate-source-tree.ts +26 -1
|
@@ -154,7 +154,14 @@ mkdir -p "$audit_dir/sessions"
|
|
|
154
154
|
printf '{"session_id":"session-1"}\n' > "$audit_dir/sessions/one.session"
|
|
155
155
|
if printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"echo AKIA1234567890ABCDEF && rm -rf /tmp/example"}}' \
|
|
156
156
|
| TELEMETRY_GOVERNANCE=true TELEMETRY_DATA_DIR="$audit_dir" TELEMETRY_SESSION_DIR="$audit_dir/sessions" bash "$ROOT/scripts/hooks/governance-audit.sh" preToolUse dev >"$TMPDIR_EVAL/governance.out" 2>"$TMPDIR_EVAL/governance.err"; then
|
|
157
|
-
|
|
157
|
+
for _audit_wait in $(seq 1 50); do
|
|
158
|
+
if [[ -s "$audit_dir/audit.jsonl" ]] \
|
|
159
|
+
&& grep -q '"event_type":"governance.secret_detected"' "$audit_dir/audit.jsonl" \
|
|
160
|
+
&& grep -q '"event_type":"governance.destructive_operation"' "$audit_dir/audit.jsonl"; then
|
|
161
|
+
break
|
|
162
|
+
fi
|
|
163
|
+
sleep 0.1
|
|
164
|
+
done
|
|
158
165
|
if [[ -s "$audit_dir/audit.jsonl" ]] \
|
|
159
166
|
&& grep -q '"event_type":"governance.secret_detected"' "$audit_dir/audit.jsonl" \
|
|
160
167
|
&& grep -q '"event_type":"governance.destructive_operation"' "$audit_dir/audit.jsonl"; then
|
|
@@ -31,6 +31,30 @@ else
|
|
|
31
31
|
_fail "hook influence behavioral cases failed validation: $(cat /tmp/flow-agents-hook-influence.out /tmp/flow-agents-hook-influence.err)"
|
|
32
32
|
fi
|
|
33
33
|
|
|
34
|
+
TMP_HOOK_INFLUENCE="$(mktemp -d)"
|
|
35
|
+
mkdir -p "$TMP_HOOK_INFLUENCE/source/kits/release-evidence" "$TMP_HOOK_INFLUENCE/dest"
|
|
36
|
+
cat > "$TMP_HOOK_INFLUENCE/source/kits/catalog.json" <<'JSON'
|
|
37
|
+
{"schema_version":"1.0","kits":[{"id":"release-evidence","name":"Release Evidence Kit","path":"kits/release-evidence","description":"Builder-less fixture"}]}
|
|
38
|
+
JSON
|
|
39
|
+
cat > "$TMP_HOOK_INFLUENCE/source/kits/release-evidence/kit.json" <<'JSON'
|
|
40
|
+
{"schema_version":"1.0","id":"release-evidence","name":"Release Evidence Kit","flows":[{"id":"release-evidence.review","path":"flows/review.flow.json"}]}
|
|
41
|
+
JSON
|
|
42
|
+
node - "$CASES" "$TMP_HOOK_INFLUENCE/cases-without-builder.json" <<'NODE'
|
|
43
|
+
const fs = require("node:fs");
|
|
44
|
+
const input = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
45
|
+
input.cases = input.cases.filter((item) => !/^(kit:builder:)?dev-builder-/.test(String(item.id || "")));
|
|
46
|
+
fs.writeFileSync(process.argv[3], JSON.stringify(input, null, 2) + "\n");
|
|
47
|
+
NODE
|
|
48
|
+
|
|
49
|
+
if FLOW_AGENTS_HOOK_INFLUENCE_SOURCE_ROOT="$TMP_HOOK_INFLUENCE/source" \
|
|
50
|
+
FLOW_AGENTS_HOOK_INFLUENCE_DEST="$TMP_HOOK_INFLUENCE/dest" \
|
|
51
|
+
flow_agents_node "$VALIDATOR" "$TMP_HOOK_INFLUENCE/cases-without-builder.json" > /tmp/flow-agents-hook-influence-builderless.out 2> /tmp/flow-agents-hook-influence-builderless.err; then
|
|
52
|
+
_pass "hook influence validator drops Builder-required cases when Builder is absent from catalog"
|
|
53
|
+
else
|
|
54
|
+
_fail "hook influence validator still required Builder cases for a Builder-less catalog: $(cat /tmp/flow-agents-hook-influence-builderless.out /tmp/flow-agents-hook-influence-builderless.err)"
|
|
55
|
+
fi
|
|
56
|
+
rm -rf "$TMP_HOOK_INFLUENCE"
|
|
57
|
+
|
|
34
58
|
if rg -q '"tier": "adapter"' "$CASES" \
|
|
35
59
|
&& rg -q '"tier": "live-acceptance"' "$CASES" \
|
|
36
60
|
&& rg -q '"tier": "installed-command"' "$CASES" \
|
|
@@ -59,7 +83,7 @@ else
|
|
|
59
83
|
_fail "hook influence cases miss a required #62 Builder Kit loop category"
|
|
60
84
|
fi
|
|
61
85
|
|
|
62
|
-
rm -f /tmp/flow-agents-hook-influence.out /tmp/flow-agents-hook-influence.err
|
|
86
|
+
rm -f /tmp/flow-agents-hook-influence.out /tmp/flow-agents-hook-influence.err /tmp/flow-agents-hook-influence-builderless.out /tmp/flow-agents-hook-influence-builderless.err
|
|
63
87
|
|
|
64
88
|
if [[ "$errors" -eq 0 ]]; then
|
|
65
89
|
echo "Hook influence case integration passed."
|
|
@@ -58,8 +58,14 @@ cat > "$SEEDED_DEST/.claude/settings.json" << 'JSON'
|
|
|
58
58
|
{
|
|
59
59
|
"permissions": {
|
|
60
60
|
"allow": ["Bash(usertool:*)"],
|
|
61
|
+
"defaultMode": "ask",
|
|
61
62
|
"customPermission": true
|
|
62
63
|
},
|
|
64
|
+
"statusLine": {
|
|
65
|
+
"type": "command",
|
|
66
|
+
"command": "echo user-statusline"
|
|
67
|
+
},
|
|
68
|
+
"skipDangerousModePermissionPrompt": false,
|
|
63
69
|
"myUserKey": "preserved-value",
|
|
64
70
|
"hooks": {
|
|
65
71
|
"Stop": [
|
|
@@ -78,7 +84,8 @@ cat > "$SEEDED_DEST/.claude/settings.json" << 'JSON'
|
|
|
78
84
|
JSON
|
|
79
85
|
|
|
80
86
|
# Run install
|
|
81
|
-
|
|
87
|
+
SEEDED_INSTALL_OUT="$TMPDIR_EVAL/seeded-claude-install.out"
|
|
88
|
+
(cd "$ROOT_DIR/dist/claude-code" && bash install.sh "$SEEDED_DEST" >"$SEEDED_INSTALL_OUT" 2>&1)
|
|
82
89
|
|
|
83
90
|
# Assert: FA hooks present
|
|
84
91
|
if node - "$SEEDED_DEST/.claude/settings.json" << 'NODE'
|
|
@@ -135,15 +142,39 @@ const fs = require("node:fs");
|
|
|
135
142
|
const s = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
136
143
|
const p = s.permissions || {};
|
|
137
144
|
if (p.customPermission !== true) throw new Error("user permissions.customPermission was clobbered: " + JSON.stringify(p));
|
|
145
|
+
if (p.defaultMode !== "ask") throw new Error("user permissions.defaultMode conflict was not preserved: " + JSON.stringify(p));
|
|
138
146
|
if (!JSON.stringify(p.allow || []).includes("usertool")) throw new Error("user permissions.allow entry not preserved by union: " + JSON.stringify(p.allow));
|
|
139
147
|
console.log("ok");
|
|
140
148
|
NODE
|
|
141
149
|
then
|
|
142
|
-
_pass "seeded: user custom permissions preserved (deep-merge union,
|
|
150
|
+
_pass "seeded: user custom permissions preserved (deep-merge union, scalar conflicts preserved)"
|
|
143
151
|
else
|
|
144
152
|
_fail "seeded: user custom permissions were clobbered"
|
|
145
153
|
fi
|
|
146
154
|
|
|
155
|
+
# Assert: user-owned scalar/object settings are preserved and surfaced as conflicts.
|
|
156
|
+
if node - "$SEEDED_DEST/.claude/settings.json" << 'NODE'
|
|
157
|
+
const fs = require("node:fs");
|
|
158
|
+
const s = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
159
|
+
if (s.statusLine?.command !== "echo user-statusline") throw new Error("statusLine conflict was not preserved: " + JSON.stringify(s.statusLine));
|
|
160
|
+
if (s.skipDangerousModePermissionPrompt !== false) throw new Error("skipDangerousModePermissionPrompt conflict was not preserved: " + JSON.stringify(s.skipDangerousModePermissionPrompt));
|
|
161
|
+
console.log("ok");
|
|
162
|
+
NODE
|
|
163
|
+
then
|
|
164
|
+
_pass "seeded: user-owned statusLine and skipDangerousModePermissionPrompt preserved"
|
|
165
|
+
else
|
|
166
|
+
_fail "seeded: user-owned scalar/object settings were clobbered"
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
if rg -q "install-merge: conflict: preserving existing setting 'statusLine'" "$SEEDED_INSTALL_OUT" \
|
|
170
|
+
&& rg -q "install-merge: conflict: preserving existing setting 'permissions.defaultMode'" "$SEEDED_INSTALL_OUT" \
|
|
171
|
+
&& rg -q "install-merge: conflict: preserving existing setting 'skipDangerousModePermissionPrompt'" "$SEEDED_INSTALL_OUT"; then
|
|
172
|
+
_pass "seeded: install reports preserved setting conflicts to the user"
|
|
173
|
+
else
|
|
174
|
+
_fail "seeded: install did not report expected setting conflicts"
|
|
175
|
+
sed -n '1,120p' "$SEEDED_INSTALL_OUT"
|
|
176
|
+
fi
|
|
177
|
+
|
|
147
178
|
echo ""
|
|
148
179
|
|
|
149
180
|
# ─── Scenario 2: Version-stamped first install ───────────────────────────────
|
|
@@ -403,6 +434,36 @@ else
|
|
|
403
434
|
_fail "--global: agents were not synced into global destination"
|
|
404
435
|
fi
|
|
405
436
|
|
|
437
|
+
# Regression guard (#439): --global must also write a per-skill-file sha256 content-hash
|
|
438
|
+
# manifest, a sibling of install.json, so `flow-agents skill-drift-check` and the SessionStart
|
|
439
|
+
# advisory have a baseline to classify installed skill files against.
|
|
440
|
+
if node - "$GLOBAL_SETTINGS_DIR/.flow-agents/skills-manifest.json" << 'NODE'
|
|
441
|
+
const fs = require("node:fs");
|
|
442
|
+
const manifest = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
443
|
+
if (!manifest.files || typeof manifest.files !== "object" || Object.keys(manifest.files).length === 0) throw new Error("skills-manifest.json files is empty: " + JSON.stringify(manifest.files));
|
|
444
|
+
if (!manifest.generatedAt) throw new Error("skills-manifest.json missing generatedAt");
|
|
445
|
+
if (manifest.runtime !== "claude-code") throw new Error("skills-manifest.json wrong runtime: " + manifest.runtime);
|
|
446
|
+
console.log("ok: " + Object.keys(manifest.files).length + " files");
|
|
447
|
+
NODE
|
|
448
|
+
then
|
|
449
|
+
_pass "--global: skills-manifest.json written with non-empty files after install"
|
|
450
|
+
else
|
|
451
|
+
_fail "--global: skills-manifest.json missing, empty, or invalid after install"
|
|
452
|
+
fi
|
|
453
|
+
|
|
454
|
+
# Re-run init --global: the manifest must regenerate (fresh generatedAt) without disturbing any
|
|
455
|
+
# of the settings-merge, skill-sync, and agent-sync assertions already proven above in this scenario.
|
|
456
|
+
FIRST_MANIFEST_GENERATED_AT=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$GLOBAL_SETTINGS_DIR/.flow-agents/skills-manifest.json','utf8')).generatedAt)" 2>/dev/null || echo "")
|
|
457
|
+
FLOW_AGENTS_USER_CLAUDE_SETTINGS="$GLOBAL_SETTINGS_DIR/settings.json" \
|
|
458
|
+
node "$ROOT_DIR/build/src/cli.js" init --runtime claude-code --global --yes >/dev/null 2>&1 || true
|
|
459
|
+
SECOND_MANIFEST_GENERATED_AT=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$GLOBAL_SETTINGS_DIR/.flow-agents/skills-manifest.json','utf8')).generatedAt)" 2>/dev/null || echo "")
|
|
460
|
+
|
|
461
|
+
if [[ -n "$FIRST_MANIFEST_GENERATED_AT" && -n "$SECOND_MANIFEST_GENERATED_AT" && "$FIRST_MANIFEST_GENERATED_AT" != "$SECOND_MANIFEST_GENERATED_AT" ]]; then
|
|
462
|
+
_pass "--global: re-running init regenerates skills-manifest.json (generatedAt changed)"
|
|
463
|
+
else
|
|
464
|
+
_fail "--global: skills-manifest.json generatedAt did not change on re-run (first=$FIRST_MANIFEST_GENERATED_AT second=$SECOND_MANIFEST_GENERATED_AT)"
|
|
465
|
+
fi
|
|
466
|
+
|
|
406
467
|
echo ""
|
|
407
468
|
|
|
408
469
|
# ─── Scenario 6: Manual proof (user-visible) ─────────────────────────────────
|
|
@@ -1055,6 +1116,12 @@ echo "--- CH4: codex-home preserves user config, profiles, hooks, local kit stat
|
|
|
1055
1116
|
CH4_DEST="$TMPDIR_EVAL/codex-home-ch4"
|
|
1056
1117
|
mkdir -p "$CH4_DEST/kits/local/repositories/user-kit" "$CH4_DEST/sk""ills/user-owned-skill" "$CH4_DEST/ag""ents"
|
|
1057
1118
|
|
|
1119
|
+
CH4_GENERIC_DIRS=(agent-cards build context docs evals integrations packaging powers prompts schemas scripts kits)
|
|
1120
|
+
for CH4_DIR in "${CH4_GENERIC_DIRS[@]}"; do
|
|
1121
|
+
mkdir -p "$CH4_DEST/$CH4_DIR"
|
|
1122
|
+
printf 'user-owned-%s\n' "$CH4_DIR" > "$CH4_DEST/$CH4_DIR/user-owned.txt"
|
|
1123
|
+
done
|
|
1124
|
+
|
|
1058
1125
|
cat > "$CH4_DEST/config.toml" << 'EOF_CFG'
|
|
1059
1126
|
model = "user-model"
|
|
1060
1127
|
EOF_CFG
|
|
@@ -1181,6 +1248,17 @@ else
|
|
|
1181
1248
|
_fail "CH4: installed scripts/kit.js could not run with installed build bundle"
|
|
1182
1249
|
fi
|
|
1183
1250
|
|
|
1251
|
+
CODEX_REAL_HOME="$TMPDIR_EVAL/fake-real-codex" bash "$ROOT_DIR/scripts/install-codex-home.sh" "$CH4_DEST" >/dev/null 2>&1
|
|
1252
|
+
CH4_GENERIC_PRESERVED=1
|
|
1253
|
+
for CH4_DIR in "${CH4_GENERIC_DIRS[@]}"; do
|
|
1254
|
+
[[ "$(cat "$CH4_DEST/$CH4_DIR/user-owned.txt" 2>/dev/null)" == "user-owned-$CH4_DIR" ]] || CH4_GENERIC_PRESERVED=0
|
|
1255
|
+
done
|
|
1256
|
+
if [[ "$CH4_GENERIC_PRESERVED" -eq 1 && -f "$CH4_DEST/.flow-agents/codex-install-manifest.json" ]]; then
|
|
1257
|
+
_pass "CH4: unrelated files in every shared bundle directory survive install and reinstall"
|
|
1258
|
+
else
|
|
1259
|
+
_fail "CH4: install or reinstall removed unrelated files from a shared bundle directory"
|
|
1260
|
+
fi
|
|
1261
|
+
|
|
1184
1262
|
echo ""
|
|
1185
1263
|
|
|
1186
1264
|
# ─── codex-home: CH5: destination symlink containment ───────────────────────
|
|
@@ -1201,6 +1279,153 @@ for CH5_REL in scripts kits sk""ills hooks.json; do
|
|
|
1201
1279
|
fi
|
|
1202
1280
|
done
|
|
1203
1281
|
|
|
1282
|
+
echo ""
|
|
1283
|
+
echo "--- CH6: codex-home rejects canonical source/destination overlap before writes ---"
|
|
1284
|
+
CH6_ROOT="$TMPDIR_EVAL/ch6-fixture-root"
|
|
1285
|
+
CH6_FAKE_BIN="$TMPDIR_EVAL/ch6-bin"
|
|
1286
|
+
CH_FIXTURE_SCRIPTS="scr""ipts"
|
|
1287
|
+
CH_FIXTURE_SKILLS="sk""ills"
|
|
1288
|
+
CH_FIXTURE_AGENTS="ag""ents"
|
|
1289
|
+
mkdir -p "$CH6_ROOT/$CH_FIXTURE_SCRIPTS" "$CH6_ROOT/dist/codex/$CH_FIXTURE_SCRIPTS" "$CH6_FAKE_BIN"
|
|
1290
|
+
cp "$ROOT_DIR/scripts/install-codex-home.sh" "$ROOT_DIR/scripts/install-owned-files.js" "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/"
|
|
1291
|
+
printf '#!/usr/bin/env bash\nexit 0\n' > "$CH6_FAKE_BIN/npm"
|
|
1292
|
+
chmod +x "$CH6_FAKE_BIN/npm"
|
|
1293
|
+
printf 'fixture\n' > "$CH6_ROOT/dist/codex/$CH_FIXTURE_SCRIPTS/fixture.txt"
|
|
1294
|
+
mkdir -p "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_SKILLS/legacy-collision" "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_AGENTS"
|
|
1295
|
+
printf 'flow-agents-new-skill\n' > "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_SKILLS/legacy-collision/SKILL.md"
|
|
1296
|
+
printf 'name = "flow-agents-new-agent"\n' > "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_AGENTS/legacy-collision.toml"
|
|
1297
|
+
|
|
1298
|
+
for CH6_CASE in equal descendant ancestor; do
|
|
1299
|
+
case "$CH6_CASE" in
|
|
1300
|
+
equal) CH6_DEST="$CH6_ROOT" ;;
|
|
1301
|
+
descendant) CH6_DEST="$CH6_ROOT/nested-destination" ;;
|
|
1302
|
+
ancestor) CH6_DEST="$TMPDIR_EVAL" ;;
|
|
1303
|
+
esac
|
|
1304
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch6-home" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH6_DEST" >"$TMPDIR_EVAL/ch6-$CH6_CASE.out" 2>&1; then
|
|
1305
|
+
_fail "CH6: installer accepted $CH6_CASE source/destination overlap"
|
|
1306
|
+
elif grep -q 'overlaps' "$TMPDIR_EVAL/ch6-$CH6_CASE.out" && [[ -f "$CH6_ROOT/dist/codex/$CH_FIXTURE_SCRIPTS/fixture.txt" ]]; then
|
|
1307
|
+
_pass "CH6: installer rejects $CH6_CASE canonical overlap before source mutation"
|
|
1308
|
+
else
|
|
1309
|
+
_fail "CH6: installer did not safely reject $CH6_CASE overlap"
|
|
1310
|
+
fi
|
|
1311
|
+
done
|
|
1312
|
+
|
|
1313
|
+
CH6_AUTH_DEST="$TMPDIR_EVAL/ch6-auth-dest"
|
|
1314
|
+
CH6_AUTH_ALIAS="$TMPDIR_EVAL/ch6-auth-alias"
|
|
1315
|
+
mkdir -p "$CH6_AUTH_DEST"
|
|
1316
|
+
printf '{"user":"preserved"}\n' > "$CH6_AUTH_DEST/auth.json"
|
|
1317
|
+
ln -s "$CH6_AUTH_DEST" "$CH6_AUTH_ALIAS"
|
|
1318
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch6-home" CODEX_REAL_HOME="$CH6_AUTH_ALIAS" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH6_AUTH_DEST" >"$TMPDIR_EVAL/ch6-auth.out" 2>&1 \
|
|
1319
|
+
&& grep -q '"user":"preserved"' "$CH6_AUTH_DEST/auth.json"; then
|
|
1320
|
+
_pass "CH6: canonical auth-home alias is treated as self-copy and preserved"
|
|
1321
|
+
else
|
|
1322
|
+
_fail "CH6: canonical auth-home alias caused a self-copy failure or mutation"
|
|
1323
|
+
fi
|
|
1324
|
+
|
|
1325
|
+
echo ""
|
|
1326
|
+
echo "--- CH7: pre-manifest ownership bootstrap is evidence-bound ---"
|
|
1327
|
+
seed_ch7_legacy() {
|
|
1328
|
+
local destination="$1"
|
|
1329
|
+
local installed_at="$2"
|
|
1330
|
+
mkdir -p "$destination/.flow-agents" "$destination/$CH_FIXTURE_SCRIPTS"
|
|
1331
|
+
printf 'old-release\n' > "$destination/$CH_FIXTURE_SCRIPTS/fixture.txt"
|
|
1332
|
+
cat > "$destination/.flow-agents/install.json" <<JSON
|
|
1333
|
+
{"version":"3.2.0","installedAt":"$installed_at","runtime":"codex"}
|
|
1334
|
+
JSON
|
|
1335
|
+
cat > "$destination/hooks.json" <<'JSON'
|
|
1336
|
+
{"hooks":{"Stop":[{"hooks":[{"statusMessage":"Recording Flow Agents telemetry"}]}]}}
|
|
1337
|
+
JSON
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
CH7_LEGACY="$TMPDIR_EVAL/ch7-genuine-legacy"
|
|
1341
|
+
seed_ch7_legacy "$CH7_LEGACY" "2099-01-01T00:00:00.000Z"
|
|
1342
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_LEGACY" >"$TMPDIR_EVAL/ch7-legacy.out" 2>&1 \
|
|
1343
|
+
&& [[ "$(cat "$CH7_LEGACY/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "fixture" ]] \
|
|
1344
|
+
&& [[ -f "$CH7_LEGACY/.flow-agents/codex-install-manifest.json" ]]; then
|
|
1345
|
+
_pass "CH7: corroborated pre-manifest legacy owned file upgrades and gains a manifest"
|
|
1346
|
+
else
|
|
1347
|
+
_fail "CH7: genuine pre-manifest legacy install did not upgrade"
|
|
1348
|
+
fi
|
|
1349
|
+
|
|
1350
|
+
CH7_ARBITRARY="$TMPDIR_EVAL/ch7-arbitrary-collision"
|
|
1351
|
+
mkdir -p "$CH7_ARBITRARY/$CH_FIXTURE_SCRIPTS"
|
|
1352
|
+
printf 'user-arbitrary\n' > "$CH7_ARBITRARY/$CH_FIXTURE_SCRIPTS/fixture.txt"
|
|
1353
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_ARBITRARY" >"$TMPDIR_EVAL/ch7-arbitrary.out" 2>&1; then
|
|
1354
|
+
_fail "CH7: first install overwrote an arbitrary unowned collision"
|
|
1355
|
+
elif [[ "$(cat "$CH7_ARBITRARY/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "user-arbitrary" ]] && grep -q 'unowned or ambiguous' "$TMPDIR_EVAL/ch7-arbitrary.out"; then
|
|
1356
|
+
_pass "CH7: arbitrary unowned collision fails before mutation and survives"
|
|
1357
|
+
else
|
|
1358
|
+
_fail "CH7: arbitrary collision was not preserved cleanly"
|
|
1359
|
+
fi
|
|
1360
|
+
|
|
1361
|
+
CH7_MODIFIED="$TMPDIR_EVAL/ch7-modified-ambiguous"
|
|
1362
|
+
seed_ch7_legacy "$CH7_MODIFIED" "2000-01-01T00:00:00.000Z"
|
|
1363
|
+
printf 'user-modified-after-install\n' > "$CH7_MODIFIED/$CH_FIXTURE_SCRIPTS/fixture.txt"
|
|
1364
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_MODIFIED" >"$TMPDIR_EVAL/ch7-modified.out" 2>&1; then
|
|
1365
|
+
_fail "CH7: ambiguous post-install modification was overwritten"
|
|
1366
|
+
elif [[ "$(cat "$CH7_MODIFIED/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "user-modified-after-install" ]] && grep -q 'unowned or ambiguous' "$TMPDIR_EVAL/ch7-modified.out"; then
|
|
1367
|
+
_pass "CH7: modified ambiguous legacy-path file fails before mutation and survives"
|
|
1368
|
+
else
|
|
1369
|
+
_fail "CH7: modified ambiguous file was not preserved cleanly"
|
|
1370
|
+
fi
|
|
1371
|
+
|
|
1372
|
+
CH7_EXTENSIBLE="$TMPDIR_EVAL/ch7-user-extensible"
|
|
1373
|
+
seed_ch7_legacy "$CH7_EXTENSIBLE" "2099-01-01T00:00:00.000Z"
|
|
1374
|
+
mkdir -p "$CH7_EXTENSIBLE/$CH_FIXTURE_SKILLS/legacy-collision" "$CH7_EXTENSIBLE/$CH_FIXTURE_AGENTS"
|
|
1375
|
+
printf 'older-user-skill\n' > "$CH7_EXTENSIBLE/$CH_FIXTURE_SKILLS/legacy-collision/SKILL.md"
|
|
1376
|
+
printf 'name = "older-user-agent"\n' > "$CH7_EXTENSIBLE/$CH_FIXTURE_AGENTS/legacy-collision.toml"
|
|
1377
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_EXTENSIBLE" >"$TMPDIR_EVAL/ch7-extensible.out" 2>&1; then
|
|
1378
|
+
_fail "CH7: legacy inference claimed a pre-existing user skill or agent"
|
|
1379
|
+
elif [[ "$(cat "$CH7_EXTENSIBLE/$CH_FIXTURE_SKILLS/legacy-collision/SKILL.md")" == "older-user-skill" ]] \
|
|
1380
|
+
&& grep -q 'older-user-agent' "$CH7_EXTENSIBLE/$CH_FIXTURE_AGENTS/legacy-collision.toml" \
|
|
1381
|
+
&& grep -q 'unowned or ambiguous' "$TMPDIR_EVAL/ch7-extensible.out"; then
|
|
1382
|
+
_pass "CH7: older user skill and agent collisions remain ambiguous and preserved"
|
|
1383
|
+
else
|
|
1384
|
+
_fail "CH7: user-extensible skill or agent collision was not preserved cleanly"
|
|
1385
|
+
fi
|
|
1386
|
+
|
|
1387
|
+
CH7_RETRY="$TMPDIR_EVAL/ch7-interrupted-retry"
|
|
1388
|
+
mkdir -p "$CH7_RETRY/.flow-agents" "$CH7_RETRY/$CH_FIXTURE_SCRIPTS"
|
|
1389
|
+
printf 'fixture\n' > "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/fixture.txt"
|
|
1390
|
+
printf 'stale-old\n' > "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/stale.txt"
|
|
1391
|
+
CH7_OLD_HASH="$(printf 'old-release\n' | shasum -a 256 | awk '{print $1}')"
|
|
1392
|
+
CH7_STALE_HASH="$(shasum -a 256 "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/stale.txt" | awk '{print $1}')"
|
|
1393
|
+
cat > "$CH7_RETRY/.flow-agents/codex-install-manifest.json" <<JSON
|
|
1394
|
+
{"schema_version":"1.0","files":[{"path":"$CH_FIXTURE_SCRIPTS/fixture.txt","sha256":"$CH7_OLD_HASH"},{"path":"$CH_FIXTURE_SCRIPTS/stale.txt","sha256":"$CH7_STALE_HASH"}]}
|
|
1395
|
+
JSON
|
|
1396
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_RETRY" >"$TMPDIR_EVAL/ch7-retry.out" 2>&1 \
|
|
1397
|
+
&& [[ "$(cat "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "fixture" ]] \
|
|
1398
|
+
&& [[ ! -e "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/stale.txt" ]]; then
|
|
1399
|
+
_pass "CH7: interrupted apply retries when current content already matches incoming and removes stale owned files"
|
|
1400
|
+
else
|
|
1401
|
+
_fail "CH7: interrupted apply state was not retry-safe"
|
|
1402
|
+
fi
|
|
1403
|
+
|
|
1404
|
+
CH7_THIRD="$TMPDIR_EVAL/ch7-interrupted-third-content"
|
|
1405
|
+
mkdir -p "$CH7_THIRD/.flow-agents" "$CH7_THIRD/$CH_FIXTURE_SCRIPTS"
|
|
1406
|
+
printf 'third-party-change\n' > "$CH7_THIRD/$CH_FIXTURE_SCRIPTS/fixture.txt"
|
|
1407
|
+
cat > "$CH7_THIRD/.flow-agents/codex-install-manifest.json" <<JSON
|
|
1408
|
+
{"schema_version":"1.0","files":[{"path":"$CH_FIXTURE_SCRIPTS/fixture.txt","sha256":"$CH7_OLD_HASH"}]}
|
|
1409
|
+
JSON
|
|
1410
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_THIRD" >"$TMPDIR_EVAL/ch7-third.out" 2>&1; then
|
|
1411
|
+
_fail "CH7: retry safety accepted arbitrary third content"
|
|
1412
|
+
elif [[ "$(cat "$CH7_THIRD/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "third-party-change" ]] && grep -q 'modified Flow Agents file' "$TMPDIR_EVAL/ch7-third.out"; then
|
|
1413
|
+
_pass "CH7: retry safety still rejects and preserves arbitrary third content"
|
|
1414
|
+
else
|
|
1415
|
+
_fail "CH7: arbitrary third content was not rejected cleanly"
|
|
1416
|
+
fi
|
|
1417
|
+
|
|
1418
|
+
CH7_FRESH="$TMPDIR_EVAL/ch7-fresh"
|
|
1419
|
+
mkdir -p "$CH7_FRESH/$CH_FIXTURE_SCRIPTS"
|
|
1420
|
+
printf 'user-unrelated\n' > "$CH7_FRESH/$CH_FIXTURE_SCRIPTS/user-owned.txt"
|
|
1421
|
+
if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_FRESH" >"$TMPDIR_EVAL/ch7-fresh.out" 2>&1 \
|
|
1422
|
+
&& [[ "$(cat "$CH7_FRESH/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "fixture" ]] \
|
|
1423
|
+
&& [[ "$(cat "$CH7_FRESH/$CH_FIXTURE_SCRIPTS/user-owned.txt")" == "user-unrelated" ]]; then
|
|
1424
|
+
_pass "CH7: safe first install writes owned files and preserves unrelated files"
|
|
1425
|
+
else
|
|
1426
|
+
_fail "CH7: safe first install or unrelated-file preservation regressed"
|
|
1427
|
+
fi
|
|
1428
|
+
|
|
1204
1429
|
echo ""
|
|
1205
1430
|
|
|
1206
1431
|
# ─── opencode --global: OG1: seed user key → install --global → key survives + $schema + stamp ─
|
|
@@ -201,17 +201,17 @@ fi
|
|
|
201
201
|
|
|
202
202
|
# ===================================================================
|
|
203
203
|
echo ""
|
|
204
|
-
echo "=== 8. Trust axis:
|
|
204
|
+
echo "=== 8. Trust axis: built-in kits are unverified without runtime privilege ==="
|
|
205
205
|
# ===================================================================
|
|
206
206
|
|
|
207
207
|
for kit_name in builder knowledge; do
|
|
208
208
|
out="$TMP_DIR/trust-${kit_name}.out"
|
|
209
209
|
run_inspect "$ROOT/kits/$kit_name" "$out" || true
|
|
210
210
|
trust=$(node -e "const d=require('fs').readFileSync('$out','utf8'); console.log(JSON.parse(d).trust)" 2>/dev/null)
|
|
211
|
-
if [[ "$trust" == "
|
|
212
|
-
pass "$kit_name kit trust:
|
|
211
|
+
if [[ "$trust" == "unverified" ]]; then
|
|
212
|
+
pass "$kit_name kit trust: unverified (official catalog metadata grants no runtime privilege)"
|
|
213
213
|
else
|
|
214
|
-
fail "$kit_name kit trust: expected
|
|
214
|
+
fail "$kit_name kit trust: expected unverified, got '$trust'"
|
|
215
215
|
cat "$out"
|
|
216
216
|
fi
|
|
217
217
|
done
|
|
@@ -226,7 +226,7 @@ for fixture in k0-flows-only k1-agent-extension k2-with-evals third-party-extens
|
|
|
226
226
|
run_inspect "$ROOT/evals/fixtures/kit-conformance-levels/$fixture" "$out" || true
|
|
227
227
|
trust=$(node -e "const d=require('fs').readFileSync('$out','utf8'); console.log(JSON.parse(d).trust)" 2>/dev/null)
|
|
228
228
|
if [[ "$trust" == "unverified" ]]; then
|
|
229
|
-
pass "$fixture fixture trust: unverified
|
|
229
|
+
pass "$fixture fixture trust: unverified"
|
|
230
230
|
else
|
|
231
231
|
fail "$fixture fixture trust: expected unverified, got '$trust'"
|
|
232
232
|
cat "$out"
|
|
@@ -244,7 +244,7 @@ if node -e "
|
|
|
244
244
|
const d = require('fs').readFileSync('$out', 'utf8');
|
|
245
245
|
const r = JSON.parse(d);
|
|
246
246
|
if (!('trust' in r)) throw new Error('missing key: trust');
|
|
247
|
-
const valid = ['
|
|
247
|
+
const valid = ['verified', 'unverified'];
|
|
248
248
|
if (!valid.includes(r.trust)) throw new Error('trust must be one of: ' + valid.join(', ') + '; got: ' + r.trust);
|
|
249
249
|
" 2>/dev/null; then
|
|
250
250
|
pass "inspect JSON output includes trust field with valid value"
|