@kontourai/flow-agents 3.3.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.github/workflows/add-to-project.yml +15 -0
  2. package/.github/workflows/ci.yml +161 -0
  3. package/CHANGELOG.md +48 -0
  4. package/CONTEXT.md +5 -1
  5. package/README.md +19 -8
  6. package/build/src/builder-flow-run-adapter.d.ts +80 -0
  7. package/build/src/builder-flow-run-adapter.js +241 -0
  8. package/build/src/builder-flow-runtime.d.ts +16 -0
  9. package/build/src/builder-flow-runtime.js +290 -0
  10. package/build/src/cli/builder-run.d.ts +1 -0
  11. package/build/src/cli/builder-run.js +27 -0
  12. package/build/src/cli/effective-backlog-settings.js +70 -2
  13. package/build/src/cli/init.d.ts +34 -0
  14. package/build/src/cli/init.js +341 -61
  15. package/build/src/cli/kit.js +55 -12
  16. package/build/src/cli/pull-work-provider.js +346 -5
  17. package/build/src/cli/skill-drift-check.d.ts +1 -0
  18. package/build/src/cli/skill-drift-check.js +165 -0
  19. package/build/src/cli/telemetry-doctor.d.ts +37 -0
  20. package/build/src/cli/telemetry-doctor.js +53 -6
  21. package/build/src/cli/validate-hook-influence.js +37 -7
  22. package/build/src/cli/workflow-sidecar.d.ts +93 -8
  23. package/build/src/cli/workflow-sidecar.js +1175 -158
  24. package/build/src/cli.js +5 -0
  25. package/build/src/flow-kit/validate.d.ts +54 -34
  26. package/build/src/flow-kit/validate.js +237 -26
  27. package/build/src/index.d.ts +2 -0
  28. package/build/src/index.js +1 -0
  29. package/build/src/lib/console-connect-options.d.ts +97 -0
  30. package/build/src/lib/console-connect-options.js +199 -0
  31. package/build/src/lib/console-telemetry-validate.d.ts +49 -0
  32. package/build/src/lib/console-telemetry-validate.js +91 -0
  33. package/build/src/lib/flow-resolver.d.ts +56 -3
  34. package/build/src/lib/flow-resolver.js +151 -11
  35. package/build/src/lib/fs.d.ts +17 -0
  36. package/build/src/lib/fs.js +172 -0
  37. package/build/src/lib/local-artifact-root.d.ts +44 -1
  38. package/build/src/lib/local-artifact-root.js +131 -3
  39. package/build/src/runtime-adapters.d.ts +39 -3
  40. package/build/src/runtime-adapters.js +77 -31
  41. package/build/src/tools/build-universal-bundles.js +40 -2
  42. package/build/src/tools/codex-agent-routing.d.ts +2 -0
  43. package/build/src/tools/codex-agent-routing.js +49 -0
  44. package/build/src/tools/generate-context-map.js +1 -0
  45. package/build/src/tools/validate-source-tree.js +27 -1
  46. package/context/scripts/hooks/lib/kit-catalog.js +235 -0
  47. package/context/scripts/hooks/lib/runnable-command.js +177 -0
  48. package/context/scripts/hooks/stop-goal-fit.js +278 -48
  49. package/context/scripts/hooks/workflow-steering.js +121 -21
  50. package/context/scripts/package.json +3 -0
  51. package/context/scripts/telemetry/install-console-config.sh +25 -4
  52. package/context/scripts/telemetry/lib/config.sh +102 -12
  53. package/context/scripts/telemetry/lib/pricing.sh +50 -0
  54. package/context/scripts/telemetry/lib/session.sh +3 -0
  55. package/context/scripts/telemetry/lib/transport.sh +87 -0
  56. package/context/scripts/telemetry/lib/usage.sh +205 -4
  57. package/context/scripts/telemetry/telemetry.conf +6 -0
  58. package/context/scripts/telemetry/telemetry.sh +48 -0
  59. package/context/settings/workspace-backlog-provider-settings.example.json +48 -0
  60. package/docs/agent-usage-feedback-loop.md +35 -0
  61. package/docs/architecture-engine-and-kits.md +110 -0
  62. package/docs/context-map.md +2 -0
  63. package/docs/decisions/embeddable-engine.md +152 -0
  64. package/docs/decisions/index.md +3 -1
  65. package/docs/decisions/trust-ledger-retention.md +88 -0
  66. package/docs/decisions/workflow-enforcement.md +31 -9
  67. package/docs/fixture-ownership.md +3 -0
  68. package/docs/implementing-trust-reconciliation.md +129 -0
  69. package/docs/index.md +19 -9
  70. package/docs/integrations/flow-agents-console.md +167 -0
  71. package/docs/kit-authoring-guide.md +52 -21
  72. package/docs/spec/builder-flow-runtime.md +80 -0
  73. package/docs/spec/runtime-hook-surface.md +45 -1
  74. package/docs/specs/economics-record-contract.md +270 -0
  75. package/docs/specs/harness-capability-matrix.md +74 -0
  76. package/docs/specs/learning-review-proposals-contract.md +340 -0
  77. package/docs/specs/routing-efficiency-review.md +59 -0
  78. package/docs/verifiable-trust.md +74 -25
  79. package/docs/workflow-usage-guide.md +10 -0
  80. package/evals/acceptance/prove-capture-teeth.sh +132 -0
  81. package/evals/ci/antigaming-suite.sh +1 -0
  82. package/evals/ci/run-baseline.sh +72 -4
  83. package/evals/fixtures/economics/acceptance.json +12 -0
  84. package/evals/fixtures/economics/agents/tool-worker-1/events.jsonl +2 -0
  85. package/evals/fixtures/economics/agents/tool-worker-2/events.jsonl +2 -0
  86. package/evals/fixtures/economics/agents/tool-worker-3/events.jsonl +2 -0
  87. package/evals/fixtures/economics/agents/tool-worker-4/events.jsonl +1 -0
  88. package/evals/fixtures/economics/agents/tool-worker-5/events.jsonl +2 -0
  89. package/evals/fixtures/economics/critique.json +22 -0
  90. package/evals/fixtures/economics/expected-record.json +71 -0
  91. package/evals/fixtures/economics/session-usage-event.json +1 -0
  92. package/evals/fixtures/economics/state.json +11 -0
  93. package/evals/fixtures/economics/transcript.jsonl +3 -0
  94. package/evals/fixtures/hook-influence/cases.json +7 -7
  95. package/evals/fixtures/learning-review-proposals/balanced/economics.jsonl +6 -0
  96. package/evals/fixtures/learning-review-proposals/effect-follow-up/economics.jsonl +5 -0
  97. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-1/trust.bundle +21 -0
  98. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-2/trust.bundle +21 -0
  99. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-3/trust.bundle +21 -0
  100. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-4/trust.bundle +21 -0
  101. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-5/trust.bundle +21 -0
  102. package/evals/fixtures/learning-review-proposals/pattern-present/economics.jsonl +6 -0
  103. package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.json +30 -0
  104. package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.md +66 -0
  105. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/gate-review.inquiries.json +26 -0
  106. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/trust.bundle +21 -0
  107. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/gate-review.inquiries.json +26 -0
  108. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/trust.bundle +21 -0
  109. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/gate-review.inquiries.json +26 -0
  110. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/trust.bundle +21 -0
  111. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/gate-review.inquiries.json +26 -0
  112. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/trust.bundle +21 -0
  113. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-5/trust.bundle +21 -0
  114. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-6/trust.bundle +21 -0
  115. package/evals/fixtures/learning-review-proposals/repeat-window/economics.jsonl +6 -0
  116. package/evals/fixtures/learning-review-proposals/under-threshold/economics.jsonl +3 -0
  117. package/evals/fixtures/telemetry/usage-transcript-sample.jsonl +4 -0
  118. package/evals/fixtures/trust-reconcile-exploits/mcp-degrade.json +42 -0
  119. package/evals/integration/test_builder_entry_enforcement.sh +241 -0
  120. package/evals/integration/test_builder_step_producers.sh +18 -10
  121. package/evals/integration/test_bundle_install.sh +172 -0
  122. package/evals/integration/test_console_tenant_isolation.sh +167 -0
  123. package/evals/integration/test_critique_supersession_roundtrip.sh +4 -1
  124. package/evals/integration/test_dual_emit_flow_step.sh +10 -4
  125. package/evals/integration/test_economics_record.sh +674 -0
  126. package/evals/integration/test_effective_backlog_settings.sh +1 -1
  127. package/evals/integration/test_evidence_capture_hook.sh +17 -2
  128. package/evals/integration/test_exemption_usage_review.sh +198 -0
  129. package/evals/integration/test_fixture_retirement_audit.sh +2 -2
  130. package/evals/integration/test_flow_kit_install_git.sh +83 -0
  131. package/evals/integration/test_flowdef_session_activation.sh +0 -1
  132. package/evals/integration/test_flowdef_session_history_preservation.sh +13 -3
  133. package/evals/integration/test_gate_lockdown.sh +7 -0
  134. package/evals/integration/test_gate_review_inquiry_records.sh +9 -1
  135. package/evals/integration/test_goal_fit_hook.sh +2031 -0
  136. package/evals/integration/test_hook_category_behaviors.sh +8 -1
  137. package/evals/integration/test_hook_influence_cases.sh +25 -1
  138. package/evals/integration/test_install_merge.sh +227 -2
  139. package/evals/integration/test_kit_conformance_levels.sh +6 -6
  140. package/evals/integration/test_learning_review_proposals.sh +329 -0
  141. package/evals/integration/test_liveness_conflict_injection.sh +26 -22
  142. package/evals/integration/test_liveness_console_relay.sh +166 -0
  143. package/evals/integration/test_liveness_heartbeat.sh +17 -17
  144. package/evals/integration/test_liveness_worktree_root.sh +575 -0
  145. package/evals/integration/test_phase_map_and_gate_claim.sh +6 -1
  146. package/evals/integration/test_publish_delivery.sh +331 -1
  147. package/evals/integration/test_pull_work_board.sh +200 -0
  148. package/evals/integration/test_pull_work_provider.sh +1 -1
  149. package/evals/integration/test_record_check.sh +378 -0
  150. package/evals/integration/test_routing_efficiency.sh +71 -0
  151. package/evals/integration/test_runtime_adapter_activation.sh +28 -0
  152. package/evals/integration/test_session_resume_roundtrip.sh +16 -19
  153. package/evals/integration/test_skill_drift_check.sh +870 -0
  154. package/evals/integration/test_telemetry.sh +445 -0
  155. package/evals/integration/test_telemetry_doctor.sh +66 -0
  156. package/evals/integration/test_telemetry_usage_pipeline.sh +228 -0
  157. package/evals/integration/test_trust_reconcile_negatives.sh +30 -13
  158. package/evals/integration/test_trust_reconcile_trailer_diagnostic.sh +247 -0
  159. package/evals/integration/test_usage_cost.sh +61 -0
  160. package/evals/integration/test_workflow_sidecar_writer.sh +1395 -0
  161. package/evals/integration/test_workflow_steering_hook.sh +157 -16
  162. package/evals/integration/test_workspace_settings.sh +176 -0
  163. package/evals/lib/env.sh +26 -0
  164. package/evals/lib/node.sh +8 -0
  165. package/evals/run.sh +29 -0
  166. package/evals/static/test_ci_integration_coverage.sh +115 -0
  167. package/evals/static/test_declared_scope_forms_documented.sh +114 -0
  168. package/evals/static/test_universal_bundles.sh +34 -0
  169. package/evals/static/test_validate_source_kit_asset_scope.sh +259 -0
  170. package/evals/static/test_workflow_skills.sh +1 -1
  171. package/kits/builder/flows/build.flow.json +9 -18
  172. package/kits/builder/flows/publish-learn.flow.json +5 -1
  173. package/kits/builder/kit.json +120 -0
  174. package/kits/builder/skills/deliver/SKILL.md +42 -0
  175. package/kits/builder/skills/evidence-gate/SKILL.md +12 -0
  176. package/kits/builder/skills/execute-plan/SKILL.md +9 -0
  177. package/kits/builder/skills/learning-review/SKILL.md +51 -0
  178. package/kits/builder/skills/plan-work/SKILL.md +17 -20
  179. package/kits/builder/skills/pull-work/SKILL.md +21 -0
  180. package/kits/builder/skills/release-readiness/SKILL.md +12 -0
  181. package/kits/knowledge/kit.json +9 -0
  182. package/kits/veritas-governance/docs/README.md +35 -7
  183. package/kits/veritas-governance/fixtures/exemption-review/mixed-fresh-stale.DECLARED.json +14 -0
  184. package/kits/veritas-governance/kit.json +14 -0
  185. package/kits/veritas-governance/skills/exemption-usage-review/SKILL.md +128 -0
  186. package/kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs +231 -0
  187. package/package.json +2 -2
  188. package/packaging/manifest.json +29 -0
  189. package/schemas/backlog-provider-settings.schema.json +13 -0
  190. package/schemas/workflow-state.schema.json +44 -0
  191. package/scripts/README.md +4 -0
  192. package/scripts/check-content-boundary.cjs +8 -1
  193. package/scripts/ci/trust-reconcile.js +136 -0
  194. package/scripts/hooks/codex-hook-adapter.js +77 -2
  195. package/scripts/hooks/evidence-capture.js +38 -5
  196. package/scripts/hooks/lib/codex-exit-code.js +316 -0
  197. package/scripts/hooks/lib/kit-catalog.js +235 -0
  198. package/scripts/hooks/lib/liveness-write.js +28 -1
  199. package/scripts/hooks/lib/local-artifact-paths.js +97 -1
  200. package/scripts/hooks/lib/runnable-command.js +177 -0
  201. package/scripts/hooks/lib/skill-drift.js +350 -0
  202. package/scripts/hooks/stop-goal-fit.js +278 -48
  203. package/scripts/hooks/workflow-steering.js +121 -21
  204. package/scripts/install-codex-home.sh +97 -47
  205. package/scripts/install-merge.js +72 -14
  206. package/scripts/install-owned-files.js +178 -0
  207. package/scripts/liveness/relay.sh +84 -0
  208. package/scripts/telemetry/economics-record.schema.json +145 -0
  209. package/scripts/telemetry/economics-record.sh +331 -0
  210. package/scripts/telemetry/install-console-config.sh +25 -4
  211. package/scripts/telemetry/learning-review-decide.sh +124 -0
  212. package/scripts/telemetry/learning-review-proposals.schema.json +161 -0
  213. package/scripts/telemetry/learning-review-proposals.sh +484 -0
  214. package/scripts/telemetry/lib/config.sh +102 -12
  215. package/scripts/telemetry/lib/pricing.sh +14 -6
  216. package/scripts/telemetry/lib/session.sh +3 -0
  217. package/scripts/telemetry/lib/transport.sh +133 -15
  218. package/scripts/telemetry/lib/usage.sh +121 -28
  219. package/scripts/telemetry/routing-efficiency.sh +0 -0
  220. package/scripts/telemetry/telemetry.conf +6 -0
  221. package/scripts/telemetry/telemetry.sh +48 -0
  222. package/src/builder-flow-run-adapter.ts +357 -0
  223. package/src/builder-flow-runtime.ts +348 -0
  224. package/src/cli/builder-flow-run-adapter.test.mjs +495 -0
  225. package/src/cli/builder-flow-runtime.test.mjs +213 -0
  226. package/src/cli/builder-run.ts +28 -0
  227. package/src/cli/codex-agent-routing.test.mjs +44 -0
  228. package/src/cli/codex-exit-code.test.mjs +207 -0
  229. package/src/cli/console-connect-options.test.mjs +329 -0
  230. package/src/cli/console-telemetry-validate.test.mjs +157 -0
  231. package/src/cli/effective-backlog-settings.ts +68 -2
  232. package/src/cli/flow-resolver-composition.test.mjs +101 -0
  233. package/src/cli/init.test.mjs +161 -0
  234. package/src/cli/init.ts +407 -62
  235. package/src/cli/kit-metadata-security.test.mjs +443 -0
  236. package/src/cli/kit.ts +50 -12
  237. package/src/cli/pull-work-provider.ts +377 -3
  238. package/src/cli/sidecar-pure-helpers.test.mjs +64 -0
  239. package/src/cli/skill-drift-check.ts +196 -0
  240. package/src/cli/telemetry-doctor.test.mjs +53 -0
  241. package/src/cli/telemetry-doctor.ts +50 -7
  242. package/src/cli/validate-hook-influence.ts +37 -6
  243. package/src/cli/workflow-sidecar.ts +1150 -151
  244. package/src/cli.ts +5 -0
  245. package/src/flow-kit/validate.ts +277 -38
  246. package/src/index.ts +19 -0
  247. package/src/lib/console-connect-options.ts +261 -0
  248. package/src/lib/console-telemetry-validate.ts +88 -0
  249. package/src/lib/flow-resolver.ts +153 -10
  250. package/src/lib/fs.ts +160 -0
  251. package/src/lib/local-artifact-root.ts +129 -3
  252. package/src/runtime-adapters.ts +113 -33
  253. package/src/tools/build-universal-bundles.ts +36 -2
  254. package/src/tools/codex-agent-routing.ts +48 -0
  255. package/src/tools/generate-context-map.ts +1 -0
  256. package/src/tools/validate-source-tree.ts +26 -1
@@ -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 && return
21
- grep -c "\"session_id\":\"${session_id}\".*\"event_type\":\"tool.invoke\"" "$jsonl_path" 2>/dev/null || echo 0
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 && return
28
- grep -c "\"session_id\":\"${session_id}\".*\"event_type\":\"agent.delegate\"" "$jsonl_path" 2>/dev/null || echo 0
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)
@@ -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. |