@kontourai/flow-agents 3.2.0 → 3.4.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/add-to-project.yml +15 -0
- package/.github/workflows/ci.yml +173 -0
- package/CHANGELOG.md +54 -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/assignment-provider.js +10 -1
- 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-artifact-cleanup-audit.js +418 -11
- package/build/src/cli/workflow-sidecar.d.ts +310 -1
- package/build/src/cli/workflow-sidecar.js +1914 -126
- 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 +54 -1
- package/build/src/lib/flow-resolver.js +112 -5
- 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 +30 -3
- package/context/contracts/artifact-contract.md +16 -2
- 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 +194 -22
- 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/coordination-guide.md +370 -0
- package/docs/decisions/agent-coordination.md +26 -9
- package/docs/decisions/embeddable-engine.md +152 -0
- package/docs/decisions/index.md +5 -3
- package/docs/decisions/trust-ledger-retention.md +88 -0
- package/docs/decisions/trust-reconcile.md +42 -9
- package/docs/decisions/workflow-enforcement.md +31 -9
- package/docs/fixture-ownership.md +6 -2
- package/docs/implementing-trust-reconciliation.md +129 -0
- package/docs/index.md +23 -9
- package/docs/integrations/flow-agents-console.md +275 -0
- package/docs/integrations/index.md +4 -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-artifact-lifecycle.md +38 -1
- package/docs/workflow-usage-guide.md +10 -0
- package/evals/acceptance/prove-capture-teeth.sh +132 -0
- package/evals/ci/antigaming-suite.sh +2 -0
- package/evals/ci/run-baseline.sh +78 -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/reconcile-preflight/disputed-critique-unsuperseded.json +48 -0
- package/evals/fixtures/reconcile-preflight/standalone-disputed-session-local.json +59 -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_checkpoint_signing.sh +10 -2
- package/evals/integration/test_ci_actor_identity.sh +221 -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 +389 -2
- package/evals/integration/test_pull_work_board.sh +200 -0
- package/evals/integration/test_pull_work_provider.sh +1 -1
- package/evals/integration/test_reconcile_preflight.sh +304 -0
- 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_takeover_protocol.sh +340 -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 +121 -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_verify_hold.sh +910 -0
- package/evals/integration/test_veritas_governance_kit.sh +257 -0
- package/evals/integration/test_workflow_artifact_cleanup_audit.sh +575 -3
- 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 +37 -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/continue-work/SKILL.md +2 -0
- package/kits/builder/skills/deliver/SKILL.md +115 -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 +33 -2
- package/kits/builder/skills/release-readiness/SKILL.md +12 -0
- package/kits/knowledge/kit.json +9 -0
- package/kits/veritas-governance/docs/README.md +113 -7
- package/kits/veritas-governance/fixtures/exemption/approved.trust-bundle.json +74 -0
- package/kits/veritas-governance/fixtures/exemption/not-approved.trust-bundle.json +74 -0
- package/kits/veritas-governance/fixtures/exemption-review/mixed-fresh-stale.DECLARED.json +14 -0
- package/kits/veritas-governance/flows/exemption-issuance.flow.json +35 -0
- package/kits/veritas-governance/kit.json +19 -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 +214 -253
- package/scripts/hooks/codex-hook-adapter.js +77 -2
- package/scripts/hooks/evidence-capture.js +38 -5
- package/scripts/hooks/lib/actor-identity.js +82 -0
- 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 +194 -22
- 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/lib/reconcile-shape.js +381 -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/assignment-provider.ts +12 -1
- 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 +72 -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-artifact-cleanup-audit.ts +483 -10
- package/src/cli/workflow-sidecar.ts +1980 -119
- 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 +117 -4
- 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 +29 -3
|
@@ -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.0",
|
|
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,
|