@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
|
@@ -46,6 +46,78 @@ console_telemetry_timeout_seconds() {
|
|
|
46
46
|
fi
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
# Derive a coarse, path-free project label for console attribution, most-stable-first so the SAME
|
|
50
|
+
# project resolves to the SAME label across developers and machines (folder names differ between
|
|
51
|
+
# clones and worktrees; the project manifest and git remote do not). Precedence:
|
|
52
|
+
# 1. FLOW_AGENTS_PROJECT — explicit operator override, always wins
|
|
53
|
+
# 2. nearest package.json name — walking up from cwd (monorepo-granular, committed => consistent)
|
|
54
|
+
# 3. git remote origin org/repo — repo-level identity, stable across clones
|
|
55
|
+
# 4. git toplevel dir basename — repo dir even from a worktree/subdir
|
|
56
|
+
# 5. cwd basename — last resort
|
|
57
|
+
# Path-free by construction (never the full local path). Cached per cwd under the telemetry data
|
|
58
|
+
# dir so the git/manifest reads run once per project, not per event; session_cleanup bounds the
|
|
59
|
+
# cache lifetime so a project rename (package.json name / git remote) self-heals within a day.
|
|
60
|
+
# Failure signals via empty output; the sole caller wraps the call as `$(...) || proj=""` so even if
|
|
61
|
+
# an internal command fails under `set -e`, telemetry is relayed unchanged (see
|
|
62
|
+
# console_telemetry_emit). Do not call this unwrapped from a `set -e` context.
|
|
63
|
+
console_project_label() {
|
|
64
|
+
local cwd="$1"
|
|
65
|
+
[[ -z "$cwd" || ! -d "$cwd" ]] && return 0
|
|
66
|
+
[[ -n "${FLOW_AGENTS_PROJECT:-}" ]] && { printf '%s' "$FLOW_AGENTS_PROJECT"; return 0; }
|
|
67
|
+
|
|
68
|
+
local cache="" key
|
|
69
|
+
if [[ -n "${TELEMETRY_SESSION_DIR:-}" && -d "${TELEMETRY_SESSION_DIR:-}" ]]; then
|
|
70
|
+
key=$(printf '%s' "$cwd" | cksum | cut -d' ' -f1)
|
|
71
|
+
cache="${TELEMETRY_SESSION_DIR%/}/project-label.${key}"
|
|
72
|
+
[[ -s "$cache" ]] && { cat "$cache"; return 0; }
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
local label="" dir name url top after path repo rest org
|
|
76
|
+
dir="$cwd"
|
|
77
|
+
while [[ -n "$dir" && "$dir" != "/" ]]; do
|
|
78
|
+
if [[ -f "$dir/package.json" ]]; then
|
|
79
|
+
name=$(jq -r '.name // empty' "$dir/package.json" 2>/dev/null) || name=""
|
|
80
|
+
[[ -n "$name" ]] && { label="$name"; break; }
|
|
81
|
+
fi
|
|
82
|
+
dir=$(dirname "$dir")
|
|
83
|
+
done
|
|
84
|
+
if [[ -z "$label" ]]; then
|
|
85
|
+
url=$(git -C "$cwd" config --get remote.origin.url 2>/dev/null) || url=""
|
|
86
|
+
if [[ -n "$url" ]]; then
|
|
87
|
+
# Reduce a git remote to a coarse, host-free org/repo. Strip scheme+host STRUCTURALLY (not by
|
|
88
|
+
# a dot-in-host heuristic) so a self-hosted or dot-less host, a port, or a user@ prefix can
|
|
89
|
+
# never leak into the label; a remote with no org tier (single path segment) falls through.
|
|
90
|
+
url="${url%/}"; url="${url%.git}"
|
|
91
|
+
path=""
|
|
92
|
+
if [[ "$url" == *"://"* ]]; then
|
|
93
|
+
# Only network VCS schemes carry an org/repo path; file:// and other local schemes fall through.
|
|
94
|
+
if [[ "$url" =~ ^(https?|ssh|git|ftps?):// ]]; then
|
|
95
|
+
after="${url#*://}" # [user@]host[:port]/org/repo
|
|
96
|
+
[[ "$after" == */* ]] && path="${after#*/}" # drop host[:port] (and any user@), keep path
|
|
97
|
+
fi
|
|
98
|
+
elif [[ "$url" == *:* && "${url%%:*}" != */* ]]; then
|
|
99
|
+
path="${url#*:}" # scp form [user@]host:org/repo
|
|
100
|
+
elif [[ "$url" != /* ]]; then
|
|
101
|
+
path="$url" # bare relative org/repo shorthand (not a local abs path)
|
|
102
|
+
fi
|
|
103
|
+
if [[ "$path" == */* ]]; then
|
|
104
|
+
repo="${path##*/}"; rest="${path%/*}"; org="${rest##*/}" # last two path segments
|
|
105
|
+
[[ -n "$org" && -n "$repo" ]] && label="$org/$repo"
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
if [[ -z "$label" ]]; then
|
|
110
|
+
top=$(git -C "$cwd" rev-parse --show-toplevel 2>/dev/null) || top=""
|
|
111
|
+
[[ -n "$top" ]] && label=$(basename "$top")
|
|
112
|
+
fi
|
|
113
|
+
[[ -z "$label" ]] && label=$(basename "$cwd")
|
|
114
|
+
|
|
115
|
+
if [[ -n "$cache" ]]; then
|
|
116
|
+
printf '%s' "$label" > "${cache}.tmp.$$" 2>/dev/null && mv "${cache}.tmp.$$" "$cache" 2>/dev/null
|
|
117
|
+
fi
|
|
118
|
+
printf '%s' "$label"
|
|
119
|
+
}
|
|
120
|
+
|
|
49
121
|
console_telemetry_emit() {
|
|
50
122
|
local event="$1"
|
|
51
123
|
local endpoint_url
|
|
@@ -53,6 +125,21 @@ console_telemetry_emit() {
|
|
|
53
125
|
[[ -z "$endpoint_url" ]] && return
|
|
54
126
|
console_telemetry_endpoint_allowed "$endpoint_url" || return
|
|
55
127
|
|
|
128
|
+
# Attribution: stamp a coarse, path-free project label (see console_project_label) before redaction
|
|
129
|
+
# so the console buckets by project consistently across developers. The full context.cwd is still
|
|
130
|
+
# redacted below — only the label leaves the machine. Every substitution is `|| var=""`-guarded so
|
|
131
|
+
# that even under `set -e` any failure (bad JSON, missing cwd, no git) relays the event unchanged.
|
|
132
|
+
local ev_cwd proj labeled_event
|
|
133
|
+
ev_cwd=$(printf '%s' "$event" | jq -r '.context.cwd // empty' 2>/dev/null) || ev_cwd=""
|
|
134
|
+
if [[ -n "$ev_cwd" ]]; then
|
|
135
|
+
proj=$(console_project_label "$ev_cwd" 2>/dev/null) || proj=""
|
|
136
|
+
if [[ -n "$proj" ]]; then
|
|
137
|
+
labeled_event=$(printf '%s' "$event" | jq -c --arg p "$proj" '
|
|
138
|
+
if ((.context.project // "") | length) == 0 then .context.project = $p else . end' 2>/dev/null) || labeled_event=""
|
|
139
|
+
[[ -n "$labeled_event" ]] && event="$labeled_event"
|
|
140
|
+
fi
|
|
141
|
+
fi
|
|
142
|
+
|
|
56
143
|
local processed_event
|
|
57
144
|
processed_event=$(redact_event "$event" "${CONSOLE_TELEMETRY_REDACT:-${TELEMETRY_CHANNEL_ANALYTICS_REDACT:-}}")
|
|
58
145
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# usage.sh — Session usage metric functions
|
|
3
3
|
|
|
4
|
+
# Module directory, resolved once at source time (cwd-independent).
|
|
5
|
+
USAGE_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
|
|
7
|
+
# Single-source pricing registry loader (local / remote / bundled).
|
|
8
|
+
source "${USAGE_LIB_DIR}/pricing.sh"
|
|
9
|
+
|
|
4
10
|
# Resolve model from agent-spec.json
|
|
5
11
|
usage_get_model() {
|
|
6
12
|
local agent_name="$1"
|
|
@@ -14,16 +20,211 @@ usage_get_model() {
|
|
|
14
20
|
echo "unknown"
|
|
15
21
|
}
|
|
16
22
|
|
|
23
|
+
# Given the JSON object produced by usage_parse_transcript (has a top-level
|
|
24
|
+
# `by_model[]` array), return the runtime-agnostic session model: the model
|
|
25
|
+
# with the most total tokens (input+output+cache_creation+cache_read). This
|
|
26
|
+
# lets any runtime that exposes a transcript (Claude Code, Codex, ...) resolve
|
|
27
|
+
# a real model name instead of the kiro-only ~/.kiro/agents lookup, which
|
|
28
|
+
# never matches non-kiro agent names (e.g. Claude Code's fixed "dev" hook
|
|
29
|
+
# arg) and falls through to "unknown". Returns empty string when $1 is
|
|
30
|
+
# null/empty or has no by_model entries, so the caller falls back to
|
|
31
|
+
# usage_get_model().
|
|
32
|
+
usage_model_from_transcript_usage() {
|
|
33
|
+
local transcript_usage="$1"
|
|
34
|
+
[[ -z "$transcript_usage" || "$transcript_usage" == "null" ]] && { echo ""; return; }
|
|
35
|
+
echo "$transcript_usage" | jq -r '
|
|
36
|
+
(.by_model // [])
|
|
37
|
+
| map({model, total: ((.input_tokens // 0) + (.output_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0))})
|
|
38
|
+
| sort_by([-.total, .model])
|
|
39
|
+
| .[0].model // empty
|
|
40
|
+
' 2>/dev/null
|
|
41
|
+
}
|
|
42
|
+
|
|
17
43
|
# Count tool invocations for a session
|
|
18
44
|
usage_count_tool_calls() {
|
|
19
45
|
local session_id="$1" jsonl_path="$2"
|
|
20
|
-
[[ ! -f "$jsonl_path" ]] && echo 0
|
|
21
|
-
grep -c
|
|
46
|
+
[[ ! -f "$jsonl_path" ]] && { echo 0; return; }
|
|
47
|
+
# grep -c prints "0" (not empty) on zero matches but still exits non-zero,
|
|
48
|
+
# so `grep -c ... || echo 0` double-emits "0\n0" here — that malformed
|
|
49
|
+
# value then breaks the caller's `jq --argjson tc "$tool_count"`, silently
|
|
50
|
+
# discarding the *entire* session.usage event whenever a session has no
|
|
51
|
+
# prior tool.invoke lines yet (a common, not-rare case). Capture the count
|
|
52
|
+
# first and only fall back when it's genuinely empty.
|
|
53
|
+
local count
|
|
54
|
+
count=$(grep -c "\"session_id\":\"${session_id}\".*\"event_type\":\"tool.invoke\"" "$jsonl_path" 2>/dev/null)
|
|
55
|
+
echo "${count:-0}"
|
|
22
56
|
}
|
|
23
57
|
|
|
24
58
|
# Count subagent delegations for a session
|
|
25
59
|
usage_count_delegations() {
|
|
26
60
|
local session_id="$1" jsonl_path="$2"
|
|
27
|
-
[[ ! -f "$jsonl_path" ]] && echo 0
|
|
28
|
-
grep -c
|
|
61
|
+
[[ ! -f "$jsonl_path" ]] && { echo 0; return; }
|
|
62
|
+
# See usage_count_tool_calls above for why this can't be `grep -c ... || echo 0`.
|
|
63
|
+
local count
|
|
64
|
+
count=$(grep -c "\"session_id\":\"${session_id}\".*\"event_type\":\"agent.delegate\"" "$jsonl_path" 2>/dev/null)
|
|
65
|
+
echo "${count:-0}"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Parse a runtime transcript (JSONL) into real per-model token + cost usage.
|
|
69
|
+
# Ground truth lives in each assistant message's `.message.usage` block:
|
|
70
|
+
# input_tokens (uncached), output_tokens, cache_creation_input_tokens,
|
|
71
|
+
# cache_read_input_tokens — plus `.message.model`.
|
|
72
|
+
# Cost is derived from the versioned pricing registry: cache writes bill at
|
|
73
|
+
# input*write_5m, cache reads at input*read. Cost uses the registry's
|
|
74
|
+
# current_version (override with arg $2) and the result stamps `pricing_version`
|
|
75
|
+
# so the console can reproduce or recompute it. Emits a compact JSON object:
|
|
76
|
+
# { by_model: [ {model, input_tokens, output_tokens,
|
|
77
|
+
# cache_creation_input_tokens, cache_read_input_tokens,
|
|
78
|
+
# estimated_cost_usd} ],
|
|
79
|
+
# input_tokens, output_tokens, cache_creation_input_tokens,
|
|
80
|
+
# cache_read_input_tokens, estimated_cost_usd, pricing_version }
|
|
81
|
+
# Tokens are source-of-truth and survive independently of pricing: if the
|
|
82
|
+
# pricing registry is unavailable (or an explicit version arg doesn't exist in
|
|
83
|
+
# it), by_model[]/input_tokens/output_tokens/etc. are still emitted — only
|
|
84
|
+
# estimated_cost_usd and pricing_version degrade to null (the console
|
|
85
|
+
# recomputes cost authoritatively from tokens). Prints nothing (non-zero) only
|
|
86
|
+
# when the transcript itself is missing/empty/unreadable or truly carries zero
|
|
87
|
+
# usage, so the caller can fall back to null usage. Never blocks agent work.
|
|
88
|
+
# Expected transcript usage path (Claude Code / Anthropic usage object). Bumped
|
|
89
|
+
# if the on-disk schema changes so drift is logged rather than silently zeroed.
|
|
90
|
+
USAGE_TRANSCRIPT_SCHEMA="message.usage.input_tokens"
|
|
91
|
+
|
|
92
|
+
# Append a one-line schema-drift warning (transcript carried usage data we could
|
|
93
|
+
# not parse). Goes to TELEMETRY_DRIFT_LOG if set, else stderr. Never fatal.
|
|
94
|
+
usage_log_drift() {
|
|
95
|
+
local transcript="$1"
|
|
96
|
+
local msg="[telemetry] pricing/usage drift: ${transcript} has usage data but expected path '${USAGE_TRANSCRIPT_SCHEMA}' parsed 0 tokens — transcript schema may have changed"
|
|
97
|
+
if [[ -n "${TELEMETRY_DRIFT_LOG:-}" ]]; then
|
|
98
|
+
echo "$msg" >> "${TELEMETRY_DRIFT_LOG}" 2>/dev/null || echo "$msg" >&2
|
|
99
|
+
else
|
|
100
|
+
echo "$msg" >&2
|
|
101
|
+
fi
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Opt-in persistent diagnostics for usage_parse_transcript's no-usage/degraded
|
|
105
|
+
# outcomes (gated by TELEMETRY_USAGE_DEBUG=1 so it never fires by default).
|
|
106
|
+
# Goes to TELEMETRY_DRIFT_LOG if set, else stderr. Never fatal, never blocks —
|
|
107
|
+
# purely so intermittent live "session.usage has null tokens" reports can be
|
|
108
|
+
# distinguished (empty transcript_path vs missing file vs no pricing registry
|
|
109
|
+
# vs a real zero-token parse) instead of being an unexplained black box.
|
|
110
|
+
usage_log_debug() {
|
|
111
|
+
[[ "${TELEMETRY_USAGE_DEBUG:-}" == "1" ]] || return 0
|
|
112
|
+
local reason="$1"
|
|
113
|
+
local msg="[telemetry] usage_parse_transcript: ${reason}"
|
|
114
|
+
if [[ -n "${TELEMETRY_DRIFT_LOG:-}" ]]; then
|
|
115
|
+
echo "$msg" >> "${TELEMETRY_DRIFT_LOG}" 2>/dev/null || echo "$msg" >&2
|
|
116
|
+
else
|
|
117
|
+
echo "$msg" >&2
|
|
118
|
+
fi
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
usage_parse_transcript() {
|
|
122
|
+
local transcript="$1" version="${2:-}"
|
|
123
|
+
if [[ -z "$transcript" ]]; then
|
|
124
|
+
usage_log_debug "no usage — reason: empty transcript_path"
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
if [[ ! -f "$transcript" ]]; then
|
|
128
|
+
usage_log_debug "no usage — reason: transcript file missing (${transcript})"
|
|
129
|
+
return 1
|
|
130
|
+
fi
|
|
131
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
132
|
+
usage_log_debug "no usage — reason: jq unavailable"
|
|
133
|
+
return 1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# Pricing registry is best-effort: when unavailable, tokens are still
|
|
137
|
+
# extracted below and only the cost fields degrade to null (defect #2 fix —
|
|
138
|
+
# previously this hard-returned 1 here, discarding token extraction
|
|
139
|
+
# entirely whenever pricing_registry() failed).
|
|
140
|
+
local registry has_registry
|
|
141
|
+
registry="$(pricing_registry 2>/dev/null)"
|
|
142
|
+
if [[ $? -eq 0 && -n "$registry" ]]; then
|
|
143
|
+
has_registry=true
|
|
144
|
+
else
|
|
145
|
+
has_registry=false
|
|
146
|
+
registry='null'
|
|
147
|
+
usage_log_debug "pricing registry unavailable (${transcript}) — extracting tokens without cost"
|
|
148
|
+
fi
|
|
149
|
+
# A non-empty registry can still be malformed (corrupt/truncated pricing.json,
|
|
150
|
+
# or a bad remote 200) — validate it parses before handing it to `jq -n
|
|
151
|
+
# --argjson`, which would otherwise abort the whole parse and discard tokens
|
|
152
|
+
# (the exact intermittent-null-tokens defect this function exists to fix).
|
|
153
|
+
if [[ "$has_registry" == true ]] && ! jq -e . >/dev/null 2>&1 <<<"$registry"; then
|
|
154
|
+
has_registry=false
|
|
155
|
+
registry='null'
|
|
156
|
+
usage_log_debug "pricing registry unparseable (${transcript}) — extracting tokens without cost"
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
local out
|
|
160
|
+
out="$(jq -n --argjson registry "$registry" --argjson has_registry "$has_registry" --arg version "$version" '
|
|
161
|
+
($has_registry and ($registry != null)) as $has_reg
|
|
162
|
+
| (if $has_reg then (if $version == "" then $registry.current_version else $version end) else null end) as $ver
|
|
163
|
+
| (if $has_reg and ($ver != null) then ($registry.versions[$ver]) else null end) as $p
|
|
164
|
+
| ($p != null) as $priced
|
|
165
|
+
| (if $priced then $p.cache_multipliers else null end) as $cm
|
|
166
|
+
| (reduce inputs as $l ({};
|
|
167
|
+
($l.message.usage) as $u
|
|
168
|
+
| if $u then
|
|
169
|
+
(($l.message.model) // "unknown") as $m
|
|
170
|
+
| .[$m].input = ((.[$m].input // 0) + (($u.input_tokens) // 0))
|
|
171
|
+
| .[$m].output = ((.[$m].output // 0) + (($u.output_tokens) // 0))
|
|
172
|
+
| .[$m].cache_creation = ((.[$m].cache_creation // 0) + (($u.cache_creation_input_tokens) // 0))
|
|
173
|
+
| .[$m].cache_read = ((.[$m].cache_read // 0) + (($u.cache_read_input_tokens) // 0))
|
|
174
|
+
else . end)) as $agg
|
|
175
|
+
| ($agg | to_entries
|
|
176
|
+
| map(
|
|
177
|
+
.key as $m | .value as $u
|
|
178
|
+
| (if $priced then (($p.models[$m]) // $p.default) else null end) as $rate
|
|
179
|
+
| (if $priced then (if ([$m] | inside($p.zero_cost_models)) then 0 else 1 end) else null end) as $billable
|
|
180
|
+
| {
|
|
181
|
+
model: $m,
|
|
182
|
+
input_tokens: ($u.input // 0),
|
|
183
|
+
output_tokens: ($u.output // 0),
|
|
184
|
+
cache_creation_input_tokens: ($u.cache_creation // 0),
|
|
185
|
+
cache_read_input_tokens: ($u.cache_read // 0),
|
|
186
|
+
estimated_cost_usd: (
|
|
187
|
+
if $priced then
|
|
188
|
+
$billable * (
|
|
189
|
+
($u.input // 0) * $rate.input
|
|
190
|
+
+ ($u.output // 0) * $rate.output
|
|
191
|
+
+ ($u.cache_creation // 0) * $rate.input * $cm.write_5m
|
|
192
|
+
+ ($u.cache_read // 0) * $rate.input * $cm.read
|
|
193
|
+
) / 1000000
|
|
194
|
+
else null end
|
|
195
|
+
)
|
|
196
|
+
})) as $by_model
|
|
197
|
+
| {
|
|
198
|
+
by_model: $by_model,
|
|
199
|
+
input_tokens: ([$by_model[].input_tokens] | add // 0),
|
|
200
|
+
output_tokens: ([$by_model[].output_tokens] | add // 0),
|
|
201
|
+
cache_creation_input_tokens: ([$by_model[].cache_creation_input_tokens] | add // 0),
|
|
202
|
+
cache_read_input_tokens: ([$by_model[].cache_read_input_tokens] | add // 0),
|
|
203
|
+
estimated_cost_usd: (if $priced then (([$by_model[].estimated_cost_usd] | add // 0) * 1000000 | round / 1000000) else null end),
|
|
204
|
+
pricing_version: (if $priced then $ver else null end)
|
|
205
|
+
}
|
|
206
|
+
' < "$transcript" 2>/dev/null)"
|
|
207
|
+
|
|
208
|
+
if [[ -z "$out" ]]; then
|
|
209
|
+
usage_log_debug "no usage — reason: jq parse failed (${transcript})"
|
|
210
|
+
return 1
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# Drift / emptiness check: if we parsed zero tokens but the transcript clearly
|
|
214
|
+
# contains usage data, the schema drifted — warn and fall back to null usage.
|
|
215
|
+
# This only discards tokens when there truly are none (total == 0); it never
|
|
216
|
+
# discards a non-zero token extraction, including the pricing-unavailable
|
|
217
|
+
# case above.
|
|
218
|
+
local total
|
|
219
|
+
total="$(printf '%s' "$out" | jq -r '((.input_tokens // 0) + (.output_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0))' 2>/dev/null)"
|
|
220
|
+
if [[ -z "$total" || "$total" == "0" ]]; then
|
|
221
|
+
if grep -q '"input_tokens"' "$transcript" 2>/dev/null; then
|
|
222
|
+
usage_log_drift "$transcript"
|
|
223
|
+
else
|
|
224
|
+
usage_log_debug "no usage — reason: parsed 0 tokens (no usage entries found in ${transcript})"
|
|
225
|
+
fi
|
|
226
|
+
return 1
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
printf '%s\n' "$out"
|
|
29
230
|
}
|
|
@@ -8,6 +8,12 @@ channel.analytics.redact=tool.input,tool.output,turn.prompt_text,delegation.targ
|
|
|
8
8
|
# The transport derives /api/telemetry/records from console_telemetry_url.
|
|
9
9
|
# console_telemetry_token=
|
|
10
10
|
# console_tenant_id=
|
|
11
|
+
# Kit-economics relay (#469): once console_telemetry_url/console_telemetry_endpoint_url
|
|
12
|
+
# resolves, the per-run kit-economics record relay defaults ON (opt-out, not silent-off).
|
|
13
|
+
# Set console_economics_relay=0 to opt out while keeping the telemetry mirror; or run
|
|
14
|
+
# install-console-config.sh --no-economics-relay to write this at install time.
|
|
15
|
+
# console_economics_relay=0
|
|
16
|
+
# console_economics_endpoint_url=
|
|
11
17
|
# Live pricing registry source. If unset, derived from console_telemetry_url as
|
|
12
18
|
# <console>/api/telemetry/pricing so bash/Python/TS runtimes read one live
|
|
13
19
|
# source; lib/pricing.sh caches it and falls back to bundled pricing.json.
|
|
@@ -318,6 +318,18 @@ add_stop_data_and_emit_usage() {
|
|
|
318
318
|
transcript_usage=$(usage_parse_transcript "$transcript_path")
|
|
319
319
|
[[ -z "$transcript_usage" ]] && transcript_usage='null'
|
|
320
320
|
|
|
321
|
+
# Prefer the transcript-derived model (runtime-agnostic — works for any
|
|
322
|
+
# runtime that exposes a transcript) over the kiro-only ~/.kiro/agents
|
|
323
|
+
# lookup above, which never resolves for non-kiro agent names (e.g.
|
|
324
|
+
# Claude Code's fixed "dev" hook arg) and falls through to "unknown".
|
|
325
|
+
# Falls back to usage_get_model's kiro result when no transcript usage
|
|
326
|
+
# is available (kiro-cli path is unchanged: transcript_usage stays null).
|
|
327
|
+
if [[ "$transcript_usage" != "null" ]]; then
|
|
328
|
+
local transcript_model
|
|
329
|
+
transcript_model=$(usage_model_from_transcript_usage "$transcript_usage")
|
|
330
|
+
[[ -n "$transcript_model" ]] && model="$transcript_model"
|
|
331
|
+
fi
|
|
332
|
+
|
|
321
333
|
local usage_event
|
|
322
334
|
usage_event=$(echo "$event" | jq -c \
|
|
323
335
|
--arg m "$model" \
|
|
@@ -340,6 +352,42 @@ add_stop_data_and_emit_usage() {
|
|
|
340
352
|
})
|
|
341
353
|
}')
|
|
342
354
|
transport_emit "$usage_event"
|
|
355
|
+
|
|
356
|
+
# Per-run kit-economics record (#349, console ADR 0003). Best-effort + DETACHED so it can never
|
|
357
|
+
# alter existing telemetry timing or fail the stop hook: assemble one kontour.console.economics
|
|
358
|
+
# fact from this session.usage event + the run's review sidecars, write it local-first, then
|
|
359
|
+
# opt-in relay it. Resolve the sidecar paths from the run cwd's active-session pointer; the
|
|
360
|
+
# emitter defaults every field cleanly when a sidecar is absent.
|
|
361
|
+
local econ_script="${TELEMETRY_DIR}/economics-record.sh"
|
|
362
|
+
if [[ -f "$econ_script" ]]; then
|
|
363
|
+
local econ_cwd econ_slug econ_state econ_acceptance econ_critique
|
|
364
|
+
econ_cwd=$(echo "$usage_event" | jq -r '.context.cwd // ""' 2>/dev/null)
|
|
365
|
+
[[ -z "$econ_cwd" || ! -d "$econ_cwd" ]] && econ_cwd="$PWD"
|
|
366
|
+
# Active slug from the canonical current pointer first, falling back to the legacy pointer.
|
|
367
|
+
econ_slug=""
|
|
368
|
+
if [[ -f "$econ_cwd/.kontourai/flow-agents/current.json" ]]; then
|
|
369
|
+
econ_slug=$(jq -r '.active_slug // .artifact_dir // empty' "$econ_cwd/.kontourai/flow-agents/current.json" 2>/dev/null)
|
|
370
|
+
elif [[ -f "$econ_cwd/.flow-agents/current.json" ]]; then
|
|
371
|
+
econ_slug=$(jq -r '.active_slug // .artifact_dir // empty' "$econ_cwd/.flow-agents/current.json" 2>/dev/null)
|
|
372
|
+
fi
|
|
373
|
+
econ_state="" econ_acceptance="" econ_critique="" econ_agents_dir=""
|
|
374
|
+
if [[ -n "$econ_slug" ]]; then
|
|
375
|
+
# state.json under .kontourai/flow-agents/<slug>/ (fallback .flow-agents/<slug>/); the run's
|
|
376
|
+
# per-agent event logs live alongside it in <slug>/agents/ (#415 delegations[] source).
|
|
377
|
+
for d in "$econ_cwd/.kontourai/flow-agents/$econ_slug" "$econ_cwd/.flow-agents/$econ_slug"; do
|
|
378
|
+
[[ -f "$d/state.json" ]] && { econ_state="$d/state.json"; [[ -d "$d/agents" ]] && econ_agents_dir="$d/agents"; break; }
|
|
379
|
+
done
|
|
380
|
+
[[ -f "$econ_cwd/.flow-agents/$econ_slug/acceptance.json" ]] && econ_acceptance="$econ_cwd/.flow-agents/$econ_slug/acceptance.json"
|
|
381
|
+
[[ -f "$econ_cwd/.flow-agents/$econ_slug/critique.json" ]] && econ_critique="$econ_cwd/.flow-agents/$econ_slug/critique.json"
|
|
382
|
+
fi
|
|
383
|
+
local econ_args=("$usage_event")
|
|
384
|
+
[[ -n "$econ_state" ]] && econ_args+=(--state "$econ_state")
|
|
385
|
+
[[ -n "$econ_acceptance" ]] && econ_args+=(--acceptance "$econ_acceptance")
|
|
386
|
+
[[ -n "$econ_critique" ]] && econ_args+=(--critique "$econ_critique")
|
|
387
|
+
[[ -n "$econ_agents_dir" ]] && econ_args+=(--agents-dir "$econ_agents_dir")
|
|
388
|
+
(bash "$econ_script" "${econ_args[@]}") </dev/null >/dev/null 2>&1 &
|
|
389
|
+
disown 2>/dev/null || true
|
|
390
|
+
fi
|
|
343
391
|
fi
|
|
344
392
|
|
|
345
393
|
echo "$event"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../schemas/backlog-provider-settings.schema.json",
|
|
3
|
+
"schema_version": "1.0",
|
|
4
|
+
"workspace": {
|
|
5
|
+
"repos": ["flow-agents", "surface", "veritas"]
|
|
6
|
+
},
|
|
7
|
+
"defaults": {
|
|
8
|
+
"work_item_provider": {
|
|
9
|
+
"role": "WorkItemProvider",
|
|
10
|
+
"kind": "github",
|
|
11
|
+
"repo": {
|
|
12
|
+
"owner": "kontourai",
|
|
13
|
+
"name": "flow-agents",
|
|
14
|
+
"url": "https://github.com/kontourai/flow-agents"
|
|
15
|
+
},
|
|
16
|
+
"capabilities": ["issues", "labels", "assignees", "pr_links", "comments"]
|
|
17
|
+
},
|
|
18
|
+
"board_provider": {
|
|
19
|
+
"role": "BoardProvider",
|
|
20
|
+
"kind": "github",
|
|
21
|
+
"repo": {
|
|
22
|
+
"owner": "kontourai",
|
|
23
|
+
"name": "flow-agents",
|
|
24
|
+
"url": "https://github.com/kontourai/flow-agents"
|
|
25
|
+
},
|
|
26
|
+
"board": {
|
|
27
|
+
"type": "github_project",
|
|
28
|
+
"owner": "kontourai",
|
|
29
|
+
"number": 1,
|
|
30
|
+
"url": "https://github.com/orgs/kontourai/projects/1"
|
|
31
|
+
},
|
|
32
|
+
"capabilities": ["projects_boards", "status_fields", "custom_fields"]
|
|
33
|
+
},
|
|
34
|
+
"selection": {
|
|
35
|
+
"filters": {
|
|
36
|
+
"issue_state": "open",
|
|
37
|
+
"include_labels": [],
|
|
38
|
+
"ready_statuses": ["ready"],
|
|
39
|
+
"exclude_statuses": ["in_progress", "blocked", "review", "verification", "done"]
|
|
40
|
+
},
|
|
41
|
+
"wip_policy": {
|
|
42
|
+
"prefer_finishing_active_work": true,
|
|
43
|
+
"active_statuses": ["in_progress", "review", "verification"],
|
|
44
|
+
"block_new_work_when_active_count_exceeds": 0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -62,6 +62,41 @@ Use `flow-agents init --yes` or `--headless` with the same flags in CI. The
|
|
|
62
62
|
legacy sink names `kontour-cloud` and `hosted-kontour-console` are still
|
|
63
63
|
accepted for existing scripts.
|
|
64
64
|
|
|
65
|
+
### Owner machine mirror
|
|
66
|
+
|
|
67
|
+
For a personal machine or repo where an owner wants Claude Code (or other
|
|
68
|
+
runtime) hook sessions mirrored to a hosted Console, without editing the
|
|
69
|
+
tracked `scripts/telemetry/telemetry.conf` default template (that file ships
|
|
70
|
+
verbatim into every packaged bundle, so writing a personal token/tenant into
|
|
71
|
+
it would leak to downstream consumers) and without exporting env vars per
|
|
72
|
+
session, `scripts/telemetry/lib/config.sh` auto-discovers a gitignored,
|
|
73
|
+
operator-created conf at either of two conventional paths, no extra wiring
|
|
74
|
+
required:
|
|
75
|
+
|
|
76
|
+
1. `<workspace>/.kontourai/telemetry-console.conf` — repo-scoped, checked
|
|
77
|
+
first.
|
|
78
|
+
2. `~/.flow-agents/telemetry-console.conf` — machine-scoped, used when no
|
|
79
|
+
workspace-scoped conf is present.
|
|
80
|
+
|
|
81
|
+
Populate either path with the existing preset installer:
|
|
82
|
+
`scripts/telemetry/install-console-config.sh <conf-path> --telemetry-sink
|
|
83
|
+
kontour-hosted-console --console-token-file <token-file> --console-tenant
|
|
84
|
+
<tenant>`. The installer `chmod 600`s the file, sets it to be owned by the
|
|
85
|
+
current user, and never echoes the token. Both conditions matter: config.sh
|
|
86
|
+
only honors a discovered conf if it is mode 600 and owned by the current
|
|
87
|
+
user, since that combination can only come from an operator running the
|
|
88
|
+
installer (or an equivalent manual `chmod 600`) — it distinguishes an
|
|
89
|
+
operator-created conf from one that arrived via `git clone`, a tarball, a
|
|
90
|
+
PR, or any other supply-chain path, none of which can produce a 600-mode
|
|
91
|
+
file. A conf that fails that check is treated as if it were absent (fail
|
|
92
|
+
open) and resolution falls through to the next tier.
|
|
93
|
+
|
|
94
|
+
The explicit `TELEMETRY_CONFIG_FILE` env var still overrides both
|
|
95
|
+
auto-discovered paths and always wins. Wiring it from a login-shell profile
|
|
96
|
+
(for example `~/.profile` on `bash -l` setups) remains available for exotic
|
|
97
|
+
setups that need a config path outside both conventional locations, but is
|
|
98
|
+
no longer required for the common case.
|
|
99
|
+
|
|
65
100
|
Check an installed telemetry setup without opening an interactive prompt:
|
|
66
101
|
|
|
67
102
|
```bash
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Engine and Kits
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Engine and Kits
|
|
6
|
+
|
|
7
|
+
**Flow Agents is an engine you build on — not a single product, and not the Builder Kit.** It has two layers:
|
|
8
|
+
|
|
9
|
+
1. The **engine** is the product-neutral runtime layer: it interprets Flow Definitions, evaluates gates, adapts to host runtimes and harnesses, provides SDK/evidence/trust primitives, and validates Flow Kit containers and Flow Agents extensions.
|
|
10
|
+
2. **Kits** are the swappable solution layer: bundles of flows, gates, skills, agents, hooks, docs, adapters, evals, and assets declared by `kit.json` and registered through `kits/catalog.json`.
|
|
11
|
+
|
|
12
|
+
The engine is what you build on. Kits are what you build with.
|
|
13
|
+
|
|
14
|
+
> **Flow Agents is not the Builder Kit.** Builder is one kit on the engine. So is Knowledge. So are the agentless Release-Evidence and Veritas-Governance kits — proof that the engine runs solutions shipping no agent at all. The engine gives no kit special runtime privilege; "official" is a marketplace label, not engine authority.
|
|
15
|
+
|
|
16
|
+
## The engine
|
|
17
|
+
|
|
18
|
+
The engine does not encode one product workflow. It supplies the common substrate that lets any kit run through the same install, validation, activation, steering, evidence, and gate-evaluation path.
|
|
19
|
+
|
|
20
|
+
Concrete engine pieces in this repository include:
|
|
21
|
+
|
|
22
|
+
- **FlowDefinition interpretation and gates** — kit manifests point at `.flow.json` definitions, and Flow Agents validates and activates those definitions for runtime use. The Kit Authoring Guide shows a minimal Flow Definition with steps, gates, and required evidence, while `kits/builder/kit.json`, `kits/knowledge/kit.json`, `kits/release-evidence/kit.json`, and `kits/veritas-governance/kit.json` show different real kit shapes.
|
|
23
|
+
- **Runtime and harness adapters** — Flow Agents compiles the same canonical policy classes to host surfaces such as Claude Code, Codex, Kiro, opencode, pi, and framework adapters. The Runtime Hook Surface spec defines the runtime-neutral vocabulary.
|
|
24
|
+
- **SDK, evidence, and trust primitives** — workflow sidecars, trust bundles, evidence records, command capture, and CI reconciliation give gates something inspectable to evaluate instead of relying on chat memory.
|
|
25
|
+
- **Kit validation framework** — `kit.json` is validated as a Flow Kit container, then Flow Agents validates extension fields such as `skills`, `docs`, `adapters`, `evals`, `assets`, `dependencies`, `workflow_triggers`, and `hook_influence_expectations`.
|
|
26
|
+
|
|
27
|
+
The important boundary: the engine owns the generic process machinery, not the domain workflow. A coding delivery workflow, a knowledge-store workflow, and an agentless CI evidence workflow all pass through the same container and gate model.
|
|
28
|
+
|
|
29
|
+
## The kits
|
|
30
|
+
|
|
31
|
+
A kit is a declared bundle. The catalog names available kits; each kit's manifest declares its own assets.
|
|
32
|
+
|
|
33
|
+
Today `kits/catalog.json` registers four built-in examples:
|
|
34
|
+
|
|
35
|
+
| Kit | Manifest | What it proves |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| Builder Kit | `kits/builder/kit.json` | A full agent-facing delivery kit with shape/build/publish-learn flows, many skills, a dependency on Knowledge, and structured `workflow_triggers`. |
|
|
38
|
+
| Knowledge Kit | `kits/knowledge/kit.json` | A durable knowledge-store kit with many Flow Definitions, one agent skill, docs, adapters, providers, evals, and its own `workflow_triggers`. |
|
|
39
|
+
| Release Evidence Kit | `kits/release-evidence/kit.json` | A minimal flows-only kit for agentless gate evaluation in CI. It has no skills and is not a Builder workflow. |
|
|
40
|
+
| Veritas Governance Kit | `kits/veritas-governance/kit.json` | An agentless governance kit that wraps `veritas readiness` evidence as trust.bundle claims without reimplementing Veritas standards evaluation. |
|
|
41
|
+
|
|
42
|
+
Those examples are deliberately different. Builder is not the product. Builder is one kit on the engine. Knowledge is another. Release Evidence and Veritas Governance prove the engine can run useful kits that are not conversational coding workflows at all.
|
|
43
|
+
|
|
44
|
+
## Manifest and catalog model
|
|
45
|
+
|
|
46
|
+
`kits/catalog.json` is the registry of built-in kits. It records the kit id, name, path, and human-facing description.
|
|
47
|
+
|
|
48
|
+
Each kit directory has a `kit.json` manifest. The shared container fields are small and portable:
|
|
49
|
+
|
|
50
|
+
- `schema_version`
|
|
51
|
+
- `id`
|
|
52
|
+
- `name`
|
|
53
|
+
- `description` or `product_name`
|
|
54
|
+
- `flows`
|
|
55
|
+
|
|
56
|
+
Flow Agents adds optional extension fields for agent use:
|
|
57
|
+
|
|
58
|
+
- `skills`
|
|
59
|
+
- `docs`
|
|
60
|
+
- `adapters`
|
|
61
|
+
- `evals`
|
|
62
|
+
- `assets`
|
|
63
|
+
- `dependencies`
|
|
64
|
+
- `workflow_triggers`
|
|
65
|
+
- `hook_influence_expectations`
|
|
66
|
+
|
|
67
|
+
This is the plugin model. A third-party kit uses the same container shape and validation path as the built-in kits. Bring-your-own-kit is not a side channel; it is the extension point.
|
|
68
|
+
|
|
69
|
+
## Kit-neutral steering
|
|
70
|
+
|
|
71
|
+
The engine is kit-neutral. No kit gets special runtime branches just because it is built in, first-party, or official.
|
|
72
|
+
|
|
73
|
+
Kits steer the engine only through structured `workflow_triggers`. For example, Builder declares a trigger for `implementation-work-detected` that points at `builder.build` and names `deliver` as the default skill. Knowledge declares a trigger for `knowledge-capture-detected` that points at `knowledge.ingest` and names `knowledge.knowledge-capture` as the default skill.
|
|
74
|
+
|
|
75
|
+
The engine renders those structured fields through one steering path. It does not accept freeform kit steering text, and it does not grant runtime privilege based on provenance.
|
|
76
|
+
|
|
77
|
+
`first_party` is legacy catalog or marketplace metadata. It can help a marketplace label a kit, but it does not change runtime authority. Built-in, official, and community kits all participate through the same manifest, catalog, activation, and trigger model.
|
|
78
|
+
|
|
79
|
+
## Marketplace direction
|
|
80
|
+
|
|
81
|
+
The growth path is a marketplace of kits, not a growing list of hardcoded engine behaviors.
|
|
82
|
+
|
|
83
|
+
The pieces already in the repository are the same pieces a marketplace needs:
|
|
84
|
+
|
|
85
|
+
- `catalog.json` as the registry shape for discoverable kits.
|
|
86
|
+
- `kit.json` as the manifest and identity document.
|
|
87
|
+
- validation as the admission check before install or activation.
|
|
88
|
+
- kit identity and trust metadata as marketplace labels, not runtime privilege.
|
|
89
|
+
- activation paths that copy declared assets without making one kit special.
|
|
90
|
+
|
|
91
|
+
That means a team can bring its own kit for a domain workflow, install it, validate it, activate it, and have it steer through the same structured trigger model as the built-in kits.
|
|
92
|
+
|
|
93
|
+
## Trust posture
|
|
94
|
+
|
|
95
|
+
Kit trust is orthogonal to engine privilege. A marketplace may call a kit official, verified, unverified, first-party, or community-contributed. The runtime should still ask the same questions:
|
|
96
|
+
|
|
97
|
+
- Is the kit manifest valid?
|
|
98
|
+
- Are declared assets present and local to the kit?
|
|
99
|
+
- Are dependencies installed and activated?
|
|
100
|
+
- Are trigger fields structured and valid?
|
|
101
|
+
- Does evidence satisfy the active FlowDefinition gate?
|
|
102
|
+
|
|
103
|
+
The answer is determined by validation, activation, and gate evidence, not by a privileged kit list.
|
|
104
|
+
|
|
105
|
+
## Related docs
|
|
106
|
+
|
|
107
|
+
- [Flow Kit Authoring Guide](kit-authoring-guide.md)
|
|
108
|
+
- [Flow Kit Repository Contract](flow-kit-repository-contract.md)
|
|
109
|
+
- [Runtime Hook Surface spec](spec/runtime-hook-surface.md)
|
|
110
|
+
- [Verifiable Trust](verifiable-trust.md)
|
package/docs/context-map.md
CHANGED
|
@@ -44,6 +44,7 @@ Generated by `npm run context-map`. Regenerate after changing agents, skills, sc
|
|
|
44
44
|
| Claim lookup | npm run workflow:sidecar -- claim <id> <dir> |
|
|
45
45
|
| Context map drift | npm run context-map:check |
|
|
46
46
|
| Bundle build | npm run build:bundles |
|
|
47
|
+
| Skill drift check | flow-agents skill-drift-check |
|
|
47
48
|
|
|
48
49
|
## Workflow Sidecars
|
|
49
50
|
|
|
@@ -94,6 +95,7 @@ Primary tools: `npm run workflow:sidecar`, `npm run workflow:validate-artifacts`
|
|
|
94
95
|
| dependency-update | skills/dependency-update/SKILL.md | Analyze and upgrade project dependencies — latest versions, security vulnerabilities, actionable update plan across all package managers. |
|
|
95
96
|
| design-probe | kits/builder/skills/design-probe/SKILL.md | Generic one-question-at-a-time design probing interview for turning unclear goals, designs, or workflow states into shared understanding before planning or execution. |
|
|
96
97
|
| eval-rebuild | skills/eval-rebuild/SKILL.md | Project-specific build and install commands for the eval feedback loop. Injected into eval-builder agent. Replace this skill for different build systems. |
|
|
98
|
+
| exemption-usage-review | kits/veritas-governance/skills/exemption-usage-review/SKILL.md | 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 config... |
|
|
97
99
|
| github-cli | skills/github-cli/SKILL.md | Interact with GitHub via gh CLI — PRs, issues, repos, releases, workflows, gists. |
|
|
98
100
|
| knowledge-capture | kits/knowledge/skills/knowledge-capture/SKILL.md | Save durable knowledge, lightweight pointers, user corrections, decisions, lessons, relationship context, or source references into the knowledge base. Use when the user says save, remember, capture, file this, bookmark context, or when... |
|
|
99
101
|
| pickup-probe | kits/builder/skills/pickup-probe/SKILL.md | Builder Kit work-item/docs/provider-grounded Probe specialization used at the design-probe flow step before plan-work. |
|