@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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "exemption-usage-review"
|
|
3
|
+
description: "Periodic audit of standing delivery/DECLARED no-agent-delivery exemptions (ADR 0022 §3): lists every current exemption's scope, reason, approver, and age since declared_at, flags entries overdue for owner re-confirmation against a configurable staleness threshold, and walks the file's git history for a supplementary commit-level trail. Use when periodically reviewing which no-agent-delivery exemptions are still standing and whether any need re-confirmation."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exemption Usage Review
|
|
7
|
+
|
|
8
|
+
Read `delivery/DECLARED`, list every standing exemption with its age, and flag which ones
|
|
9
|
+
are overdue for owner re-confirmation — **process visibility, not enforcement** (ADR 0022
|
|
10
|
+
§3). This skill never changes `delivery/DECLARED` and never changes
|
|
11
|
+
`scripts/ci/trust-reconcile.js`'s reconciliation/exit-code behavior.
|
|
12
|
+
|
|
13
|
+
## Contract
|
|
14
|
+
|
|
15
|
+
- Read-only against `delivery/DECLARED` and its git history — no write, no mutation, no
|
|
16
|
+
append, no delete, anywhere in this repo.
|
|
17
|
+
- Never gates anything: this is a **skill**, not a flow. It has no `expects[]` claim to
|
|
18
|
+
evaluate and attaches no evidence. There is no pass/fail verdict — only a report.
|
|
19
|
+
- Never influences `scripts/ci/trust-reconcile.js`'s reconciliation decision or exit code.
|
|
20
|
+
The reconciler is unaware this skill exists, exactly as it is unaware of the rest of this
|
|
21
|
+
kit (ADR 0022 §3, "uninstalling `veritas-governance` must never weaken enforcement").
|
|
22
|
+
- Does not reimplement `scripts/ci/trust-reconcile.js`'s `matchesScope` /
|
|
23
|
+
`matchesScopeCondition` / `parseDeclaredMarker` functions. The review lists **every**
|
|
24
|
+
standing entry unconditionally — it has no "does this scope match the current change"
|
|
25
|
+
question to answer (that is the reconciler's job, evaluated per-change at CI time). This
|
|
26
|
+
skill answers a different question — "what exemptions exist at all, and how old are they" —
|
|
27
|
+
so it needs only a much simpler parse-and-age routine, not the reconciler's scope-matching
|
|
28
|
+
engine. See `review-exemptions.mjs`'s header comment for the same note in code.
|
|
29
|
+
- No `.kontourai/flow-agents/<slug>/` session artifact contract applies here: this skill
|
|
30
|
+
produces a standalone report (stdout, human-readable or `--json`), not a workflow sidecar
|
|
31
|
+
artifact. State this plainly rather than inventing an artifact contract this tool does not
|
|
32
|
+
need.
|
|
33
|
+
|
|
34
|
+
## What this review does and does not verify
|
|
35
|
+
|
|
36
|
+
**Does verify:**
|
|
37
|
+
- Every entry currently present in the live `delivery/DECLARED` file is listed with its
|
|
38
|
+
`scope`, `reason`, `approved_by`, `declared_at`, a computed `age_days` (now, or `--as-of`,
|
|
39
|
+
minus `declared_at`), and a `stale` boolean (`age_days > --stale-days`, default 90).
|
|
40
|
+
- The `git log --follow -- delivery/DECLARED` commit history for the file — optionally
|
|
41
|
+
bounded to a `--window-days` review window — is walked and reported as a supplementary
|
|
42
|
+
commit-level trail (sha, author, date, subject).
|
|
43
|
+
|
|
44
|
+
**Does not verify:**
|
|
45
|
+
- Whether any `approved_by` value names a real, authenticated human approver.
|
|
46
|
+
`approved_by` is free text on `delivery/DECLARED` itself (see this kit's own
|
|
47
|
+
`docs/README.md`, "Human-approval evidence: what is and is not enforced") — this tool
|
|
48
|
+
reports what the field says, it does not authenticate it.
|
|
49
|
+
- Whether any entry's `scope` (`ref:`/`commit:`/`author:`/`branch-prefix:`, or a
|
|
50
|
+
compound-AND combination) currently matches any particular change. That is
|
|
51
|
+
`scripts/ci/trust-reconcile.js`'s job at reconciliation time — a "does this exemption
|
|
52
|
+
apply to THIS change" question this review never asks. This review lists every entry
|
|
53
|
+
regardless of whether it currently matches anything.
|
|
54
|
+
- A full point-in-time reconstruction and diff of every historical version of
|
|
55
|
+
`delivery/DECLARED` (e.g. "entry X was removed then silently re-added with a different
|
|
56
|
+
reason"). `history_commits` gives the commit-level trail a human reviewer can inspect
|
|
57
|
+
further with `git show <sha>:delivery/DECLARED`; this tool does not do that per-commit
|
|
58
|
+
content diffing itself.
|
|
59
|
+
- Anything about whether the exemption is still *needed* — that is an owner judgment call
|
|
60
|
+
this review surfaces evidence for, not a decision it makes.
|
|
61
|
+
|
|
62
|
+
## Inputs
|
|
63
|
+
|
|
64
|
+
- `delivery/DECLARED` (default; override via `--declared-path <path>` for a fixture or a
|
|
65
|
+
different repo layout).
|
|
66
|
+
- `--repo-root <path>` (default: current working directory) — the git repository whose
|
|
67
|
+
history is walked.
|
|
68
|
+
- `--stale-days <n>` (default: `90`) — the configurable age threshold. Entries with
|
|
69
|
+
`age_days > stale-days` are flagged `stale: true`.
|
|
70
|
+
- `--window-days <n>` (optional; default: full history) — bounds the `git log --follow`
|
|
71
|
+
history walk to commits within the last `<n>` days of `--as-of`. Does not affect which
|
|
72
|
+
*current* entries are listed — the live file's entries are always listed in full; this
|
|
73
|
+
only bounds the supplementary history trail.
|
|
74
|
+
- `--as-of <ISO8601>` (default: `new Date().toISOString()`, i.e. wall-clock now) —
|
|
75
|
+
deterministic override for "now", so a scheduled/periodic invocation or an eval is not
|
|
76
|
+
wall-clock-flaky. Mirrors this repo's `TRUST_RECONCILE_SHA`/`_REF`/`_ACTOR` override
|
|
77
|
+
convention in `scripts/ci/trust-reconcile.js`.
|
|
78
|
+
- `--json` (optional) — emit a machine-readable JSON report instead of the human-readable
|
|
79
|
+
table.
|
|
80
|
+
|
|
81
|
+
## How to run the review
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Human-readable report against this repo's real delivery/DECLARED, default 90-day threshold.
|
|
85
|
+
node kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs
|
|
86
|
+
|
|
87
|
+
# Machine-readable, with an explicit deterministic "now" and a tighter threshold.
|
|
88
|
+
node kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs \
|
|
89
|
+
--as-of 2026-07-05T00:00:00Z --stale-days 30 --json
|
|
90
|
+
|
|
91
|
+
# Bound the supplementary history walk to the last 180 days.
|
|
92
|
+
node kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs \
|
|
93
|
+
--window-days 180
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Exit code: `0` on a clean run — even when one or more entries are flagged `stale`. Staleness
|
|
97
|
+
is informational output for a human owner to act on, never a script failure condition. Exit
|
|
98
|
+
`2` on bad arguments; exit `3` when `delivery/DECLARED` is missing or not valid JSON (nothing
|
|
99
|
+
to review — a tool-usage failure, not a staleness finding).
|
|
100
|
+
|
|
101
|
+
## Output shape
|
|
102
|
+
|
|
103
|
+
Each standing-exemption row: `{scope, reason, approved_by, declared_at, age_days, stale}`.
|
|
104
|
+
`age_days`/`stale` are `null` (never silently coerced to `true`/`false`) when `declared_at`
|
|
105
|
+
is missing or unparsable — an honest "unknown", not a guessed verdict.
|
|
106
|
+
|
|
107
|
+
The history section separately reports `{sha, author, date, subject}` per commit found by
|
|
108
|
+
`git log --follow -- delivery/DECLARED` in the (optionally windowed) range. A git failure
|
|
109
|
+
(no repository, no history, shallow clone) degrades to an empty history list plus a
|
|
110
|
+
diagnostic note — never a crash and never a fabricated commit.
|
|
111
|
+
|
|
112
|
+
## What happens with a stale entry
|
|
113
|
+
|
|
114
|
+
A `stale: true` entry means: this exemption has been standing longer than the configured
|
|
115
|
+
threshold without a recorded re-confirmation. This review does not renew, revoke, or modify
|
|
116
|
+
the entry itself — it surfaces the finding for an owner to act on: re-confirm the exemption
|
|
117
|
+
is still needed (e.g. re-run the kit's exemption-issuance flow to record a fresh
|
|
118
|
+
`declared_at` with the same or updated `reason`/`approved_by`), or remove it from
|
|
119
|
+
`delivery/DECLARED` by direct, CODEOWNERS-reviewed edit. Both of those actions are outside
|
|
120
|
+
this skill's scope by design — this skill only reports.
|
|
121
|
+
|
|
122
|
+
## Accepted gap: nothing schedules this review
|
|
123
|
+
|
|
124
|
+
ADR 0022 §3 asks for the review tool to exist, not for automated scheduling. This skill has
|
|
125
|
+
no CI job, cron trigger, or scheduled invocation wired to it — an operator must run it
|
|
126
|
+
periodically themselves (see "How to run the review" above). This is an accepted,
|
|
127
|
+
explicitly-named scope boundary, not a silent gap: building a scheduling/CI-trigger surface
|
|
128
|
+
was not requested and is not part of this slice.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// review-exemptions.mjs — Veritas Governance Kit exemption-usage-review helper (ADR 0022 §3).
|
|
3
|
+
//
|
|
4
|
+
// PURPOSE. A periodic audit tool that lists every standing `delivery/DECLARED` exemption
|
|
5
|
+
// (scope, reason, approver, age since declared_at) and flags stale/overdue entries against a
|
|
6
|
+
// configurable threshold, for owner re-confirmation. This is PROCESS VISIBILITY, not
|
|
7
|
+
// enforcement: it is read-only, writes nothing outside its own stdout/report output, and its
|
|
8
|
+
// own findings never feed back into `scripts/ci/trust-reconcile.js`'s exit code or into
|
|
9
|
+
// `delivery/DECLARED` itself. See ADR 0022 §3: "a periodic audit skill/flow that walks
|
|
10
|
+
// delivery/DECLARED history (git log --follow -- delivery/DECLARED) merged in a review window
|
|
11
|
+
// and surfaces every standing exemption (scope, reason, approver, age) for owner
|
|
12
|
+
// re-confirmation — process visibility, not enforcement."
|
|
13
|
+
//
|
|
14
|
+
// WHAT THIS DOES VERIFY:
|
|
15
|
+
// - Every entry currently present in the live `delivery/DECLARED` JSON array/object is
|
|
16
|
+
// listed with its `scope`, `reason`, `approved_by`, `declared_at`, computed `age_days`,
|
|
17
|
+
// and a `stale` boolean (age_days > --stale-days).
|
|
18
|
+
// - The `git log --follow -- delivery/DECLARED` commit history for the file (within
|
|
19
|
+
// --window-days when given, else full history) is walked and reported as
|
|
20
|
+
// `history_commits` (sha, author, date, subject) — this is a supplementary "how did this
|
|
21
|
+
// file change over time" view, separate from the "what's standing today" listing.
|
|
22
|
+
//
|
|
23
|
+
// WHAT THIS DOES NOT VERIFY (state plainly, per this kit's honesty convention):
|
|
24
|
+
// - It does NOT verify that any `approved_by` value corresponds to a real, authenticated
|
|
25
|
+
// human approver — that field is free text in `delivery/DECLARED` itself (see
|
|
26
|
+
// docs/README.md "Human-approval evidence: what is and is not enforced"); this tool only
|
|
27
|
+
// reports what the field says, never authenticates it.
|
|
28
|
+
// - It does NOT re-evaluate whether a scope's `ref:`/`commit:`/`author:`/`branch-prefix:`
|
|
29
|
+
// condition currently matches any particular change — that is
|
|
30
|
+
// `scripts/ci/trust-reconcile.js`'s `matchesScope`/`matchesScopeCondition` job (a
|
|
31
|
+
// "does this exemption apply to THIS change" question). This tool answers a different
|
|
32
|
+
// question — "what exemptions are standing at all, and how old are they" — for every
|
|
33
|
+
// entry, regardless of whether any given entry's scope currently matches anything.
|
|
34
|
+
// - It does NOT reconstruct a full point-in-time list of entries that existed at each
|
|
35
|
+
// historical commit and diff them against each other (e.g. it does not detect "entry X
|
|
36
|
+
// was removed then silently re-added with a different reason") — `history_commits` gives
|
|
37
|
+
// the commit-level trail (who changed the file, when) for a human reviewer to inspect
|
|
38
|
+
// with `git show <sha>:delivery/DECLARED` themselves; this tool does not do that
|
|
39
|
+
// per-commit content diffing itself.
|
|
40
|
+
// - It does NOT mutate `delivery/DECLARED`, does not attach evidence, does not run a Flow
|
|
41
|
+
// gate, and has no exit-code-driven pass/fail: this script's own process exit code is 0
|
|
42
|
+
// on any clean parse, regardless of how many entries are flagged stale — staleness is
|
|
43
|
+
// informational output, not a script failure condition.
|
|
44
|
+
//
|
|
45
|
+
// NO-FORK NOTE: this script intentionally does NOT reuse trust-reconcile.js's
|
|
46
|
+
// `matchesScope`/`matchesScopeCondition`/`parseDeclaredMarker` functions. The review lists ALL
|
|
47
|
+
// entries unconditionally (it has no "does this scope match the current context" question to
|
|
48
|
+
// answer), so it needs only a much simpler "parse the JSON array, compute age" routine, not
|
|
49
|
+
// the reconciler's scope-matching engine. This is a deliberate scope difference, not a missed
|
|
50
|
+
// reuse opportunity — see SKILL.md.
|
|
51
|
+
//
|
|
52
|
+
// Usage:
|
|
53
|
+
// node review-exemptions.mjs [--declared-path <path>] [--repo-root <path>]
|
|
54
|
+
// [--stale-days <n>] [--window-days <n>] [--as-of <ISO8601>] [--json]
|
|
55
|
+
//
|
|
56
|
+
// Exit: 0 on a clean run (parse succeeded, report printed) — even when entries are flagged
|
|
57
|
+
// stale. Exit 2 on bad args. Exit 3 when delivery/DECLARED is missing or not valid JSON
|
|
58
|
+
// (nothing to review — this is a tool-usage failure, not a staleness finding).
|
|
59
|
+
|
|
60
|
+
import { readFileSync } from "node:fs";
|
|
61
|
+
import { spawnSync } from "node:child_process";
|
|
62
|
+
import path from "node:path";
|
|
63
|
+
|
|
64
|
+
const DEFAULT_STALE_DAYS = 90;
|
|
65
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
66
|
+
|
|
67
|
+
function parseArgs(argv) {
|
|
68
|
+
const out = {
|
|
69
|
+
declaredPath: undefined,
|
|
70
|
+
repoRoot: process.cwd(),
|
|
71
|
+
staleDays: DEFAULT_STALE_DAYS,
|
|
72
|
+
windowDays: undefined,
|
|
73
|
+
asOf: undefined,
|
|
74
|
+
json: false,
|
|
75
|
+
};
|
|
76
|
+
for (let i = 0; i < argv.length; i++) {
|
|
77
|
+
const a = argv[i];
|
|
78
|
+
if (a === "--declared-path") out.declaredPath = argv[++i];
|
|
79
|
+
else if (a === "--repo-root") out.repoRoot = argv[++i];
|
|
80
|
+
else if (a === "--stale-days") out.staleDays = Number(argv[++i]);
|
|
81
|
+
else if (a === "--window-days") out.windowDays = Number(argv[++i]);
|
|
82
|
+
else if (a === "--as-of") out.asOf = argv[++i];
|
|
83
|
+
else if (a === "--json") out.json = true;
|
|
84
|
+
else if (a === "--help" || a === "-h") out.help = true;
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function usage() {
|
|
90
|
+
return "usage: review-exemptions.mjs [--declared-path <path>] [--repo-root <path>] "
|
|
91
|
+
+ "[--stale-days <n>] [--window-days <n>] [--as-of <ISO8601>] [--json]\n";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Read and parse the live delivery/DECLARED file into a flat array of raw entries.
|
|
96
|
+
* Mirrors trust-reconcile.js's tolerant single-object-or-array shape (a single {scope,...}
|
|
97
|
+
* object OR a JSON array of such objects) WITHOUT reusing its parseDeclaredMarker() function
|
|
98
|
+
* (see NO-FORK NOTE above) — this parse is deliberately simpler: no well-formed/malformed
|
|
99
|
+
* bucketing, no scope-matching, just "read the array, keep what looks like an entry object".
|
|
100
|
+
*/
|
|
101
|
+
export function readDeclaredEntries(declaredPath) {
|
|
102
|
+
const raw = readFileSync(declaredPath, "utf8");
|
|
103
|
+
const parsed = JSON.parse(raw);
|
|
104
|
+
const entries = Array.isArray(parsed) ? parsed : [parsed];
|
|
105
|
+
return entries.filter((e) => e && typeof e === "object");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Age in whole days between an ISO8601 `declared_at` and an ISO8601 `asOfIso` "now". */
|
|
109
|
+
export function ageDays(declaredAtIso, asOfIso) {
|
|
110
|
+
const declared = new Date(declaredAtIso).getTime();
|
|
111
|
+
const asOf = new Date(asOfIso).getTime();
|
|
112
|
+
if (Number.isNaN(declared) || Number.isNaN(asOf)) return null;
|
|
113
|
+
return Math.floor((asOf - declared) / MS_PER_DAY);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Build the standing-exemption report rows: one row per delivery/DECLARED entry, with
|
|
118
|
+
* computed age_days and a stale boolean (age_days > staleDays). Entries with an unparsable
|
|
119
|
+
* declared_at get age_days: null, stale: null (never silently coerced to fresh or stale).
|
|
120
|
+
*/
|
|
121
|
+
export function buildReport(entries, { staleDays, asOfIso }) {
|
|
122
|
+
return entries.map((entry) => {
|
|
123
|
+
const declaredAt = typeof entry.declared_at === "string" ? entry.declared_at : null;
|
|
124
|
+
const age = declaredAt ? ageDays(declaredAt, asOfIso) : null;
|
|
125
|
+
return {
|
|
126
|
+
scope: typeof entry.scope === "string" ? entry.scope : null,
|
|
127
|
+
reason: typeof entry.reason === "string" ? entry.reason : null,
|
|
128
|
+
approved_by: typeof entry.approved_by === "string" ? entry.approved_by : null,
|
|
129
|
+
declared_at: declaredAt,
|
|
130
|
+
age_days: age,
|
|
131
|
+
stale: age === null ? null : age > staleDays,
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Walk `git log --follow -- <declaredRelPath>` history for delivery/DECLARED, optionally
|
|
138
|
+
* bounded to a review window (--window-days before asOfIso). Read-only (`git log`, no
|
|
139
|
+
* mutation). Never throws — a git failure (no repo, no history, shallow clone) degrades to
|
|
140
|
+
* an empty list plus a diagnostic note, never a crash.
|
|
141
|
+
*/
|
|
142
|
+
export function walkDeclaredHistory(repoRoot, declaredRelPath, { windowDays, asOfIso }) {
|
|
143
|
+
const args = ["log", "--follow", "--date=iso-strict", "--format=%H%x1f%an%x1f%ad%x1f%s"];
|
|
144
|
+
if (windowDays && Number.isFinite(windowDays) && windowDays > 0) {
|
|
145
|
+
const since = new Date(new Date(asOfIso).getTime() - windowDays * MS_PER_DAY).toISOString();
|
|
146
|
+
args.push(`--since=${since}`);
|
|
147
|
+
}
|
|
148
|
+
args.push("--", declaredRelPath);
|
|
149
|
+
try {
|
|
150
|
+
const res = spawnSync("git", args, { cwd: repoRoot, encoding: "utf8" });
|
|
151
|
+
if (!res || res.error || res.status !== 0) {
|
|
152
|
+
return { commits: [], diagnostic: "git log --follow unavailable or failed; history_commits is empty (no historical trail could be walked)" };
|
|
153
|
+
}
|
|
154
|
+
const lines = res.stdout.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
155
|
+
const commits = lines.map((line) => {
|
|
156
|
+
const [sha, author, date, subject] = line.split("\x1f");
|
|
157
|
+
return { sha, author, date, subject };
|
|
158
|
+
});
|
|
159
|
+
return { commits, diagnostic: null };
|
|
160
|
+
} catch (err) {
|
|
161
|
+
return { commits: [], diagnostic: `git log --follow threw: ${err && err.message ? err.message : String(err)}` };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function renderHuman(report, history, opts) {
|
|
166
|
+
const lines = [];
|
|
167
|
+
lines.push(`Exemption usage review — as-of ${opts.asOfIso}, stale threshold ${opts.staleDays} day(s)`);
|
|
168
|
+
lines.push(`PROCESS-ONLY: read-only report. Does not modify delivery/DECLARED or scripts/ci/trust-reconcile.js's behavior.`);
|
|
169
|
+
lines.push("");
|
|
170
|
+
lines.push(`Standing exemptions (${report.length}):`);
|
|
171
|
+
if (report.length === 0) lines.push(" (none)");
|
|
172
|
+
for (const row of report) {
|
|
173
|
+
const staleTag = row.stale === null ? "UNKNOWN-AGE" : row.stale ? "STALE — needs owner re-confirmation" : "fresh";
|
|
174
|
+
lines.push(` - scope: ${row.scope ?? "(missing)"}`);
|
|
175
|
+
lines.push(` reason: ${row.reason ?? "(missing)"}`);
|
|
176
|
+
lines.push(` approved_by: ${row.approved_by ?? "(missing)"}`);
|
|
177
|
+
lines.push(` declared_at: ${row.declared_at ?? "(missing)"} | age_days: ${row.age_days ?? "n/a"} | ${staleTag}`);
|
|
178
|
+
}
|
|
179
|
+
lines.push("");
|
|
180
|
+
lines.push(`History (git log --follow -- delivery/DECLARED)${opts.windowDays ? ` — last ${opts.windowDays} day(s)` : " — full history"}:`);
|
|
181
|
+
if (history.diagnostic) lines.push(` NOTE: ${history.diagnostic}`);
|
|
182
|
+
if (history.commits.length === 0 && !history.diagnostic) lines.push(" (no commits found)");
|
|
183
|
+
for (const c of history.commits) {
|
|
184
|
+
lines.push(` - ${c.sha.slice(0, 12)} ${c.date} ${c.author} — ${c.subject}`);
|
|
185
|
+
}
|
|
186
|
+
return lines.join("\n");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function main() {
|
|
190
|
+
const args = parseArgs(process.argv.slice(2));
|
|
191
|
+
if (args.help) {
|
|
192
|
+
process.stdout.write(usage());
|
|
193
|
+
return 0;
|
|
194
|
+
}
|
|
195
|
+
const repoRoot = path.resolve(args.repoRoot);
|
|
196
|
+
const declaredPath = args.declaredPath
|
|
197
|
+
? path.resolve(args.declaredPath)
|
|
198
|
+
: path.join(repoRoot, "delivery", "DECLARED");
|
|
199
|
+
const staleDays = Number.isFinite(args.staleDays) ? args.staleDays : DEFAULT_STALE_DAYS;
|
|
200
|
+
const asOfIso = args.asOf || new Date().toISOString();
|
|
201
|
+
|
|
202
|
+
let entries;
|
|
203
|
+
try {
|
|
204
|
+
entries = readDeclaredEntries(declaredPath);
|
|
205
|
+
} catch (err) {
|
|
206
|
+
process.stderr.write(`cannot read/parse delivery/DECLARED at ${declaredPath}: ${err && err.message ? err.message : String(err)}\n`);
|
|
207
|
+
return 3;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const report = buildReport(entries, { staleDays, asOfIso });
|
|
211
|
+
const declaredRelPath = path.relative(repoRoot, declaredPath) || "delivery/DECLARED";
|
|
212
|
+
const history = walkDeclaredHistory(repoRoot, declaredRelPath, { windowDays: args.windowDays, asOfIso });
|
|
213
|
+
|
|
214
|
+
if (args.json) {
|
|
215
|
+
process.stdout.write(`${JSON.stringify({
|
|
216
|
+
as_of: asOfIso,
|
|
217
|
+
stale_days: staleDays,
|
|
218
|
+
window_days: args.windowDays ?? null,
|
|
219
|
+
declared_path: declaredPath,
|
|
220
|
+
entries: report,
|
|
221
|
+
history_commits: history.commits,
|
|
222
|
+
history_diagnostic: history.diagnostic,
|
|
223
|
+
}, null, 2)}\n`);
|
|
224
|
+
} else {
|
|
225
|
+
process.stdout.write(`${renderHuman(report, history, { asOfIso, staleDays, windowDays: args.windowDays })}\n`);
|
|
226
|
+
}
|
|
227
|
+
return 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const isEntry = process.argv[1] && import.meta.url === `file://${process.argv[1]}`;
|
|
231
|
+
if (isEntry) process.exitCode = main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kontourai/flow-agents",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Flow Agents — a Kontour product that applies Flow and Veritas discipline as a portable process layer inside the agent tools you already use: Claude Code, Codex, Kiro, opencode, pi, and GitHub Actions — with framework adapters (AWS Strands preview) on the same policy-engine contract.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"typescript": "^6.0.3"
|
|
150
150
|
},
|
|
151
151
|
"dependencies": {
|
|
152
|
-
"@kontourai/flow": "^
|
|
152
|
+
"@kontourai/flow": "^3.0.0"
|
|
153
153
|
},
|
|
154
154
|
"optionalDependencies": {
|
|
155
155
|
"@kontourai/surface": "^2.0.0",
|
package/packaging/manifest.json
CHANGED
|
@@ -56,6 +56,13 @@
|
|
|
56
56
|
"excluded_agents": [
|
|
57
57
|
"dev"
|
|
58
58
|
],
|
|
59
|
+
"allowed_agent_models": [
|
|
60
|
+
"gpt-5.3-codex-spark",
|
|
61
|
+
"gpt-5.4-mini",
|
|
62
|
+
"gpt-5.5",
|
|
63
|
+
"gpt-5.6-sol",
|
|
64
|
+
"gpt-5.6-terra"
|
|
65
|
+
],
|
|
59
66
|
"profiles": {
|
|
60
67
|
"builder": {
|
|
61
68
|
"model": "gpt-5.5",
|
|
@@ -114,6 +121,28 @@
|
|
|
114
121
|
"agi-nova-beta-1m": "medium",
|
|
115
122
|
"default": "medium"
|
|
116
123
|
},
|
|
124
|
+
"codex_agent_map": {
|
|
125
|
+
"tool-planner": {
|
|
126
|
+
"model": "gpt-5.6-sol",
|
|
127
|
+
"reasoning_effort": "high"
|
|
128
|
+
},
|
|
129
|
+
"tool-worker": {
|
|
130
|
+
"model": "gpt-5.6-terra",
|
|
131
|
+
"reasoning_effort": "high"
|
|
132
|
+
},
|
|
133
|
+
"tool-code-reviewer": {
|
|
134
|
+
"model": "gpt-5.6-sol",
|
|
135
|
+
"reasoning_effort": "high"
|
|
136
|
+
},
|
|
137
|
+
"tool-security-reviewer": {
|
|
138
|
+
"model": "gpt-5.6-sol",
|
|
139
|
+
"reasoning_effort": "high"
|
|
140
|
+
},
|
|
141
|
+
"tool-verifier": {
|
|
142
|
+
"model": "gpt-5.6-sol",
|
|
143
|
+
"reasoning_effort": "high"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
117
146
|
"target_substitutions": {
|
|
118
147
|
"common": [],
|
|
119
148
|
"claude_code": [
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"properties": {
|
|
9
9
|
"$schema": { "type": "string" },
|
|
10
10
|
"schema_version": { "const": "1.0" },
|
|
11
|
+
"workspace": { "$ref": "#/$defs/workspace" },
|
|
11
12
|
"defaults": { "$ref": "#/$defs/backlog_settings" },
|
|
12
13
|
"projects": {
|
|
13
14
|
"type": "array",
|
|
@@ -22,6 +23,18 @@
|
|
|
22
23
|
{ "type": "object", "required": ["project"] }
|
|
23
24
|
]
|
|
24
25
|
},
|
|
26
|
+
"workspace": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"additionalProperties": false,
|
|
29
|
+
"required": ["repos"],
|
|
30
|
+
"properties": {
|
|
31
|
+
"repos": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": { "type": "string", "minLength": 1 },
|
|
34
|
+
"uniqueItems": true
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
25
38
|
"backlog_settings": {
|
|
26
39
|
"type": "object",
|
|
27
40
|
"additionalProperties": false,
|
|
@@ -59,6 +59,36 @@
|
|
|
59
59
|
},
|
|
60
60
|
"uniqueItems": true
|
|
61
61
|
},
|
|
62
|
+
"work_item_refs": {
|
|
63
|
+
"type": "array",
|
|
64
|
+
"items": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"minLength": 1
|
|
67
|
+
},
|
|
68
|
+
"minItems": 1,
|
|
69
|
+
"uniqueItems": true,
|
|
70
|
+
"description": "Provider-neutral work item references anchoring this workflow session."
|
|
71
|
+
},
|
|
72
|
+
"flow_run": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"additionalProperties": false,
|
|
75
|
+
"required": ["run_id", "definition_id", "definition_version", "status", "current_step", "run_ref", "open_gate_ids"],
|
|
76
|
+
"properties": {
|
|
77
|
+
"run_id": { "type": "string", "minLength": 1 },
|
|
78
|
+
"definition_id": { "type": "string", "minLength": 1 },
|
|
79
|
+
"definition_version": { "type": "string", "minLength": 1 },
|
|
80
|
+
"status": { "type": "string", "minLength": 1 },
|
|
81
|
+
"current_step": { "type": "string", "minLength": 1 },
|
|
82
|
+
"run_ref": { "type": "string", "minLength": 1 },
|
|
83
|
+
"open_gate_ids": {
|
|
84
|
+
"type": "array",
|
|
85
|
+
"items": { "type": "string", "minLength": 1 },
|
|
86
|
+
"uniqueItems": true
|
|
87
|
+
},
|
|
88
|
+
"route_back_attempt": { "type": "integer", "minimum": 1 },
|
|
89
|
+
"route_back_max_attempts": { "type": "integer", "minimum": 1 }
|
|
90
|
+
}
|
|
91
|
+
},
|
|
62
92
|
"next_action": {
|
|
63
93
|
"type": "object",
|
|
64
94
|
"additionalProperties": false,
|
|
@@ -78,6 +108,20 @@
|
|
|
78
108
|
},
|
|
79
109
|
"target_artifact": {
|
|
80
110
|
"type": "string"
|
|
111
|
+
},
|
|
112
|
+
"skills": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": { "type": "string", "minLength": 1 },
|
|
115
|
+
"uniqueItems": true
|
|
116
|
+
},
|
|
117
|
+
"operations": {
|
|
118
|
+
"type": "array",
|
|
119
|
+
"items": { "type": "string", "minLength": 1 },
|
|
120
|
+
"uniqueItems": true
|
|
121
|
+
},
|
|
122
|
+
"command": {
|
|
123
|
+
"type": "string",
|
|
124
|
+
"minLength": 1
|
|
81
125
|
}
|
|
82
126
|
}
|
|
83
127
|
}
|
package/scripts/README.md
CHANGED
|
@@ -69,9 +69,11 @@ renamed, or changes category, update the table and the validator together.
|
|
|
69
69
|
| `desktop-notify.sh` | local notification helper | `evals/integration/test_hook_category_behaviors.sh` | Optional local desktop notification helper. |
|
|
70
70
|
| `lib/actor-identity.js` | shared hook library | `evals/integration/test_actor_identity.sh` | Shared runtime-agnostic actor identity resolver (`resolveActor`) consumed by `workflow-steering.js` and `workflow-sidecar.js` to retire the shared `"local"` liveness-actor default (issue #287). |
|
|
71
71
|
| `lib/audit-transport.sh` | shared hook library | `evals/integration/test_hook_category_behaviors.sh`, `evals/integration/test_telemetry.sh` | Shared audit event transport functions. |
|
|
72
|
+
| `lib/codex-exit-code.js` | shared hook library | `evals/acceptance/prove-capture-teeth.sh` | Shared codex-only host-banner exit-code extraction (`extractExitCodeFromBanner`, `readExitCodeFromRollout`) — parses the `Process exited with code N` prose the codex CLI writes into a `function_call_output` payload or session rollout so `codex-hook-adapter.js` can inject a structured exit code before `evidence-capture.js` observes (issue #470). |
|
|
72
73
|
| `lib/config-protection-remedies.js` | shared hook library | `evals/integration/test_hook_category_behaviors.sh` | Sanctioned-remedy table for `config-protection.js` (WS8/ADR 0020 extraction). |
|
|
73
74
|
| `lib/current-pointer.js` | shared hook library | `evals/integration/test_current_json_per_actor.sh` | Shared per-actor "current" pointer reader/writer (`readCurrentPointer`, `writePerActorCurrent`) — the compat-shim fallback (per-actor `current/<actor>.json` first, legacy global `current.json` fallback) every actor-aware consumer routes through (issue #291). |
|
|
74
75
|
| `lib/hook-flags.js` | shared hook library | `evals/integration/test_hook_category_behaviors.sh` | Shared profile/disable flag parsing. |
|
|
76
|
+
| `lib/kit-catalog.js` | shared hook library | `evals/integration/test_workflow_steering_hook.sh` | Build-free kit catalog reader used by `workflow-steering.js` to load kit-declared workflow triggers while hooks remain fail-open and independent of compiled TypeScript output. |
|
|
75
77
|
| `lib/liveness-heartbeat.js` | shared hook library | `evals/integration/test_liveness_heartbeat.sh` | Shared tool-activity liveness heartbeat (`maybeEmitHeartbeat`); rides `postToolUse` across all four telemetry hook wrappers, throttled and fail-open (issue #288). |
|
|
76
78
|
| `lib/liveness-policy.js` | shared hook library | `evals/integration/test_workflow_sidecar_writer.sh`, `evals/integration/test_liveness_heartbeat.sh` | Shared liveness on/off predicate (`isLivenessEnabled`, default-on/opt-out) and TTL/heartbeat-throttle default resolution (issue #288). |
|
|
77
79
|
| `lib/liveness-read.js` | shared hook library | `evals/integration/test_session_resume_roundtrip.sh` | Shared liveness event reader + freshness check (`readLivenessEvents`, `freshHolders`); consumed by the reground hook and `workflow-sidecar liveness status`. |
|
|
@@ -79,6 +81,8 @@ renamed, or changes category, update the table and the validator together.
|
|
|
79
81
|
| `lib/local-artifact-paths.js` | shared hook library | `evals/integration/test_migrate_local_artifacts.sh`, `evals/integration/test_workflow_sidecar_writer.sh` | Shared `.kontourai/flow-agents` artifact-root helpers for CJS hooks. |
|
|
80
82
|
| `lib/patterns.sh` | shared hook library | `evals/integration/test_hook_category_behaviors.sh`, `evals/integration/test_telemetry.sh` | Shared shell pattern constants. |
|
|
81
83
|
| `lib/resolve-formatter.js` | shared hook library | `evals/integration/test_hook_category_behaviors.sh` | Shared formatter resolution helper. |
|
|
84
|
+
| `lib/runnable-command.js` | shared hook library | `evals/integration/test_goal_fit_hook.sh` | Shared runnable-command-text heuristic (`isRunnableCommandText`) consumed by `stop-goal-fit.js` and `workflow-sidecar.js` so record-time and Stop-time checks never drift (issue #412). |
|
|
85
|
+
| `lib/skill-drift.js` | shared hook library | `evals/integration/test_skill_drift_check.sh` | Shared installed-Claude-Code-skill manifest builder and drift classifier (`buildManifest`, `compareSkillDrift`) — the single choke point the `init --global` manifest writer, the `flow-agents skill-drift-check` CLI, and the SessionStart advisory all route through so they never disagree on drift classification (issue #439). |
|
|
82
86
|
|
|
83
87
|
## Telemetry
|
|
84
88
|
|
|
@@ -37,6 +37,11 @@ function trackedFiles() {
|
|
|
37
37
|
return output.split("\0").filter(Boolean);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
function untrackedFiles() {
|
|
41
|
+
const output = execFileSync("git", ["ls-files", "--others", "--exclude-standard", "-z"], { encoding: "utf8" });
|
|
42
|
+
return output.split("\0").filter(Boolean);
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
function isIgnoredPath(filePath) {
|
|
41
46
|
return filePath === SELF || ignoredPathPatterns.some((pattern) => pattern.test(filePath));
|
|
42
47
|
}
|
|
@@ -51,7 +56,9 @@ function lineNumberFor(content, index) {
|
|
|
51
56
|
|
|
52
57
|
const findings = [];
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
const allFiles = new Set([...trackedFiles(), ...untrackedFiles()]);
|
|
60
|
+
|
|
61
|
+
for (const filePath of allFiles) {
|
|
55
62
|
if (isWorkflowRuntimeArtifact(filePath)) {
|
|
56
63
|
findings.push({
|
|
57
64
|
filePath,
|