@kontourai/flow-agents 0.2.0 → 0.3.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.
Files changed (46) hide show
  1. package/.github/workflows/runtime-compat.yml +1 -1
  2. package/CHANGELOG.md +23 -0
  3. package/README.md +38 -19
  4. package/build/src/cli/flow-kit.js +9 -4
  5. package/build/src/cli/runtime-adapter.js +9 -5
  6. package/build/src/cli/telemetry-doctor.js +4 -1
  7. package/build/src/runtime-adapters.js +34 -0
  8. package/build/src/tools/build-universal-bundles.js +18 -1
  9. package/console.telemetry.json +115 -20
  10. package/docs/_layouts/default.html +2 -0
  11. package/docs/index.md +8 -0
  12. package/docs/integrations/index.md +4 -0
  13. package/docs/integrations/knowledge-kit-live.md +211 -0
  14. package/docs/kit-authoring-guide.md +169 -0
  15. package/docs/spec/runtime-hook-surface.md +56 -3
  16. package/evals/acceptance/run.sh +10 -1
  17. package/evals/acceptance/test_knowledge_kit_live.sh +221 -0
  18. package/evals/acceptance/test_pi_harness.sh +15 -0
  19. package/evals/integration/test_runtime_adapter_activation.sh +113 -1
  20. package/integrations/strands/examples/knowledge_kit_live.py +461 -0
  21. package/integrations/strands/flow_agents_strands/steering.py +54 -1
  22. package/integrations/strands/tests/test_hooks.py +88 -0
  23. package/integrations/strands-ts/src/hooks.ts +104 -0
  24. package/integrations/strands-ts/test/test-steering.ts +159 -0
  25. package/kits/catalog.json +6 -0
  26. package/kits/knowledge/adapters/default-store/index.js +821 -0
  27. package/kits/knowledge/adapters/flow-runner/index.js +1179 -0
  28. package/kits/knowledge/adapters/flow-runner/telemetry.js +174 -0
  29. package/kits/knowledge/docs/README.md +135 -0
  30. package/kits/knowledge/docs/store-contract.md +526 -0
  31. package/kits/knowledge/evals/consolidation/suite.test.js +1234 -0
  32. package/kits/knowledge/evals/contract-suite/suite.test.js +670 -0
  33. package/kits/knowledge/evals/ingest-compile/suite.test.js +574 -0
  34. package/kits/knowledge/evals/synthesis/suite.test.js +909 -0
  35. package/kits/knowledge/flows/compile.flow.json +60 -0
  36. package/kits/knowledge/flows/consolidate.flow.json +77 -0
  37. package/kits/knowledge/flows/ingest.flow.json +60 -0
  38. package/kits/knowledge/flows/store-contract.flow.json +48 -0
  39. package/kits/knowledge/flows/synthesize.flow.json +77 -0
  40. package/kits/knowledge/kit.json +78 -0
  41. package/package.json +1 -1
  42. package/src/cli/flow-kit.ts +10 -4
  43. package/src/cli/runtime-adapter.ts +10 -5
  44. package/src/cli/telemetry-doctor.ts +4 -1
  45. package/src/runtime-adapters.ts +35 -0
  46. package/src/tools/build-universal-bundles.ts +18 -1
@@ -72,7 +72,7 @@ jobs:
72
72
  node-version: 24
73
73
 
74
74
  - name: Set up Python
75
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
75
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
76
76
  with:
77
77
  python-version: "3.12"
78
78
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0](https://github.com/kontourai/flow-agents/compare/v0.2.0...v0.3.0) (2026-06-12)
4
+
5
+
6
+ ### Features
7
+
8
+ * **knowledge-kit:** concept synthesis with evidence-gated mutations (S3, [#34](https://github.com/kontourai/flow-agents/issues/34)) ([f307165](https://github.com/kontourai/flow-agents/commit/f30716503b22202d8929876b3e0b5d0d4bcbd2cb))
9
+ * **knowledge-kit:** decision-snapshot consolidation, supersede-not-delete (S6, [#36](https://github.com/kontourai/flow-agents/issues/36)) ([7211605](https://github.com/kontourai/flow-agents/commit/7211605fd19a0a332b7816c1fb0e66259771c3ba))
10
+ * **knowledge-kit:** ingest/classify + compile flows with provenance gates (S2, [#33](https://github.com/kontourai/flow-agents/issues/33)) ([07dffd5](https://github.com/kontourai/flow-agents/commit/07dffd5f6c6ab8555fc8c7e029d6432cd854dd05))
11
+ * **knowledge-kit:** keyless live example + acceptance harness (S5, [#35](https://github.com/kontourai/flow-agents/issues/35)) ([9a565aa](https://github.com/kontourai/flow-agents/commit/9a565aaa8deac236f07b63933bb8ce6887ac25f9))
12
+ * **knowledge-kit:** store contract + default reference adapter (S1, [#31](https://github.com/kontourai/flow-agents/issues/31)) ([4ed06ba](https://github.com/kontourai/flow-agents/commit/4ed06ba7cad7865094feddf0bd5ac7f76639b9ed))
13
+ * strands-local kit activation — framework-path kits (S4, [#32](https://github.com/kontourai/flow-agents/issues/32)) ([8dc05ec](https://github.com/kontourai/flow-agents/commit/8dc05ecf810dc3d205046c4773aa2c1e62159acb))
14
+
15
+
16
+ ### Fixes
17
+
18
+ * dedup pi session.start; document opencode run-mode session.created gap ([4d7e5b1](https://github.com/kontourai/flow-agents/commit/4d7e5b1e2de6573b824852598b04a5da3485adf6))
19
+ * telemetry-doctor reported the workspace parent as the local sink dir ([e15d7b2](https://github.com/kontourai/flow-agents/commit/e15d7b2e922225e4c30a39fceea304ca01e5ac17))
20
+
21
+
22
+ ### Documentation
23
+
24
+ * Flow Kits authoring guide, README kits section, npx command forms ([a89a86c](https://github.com/kontourai/flow-agents/commit/a89a86cc488abb7f6cd3cd300a67044174afa154))
25
+
3
26
  ## [0.2.0](https://github.com/kontourai/flow-agents/compare/v0.1.2...v0.2.0) (2026-06-11)
4
27
 
5
28
 
package/README.md CHANGED
@@ -45,17 +45,29 @@ The spec defines three conformance levels: **L0** (telemetry only), **L1** (stee
45
45
 
46
46
  ## Runtime and support matrix
47
47
 
48
- | Tier | Runtime | Ships | Tested | Conformance |
49
- | --- | --- | --- | --- | --- |
50
- | **Core harness** | Claude Code | install + hooks + bundle | 77 integration + 36 static assertions | L2 reference implementation |
51
- | **Core harness** | Codex | install + hooks + bundle | 77 integration + 36 static assertions | L2 — reference implementation |
52
- | **Core harness** | Kiro | install + hooks + bundle | included in bundle assertions | L2 |
53
- | **Core harness** | opencode | `.opencode/agents/`, `.opencode/skills/`, `.opencode/plugins/flow-agents.js`, `opencode.json` | included in bundle assertions | L1 — no prompt-submit hook; steering wired to `session.created` + `tool.execute.before` |
54
- | **Core harness** | pi | `.pi/extensions/flow-agents.ts`, `.pi/skills/`, `AGENTS.md` | included in bundle assertions | L1no stop hook; stop-goal-fit unavailable |
55
- | **Official framework adapter** | AWS Strands (Python) | `integrations/strands/` — `flow-agents-strands` PyPI package | 50 unit tests (no Strands SDK required) | Spike/preview see [integrations/strands/README.md](integrations/strands/README.md) |
56
- | **Conformance-certified** | Community / third-party | Self-certify using the conformance kit | | Conformance kit in development; not yet shipped |
57
-
58
- Honest gaps are documented in the artifacts: opencode has no native `prompt.submit`-equivalent event; Codex live hook influence is limited to installed-command and protocol coverage; pi has no `permissionRequest` equivalent and no stop hook. The [Runtime Hook Surface spec](docs/spec/runtime-hook-surface.md) names every gap explicitly.
48
+ L2 means all four policy classes with blocking; L1 means steering and stop-goal-fit warning only (no quality gate or blocking config protection). The [Runtime Hook Surface spec](docs/spec/runtime-hook-surface.md) defines the levels and names every hook-surface gap explicitly.
49
+
50
+ **Full support L2 (all four policies, blocking)**
51
+
52
+ | Runtime | Ships | Tested |
53
+ | --- | --- | --- |
54
+ | Claude Code | install + hooks + bundle | 77 integration + 36 static assertionsreference implementation |
55
+ | Codex | install + hooks + bundle | 77 integration + 36 static assertionsreference implementation |
56
+ | Kiro | install + hooks + bundle | included in bundle assertions |
57
+
58
+ **Partial support L1 (steering + stop-goal-fit warning)**
59
+
60
+ | Runtime | Ships | Gap | Tested |
61
+ | --- | --- | --- | --- |
62
+ | opencode | `.opencode/agents/`, `.opencode/skills/`, `.opencode/plugins/flow-agents.js`, `opencode.json` | No prompt-submit hook; steering wired to `session.created` + `tool.execute.before` | included in bundle assertions |
63
+ | pi | `.pi/extensions/flow-agents.ts`, `.pi/skills/`, `AGENTS.md` | No stop hook; stop-goal-fit unavailable | included in bundle assertions |
64
+
65
+ **Other**
66
+
67
+ | Tier | Runtime | Ships | Tested |
68
+ | --- | --- | --- | --- |
69
+ | Official framework adapter | AWS Strands (Python) | `integrations/strands/` — `flow-agents-strands` PyPI package | 50 unit tests (no Strands SDK required) — spike/preview, see [integrations/strands/README.md](integrations/strands/README.md) |
70
+ | Conformance-certified | Community / third-party | Self-certify using the conformance kit | Conformance kit in development; not yet shipped |
59
71
 
60
72
  ## Install
61
73
 
@@ -77,7 +89,7 @@ Working from a checkout (for contributors): `npm install && npm run build`, then
77
89
 
78
90
  The installer copies the bundled agents, skills, context, scripts, evals, Flow Kit assets, and the Flow Agents-owned `console.telemetry.json` descriptor into the target workspace. Telemetry writes to local files by default; optional sinks mirror it to a local, hosted, or self-hosted Kontour Console (`--telemetry-sink local-kontour-console | kontour-hosted-console | user-hosted-console --console-url …`).
79
91
 
80
- The low-level bundle installer remains available when you already have a generated bundle checkout:
92
+ `bash install.sh` is the low-level option for CI pipelines or scripts that already have a generated bundle checkout (e.g. from a pinned `git clone` of this repo). Prefer `npx @kontourai/flow-agents init` for normal workspace setup — it fetches the latest published bundle and auto-detects the runtime:
81
93
 
82
94
  ```bash
83
95
  bash install.sh /path/to/workspace --telemetry-sink local-kontour-console
@@ -91,19 +103,26 @@ After installing, ask the agent for the workflow you want — in plain language:
91
103
  Use Builder Kit shape for this feature idea and create executable GitHub issues.
92
104
  ```
93
105
 
94
- ```text
95
- Use pull-work, select the next ready issue, and hand it to plan-work.
96
- ```
97
-
98
106
  ```text
99
107
  Use deliver for this issue. Plan it, execute it, verify it, and stop if evidence is missing.
100
108
  ```
101
109
 
102
- ```text
103
- Use fix-bug. Reproduce the issue, diagnose root cause, plan the fix, implement it, and verify the regression path.
110
+ The [Workflow Usage Guide](docs/workflow-usage-guide.md) has example prompts and expected behavior for every stage — `pull-work`, `plan-work`, `execute-plan`, `review-work`, `verify-work`, `fix-bug`, `release-readiness`, and more. The [Agent System Guidebook](docs/agent-system-guidebook.md) is the plain-language map of how the pieces fit.
111
+
112
+ ## Flow Kits
113
+
114
+ A Flow Kit is a portable workflow bundle: a `kit.json` manifest, one or more Flow Definitions, and optional skills, docs, adapters, evals, and assets — all validated and installed as a unit. Kits are the extension model for Flow Agents: they let you package a workflow once and deploy it into any workspace through the same path as the built-in workflows.
115
+
116
+ **Builder Kit** is the first Kontour-authored kit. It ships with `builder.shape` (shape a problem into slices and fileable work items) and `builder.build` (pull ready work through design probing, planning, execution, verification, PR readiness, merge readiness, and learning). Builder Kit is installed automatically by `npx @kontourai/flow-agents init`.
117
+
118
+ Install a local kit:
119
+
120
+ ```bash
121
+ npx @kontourai/flow-agents flow-kit install-local path/to/my-kit --dest /path/to/workspace
104
122
  ```
105
123
 
106
- The [Workflow Usage Guide](docs/workflow-usage-guide.md) walks every stage with example prompts and expected behavior; the [Agent System Guidebook](docs/agent-system-guidebook.md) is the plain-language map of how the pieces fit.
124
+ - [Kit Authoring Guide](docs/kit-authoring-guide.md) build your own kit from scratch: directory layout, `kit.json`, a flow file, validation, install, and activation.
125
+ - [Flow Kit Repository Contract](docs/flow-kit-repository-contract.md) — the full validation rules, registry schema, and activation diagnostics.
107
126
 
108
127
  ## Framework adapters
109
128
 
@@ -4,7 +4,7 @@ import * as path from "node:path";
4
4
  import { parseArgs, flagBool, flagString } from "../lib/args.js";
5
5
  import { assertPathContained, copyDir, isoNow, readJson, walkFiles, writeJson } from "../lib/fs.js";
6
6
  import { assertKitRepository } from "../flow-kit/validate.js";
7
- import { activateCodexLocal } from "../runtime-adapters.js";
7
+ import { activateCodexLocal, activateStrandsLocal } from "../runtime-adapters.js";
8
8
  const REGISTRY_REL = path.join("kits", "local", "installed-kits.json");
9
9
  const REPOSITORIES_REL = path.join("kits", "local", "repositories");
10
10
  function registryPath(dest) { return path.join(dest, REGISTRY_REL); }
@@ -108,16 +108,21 @@ function status(argv) {
108
108
  }
109
109
  return 0;
110
110
  }
111
+ // Available adapters for the activate subcommand (Issue #32: added strands-local).
112
+ const AVAILABLE_ADAPTERS = ["codex-local", "strands-local"];
111
113
  function activate(argv) {
112
114
  const args = parseArgs(argv);
113
115
  const dest = path.resolve(flagString(args.flags, "dest", ".") ?? ".");
114
116
  const sourceRoot = path.resolve(flagString(args.flags, "source-root", path.resolve(path.dirname(process.argv[1]), "..")) ?? ".");
115
117
  const adapter = flagString(args.flags, "adapter");
116
- if (adapter && adapter !== "codex-local") {
117
- console.log(JSON.stringify({ selected_adapter: null, available_adapters: ["codex-local"], supported_asset_classes: [], generated_runtime_files: [], skipped_assets: [], warnings: [], errors: [`unknown runtime adapter '${adapter}'; available adapters: codex-local`] }, null, 2));
118
+ if (adapter && !AVAILABLE_ADAPTERS.includes(adapter)) {
119
+ console.log(JSON.stringify({ selected_adapter: null, available_adapters: AVAILABLE_ADAPTERS, supported_asset_classes: [], generated_runtime_files: [], skipped_assets: [], warnings: [], errors: [`unknown runtime adapter '${adapter}'; available adapters: ${AVAILABLE_ADAPTERS.join(", ")}`] }, null, 2));
118
120
  return 2;
119
121
  }
120
- const result = activateCodexLocal(sourceRoot, dest);
122
+ // Default to codex-local for backward compatibility; strands-local is opt-in via --adapter.
123
+ const result = adapter === "strands-local"
124
+ ? activateStrandsLocal(sourceRoot, dest)
125
+ : activateCodexLocal(sourceRoot, dest);
121
126
  console.log(JSON.stringify(result, null, 2));
122
127
  return Array.isArray(result.errors) && result.errors.length ? 1 : 0;
123
128
  }
@@ -1,21 +1,25 @@
1
1
  import * as path from "node:path";
2
2
  import { parseArgs, flagString } from "../lib/args.js";
3
- import { activateCodexLocal } from "../runtime-adapters.js";
3
+ import { activateCodexLocal, activateStrandsLocal } from "../runtime-adapters.js";
4
+ const AVAILABLE_ADAPTERS = ["codex-local", "strands-local"];
4
5
  export function main(argv = process.argv.slice(2)) {
5
6
  const [command, ...rest] = argv;
6
7
  if (command !== "activate") {
7
- console.error("usage: runtime-adapter activate [--dest DIR] [--source-root DIR] [--adapter codex-local]");
8
+ console.error("usage: runtime-adapter activate [--dest DIR] [--source-root DIR] [--adapter codex-local|strands-local]");
8
9
  return 2;
9
10
  }
10
11
  const args = parseArgs(rest);
11
12
  const dest = path.resolve(flagString(args.flags, "dest", ".") ?? ".");
12
13
  const sourceRoot = path.resolve(flagString(args.flags, "source-root", path.resolve(path.dirname(process.argv[1]), "..")) ?? ".");
13
14
  const adapter = flagString(args.flags, "adapter");
14
- if (adapter && adapter !== "codex-local") {
15
- console.log(JSON.stringify({ selected_adapter: null, available_adapters: ["codex-local"], supported_asset_classes: [], generated_runtime_files: [], skipped_assets: [], warnings: [], errors: [`unknown runtime adapter '${adapter}'; available adapters: codex-local`] }, null, 2));
15
+ if (adapter && !AVAILABLE_ADAPTERS.includes(adapter)) {
16
+ console.log(JSON.stringify({ selected_adapter: null, available_adapters: AVAILABLE_ADAPTERS, supported_asset_classes: [], generated_runtime_files: [], skipped_assets: [], warnings: [], errors: [`unknown runtime adapter '${adapter}'; available adapters: ${AVAILABLE_ADAPTERS.join(", ")}`] }, null, 2));
16
17
  return 2;
17
18
  }
18
- const result = activateCodexLocal(sourceRoot, dest);
19
+ // Default to codex-local for backward compatibility; strands-local is opt-in via --adapter.
20
+ const result = adapter === "strands-local"
21
+ ? activateStrandsLocal(sourceRoot, dest)
22
+ : activateCodexLocal(sourceRoot, dest);
19
23
  console.log(JSON.stringify(result, null, 2));
20
24
  return Array.isArray(result.errors) && result.errors.length ? 1 : 0;
21
25
  }
@@ -46,7 +46,10 @@ function channelConfigValue(config, channel, key, fallback = "") {
46
46
  }
47
47
  function telemetryDataDir(dest) {
48
48
  const configured = process.env.TELEMETRY_DATA_DIR;
49
- return configured ? path.resolve(dest, configured) : path.resolve(dest, "..", ".telemetry");
49
+ // Must mirror scripts/telemetry/lib/config.sh: the sink lives INSIDE the
50
+ // workspace at <dest>/.telemetry. The previous "../.telemetry" duplicated
51
+ // the parent-escape bug fixed in config.sh on 2026-06-11.
52
+ return configured ? path.resolve(dest, configured) : path.resolve(dest, ".telemetry");
50
53
  }
51
54
  function deriveConsoleEndpoint(consoleUrl, explicitEndpoint) {
52
55
  if (explicitEndpoint)
@@ -144,3 +144,37 @@ export function activateCodexLocal(sourceRoot, dest) {
144
144
  generated.push({ asset_class: "activation-manifest", path: relPath(dest, manifestPath), kit_id: "runtime", asset_id: "codex-local.activation", source_path: manifestPath.split(path.sep).join("/") });
145
145
  return { selected_adapter: "codex-local", supported_asset_classes: ["flows"], generated_runtime_files: generated, skipped_assets: skipped, warnings: inventory.warnings, errors: inventory.errors };
146
146
  }
147
+ // Decision Q3 (Issue #32): Option (a) — new adapter id "strands-local" rather than
148
+ // loading kit flows inside FlowAgentsHooks. Rationale: activation is a workspace-prep
149
+ // concern (reads catalog + installed kits, writes runtime files, produces diagnostics).
150
+ // Keeping it in the CLI adapter layer maximises reuse of readKitInventory and safeSegment,
151
+ // mirrors the codex-local pattern exactly, and keeps framework adapters free of catalog-
152
+ // layout knowledge. The Strands steering layer then reads the written runtime files.
153
+ export function activateStrandsLocal(sourceRoot, dest) {
154
+ const inventory = readKitInventory(sourceRoot, dest);
155
+ // Runtime flows land at .flow-agents/runtime/strands/flows/<kit-id>/<asset-id>.flow.json
156
+ // so the Strands steering context can glob for *.flow.json under this path.
157
+ const runtimeDir = path.join(dest, ".flow-agents", "runtime", "strands");
158
+ const generated = [];
159
+ const skipped = [];
160
+ for (const asset of inventory.assets) {
161
+ if (asset.asset_class !== "flows") {
162
+ skipped.push({ asset_class: asset.asset_class, path: asset.relative_path, kit_id: asset.kit_id, asset_id: asset.asset_id, reason: "asset class is diagnostic-only for strands-local" });
163
+ continue;
164
+ }
165
+ if (!asset.asset_id) {
166
+ skipped.push({ asset_class: asset.asset_class, path: asset.relative_path, kit_id: asset.kit_id, asset_id: null, reason: "flow asset is missing an id" });
167
+ continue;
168
+ }
169
+ const output = path.join(runtimeDir, "flows", safeSegment(asset.kit_id), `${safeSegment(asset.asset_id)}.flow.json`);
170
+ fs.mkdirSync(path.dirname(output), { recursive: true });
171
+ fs.copyFileSync(asset.source_path, output);
172
+ generated.push({ asset_class: asset.asset_class, path: relPath(dest, output), kit_id: asset.kit_id, asset_id: asset.asset_id, source_path: asset.source_path.split(path.sep).join("/") });
173
+ }
174
+ fs.mkdirSync(runtimeDir, { recursive: true });
175
+ const manifest = { schema_version: "1.0", adapter: "strands-local", supported_asset_classes: ["flows"], generated_runtime_files: generated, skipped_assets: skipped, warnings: inventory.warnings, errors: inventory.errors };
176
+ const manifestPath = path.join(runtimeDir, "activation.json");
177
+ writeJson(manifestPath, manifest);
178
+ generated.push({ asset_class: "activation-manifest", path: relPath(dest, manifestPath), kit_id: "runtime", asset_id: "strands-local.activation", source_path: manifestPath.split(path.sep).join("/") });
179
+ return { selected_adapter: "strands-local", supported_asset_classes: ["flows"], generated_runtime_files: generated, skipped_assets: skipped, warnings: inventory.warnings, errors: inventory.errors };
180
+ }
@@ -384,6 +384,15 @@ function exportOpencodePlugin() {
384
384
  // (for session-start steering context) and tool.execute.before (for
385
385
  // policy). This is the closest reasonable approximation — documented here
386
386
  // as an honest gap matching the codex live-hook-influence caveat pattern.
387
+ //
388
+ // KNOWN GAP (verified 2026-06-11, opencode v1.16.2): session.created is NOT
389
+ // delivered to plugin event handlers in opencode (non-interactive) mode.
390
+ // The session IS created server-side but the event fires before the plugin
391
+ // hook dispatch loop is active. As a result, agentSpawn telemetry (session.start)
392
+ // is never emitted in run-mode sessions — only tool.invoke/tool.result appear.
393
+ // This is an opencode runtime limitation, not a bug in this plugin.
394
+ // Session.start telemetry carries L1 conformance but is unavailable in run mode.
395
+ // See docs/spec/runtime-hook-surface.md opencode mapping row for the full gap note.
387
396
  return `/**
388
397
  * Flow Agents opencode plugin.
389
398
  *
@@ -398,6 +407,13 @@ function exportOpencodePlugin() {
398
407
  * cannot intercept mid-session user messages before they are processed.
399
408
  * This is an accepted gap documented here analogously to the codex
400
409
  * live-hook-influence caveat.
410
+ *
411
+ * KNOWN GAP: session.created is NOT delivered to plugin handlers in opencode
412
+ * run (non-interactive) mode (verified v1.16.2, 2026-06-11). agentSpawn
413
+ * telemetry (session.start) is therefore absent from run-mode sessions.
414
+ * tool.invoke and tool.result events (L1) are still recorded normally.
415
+ * This is an opencode runtime limitation; no workaround is available without
416
+ * a different hook surface. See docs/spec/runtime-hook-surface.md for details.
401
417
  */
402
418
 
403
419
  import { spawnSync } from 'node:child_process';
@@ -577,7 +593,8 @@ export default function (pi: ExtensionAPI) {
577
593
  });
578
594
 
579
595
  pi.on("before_agent_start", async (event, _ctx) => {
580
- runTelemetry("before_agent_start");
596
+ // Telemetry for agentSpawn is emitted by session_start above; do not repeat it here
597
+ // to avoid duplicate session.start events in the telemetry log.
581
598
  // Inject workflow steering context at agent start
582
599
  const result = runAdapter("pi-hook-adapter.js", "before_agent_start", "workflow-steering", "workflow-steering.js");
583
600
  if (result.context) {
@@ -9,7 +9,9 @@
9
9
  "id": "flow-agents-workflow-state",
10
10
  "label": "Workflow state",
11
11
  "root": "product:flow-agents:.flow-agents",
12
- "files": ["state.json"],
12
+ "files": [
13
+ "state.json"
14
+ ],
13
15
  "attributes": {
14
16
  "taskSlug": "task_slug",
15
17
  "repo": "repo",
@@ -30,7 +32,9 @@
30
32
  "id": "flow-agents-acceptance",
31
33
  "label": "Acceptance criteria",
32
34
  "root": "product:flow-agents:.flow-agents",
33
- "files": ["acceptance.json"],
35
+ "files": [
36
+ "acceptance.json"
37
+ ],
34
38
  "attributes": {
35
39
  "taskSlug": "task_slug",
36
40
  "repo": "repo",
@@ -47,7 +51,9 @@
47
51
  "id": "flow-agents-evidence",
48
52
  "label": "Verification evidence",
49
53
  "root": "product:flow-agents:.flow-agents",
50
- "files": ["evidence.json"],
54
+ "files": [
55
+ "evidence.json"
56
+ ],
51
57
  "attributes": {
52
58
  "taskSlug": "task_slug",
53
59
  "repo": "repo",
@@ -67,7 +73,9 @@
67
73
  "id": "flow-agents-handoffs",
68
74
  "label": "Handoffs",
69
75
  "root": "product:flow-agents:.flow-agents",
70
- "files": ["handoff.json"],
76
+ "files": [
77
+ "handoff.json"
78
+ ],
71
79
  "attributes": {
72
80
  "taskSlug": "task_slug",
73
81
  "repo": "repo",
@@ -87,7 +95,9 @@
87
95
  "id": "flow-agents-learning",
88
96
  "label": "Learning records",
89
97
  "root": "product:flow-agents:.flow-agents",
90
- "files": ["learning.json"],
98
+ "files": [
99
+ "learning.json"
100
+ ],
91
101
  "attributes": {
92
102
  "taskSlug": "task_slug",
93
103
  "repo": "repo",
@@ -101,22 +111,75 @@
101
111
  }
102
112
  ],
103
113
  "facets": [
104
- { "id": "skills", "label": "Skills", "attribute": "skill", "limit": 16 },
105
- { "id": "tools", "label": "Tools", "attribute": "toolName", "limit": 16 },
106
- { "id": "flows", "label": "Flows", "attribute": "flow", "limit": 16 },
107
- { "id": "repositories", "label": "Repositories", "attribute": "repo", "limit": 16 },
108
- { "id": "projects", "label": "Projects", "attribute": "project", "limit": 16 },
109
- { "id": "runtimes", "label": "Runtimes", "attribute": "runtime", "limit": 12 },
110
- { "id": "agents", "label": "Agents", "attribute": "agent", "limit": 16 },
111
- { "id": "models", "label": "Models", "attribute": "model", "limit": 16 },
112
- { "id": "statuses", "label": "Statuses", "attribute": "status", "limit": 12 },
113
- { "id": "outcomes", "label": "Outcomes", "attribute": "outcome", "limit": 12 }
114
+ {
115
+ "id": "skills",
116
+ "label": "Skills",
117
+ "attribute": "skill",
118
+ "limit": 16
119
+ },
120
+ {
121
+ "id": "tools",
122
+ "label": "Tools",
123
+ "attribute": "toolName",
124
+ "limit": 16
125
+ },
126
+ {
127
+ "id": "flows",
128
+ "label": "Flows",
129
+ "attribute": "flow",
130
+ "limit": 16
131
+ },
132
+ {
133
+ "id": "repositories",
134
+ "label": "Repositories",
135
+ "attribute": "repo",
136
+ "limit": 16
137
+ },
138
+ {
139
+ "id": "projects",
140
+ "label": "Projects",
141
+ "attribute": "project",
142
+ "limit": 16
143
+ },
144
+ {
145
+ "id": "runtimes",
146
+ "label": "Runtimes",
147
+ "attribute": "runtime",
148
+ "limit": 12
149
+ },
150
+ {
151
+ "id": "agents",
152
+ "label": "Agents",
153
+ "attribute": "agent",
154
+ "limit": 16
155
+ },
156
+ {
157
+ "id": "models",
158
+ "label": "Models",
159
+ "attribute": "model",
160
+ "limit": 16
161
+ },
162
+ {
163
+ "id": "statuses",
164
+ "label": "Statuses",
165
+ "attribute": "status",
166
+ "limit": 12
167
+ },
168
+ {
169
+ "id": "outcomes",
170
+ "label": "Outcomes",
171
+ "attribute": "outcome",
172
+ "limit": 12
173
+ }
114
174
  ],
115
175
  "flows": [
116
176
  {
117
177
  "id": "builder.shape",
118
178
  "label": "Builder shape",
119
- "match": { "attribute": "flow", "includes": "builder.shape" },
179
+ "match": {
180
+ "attribute": "flow",
181
+ "includes": "builder.shape"
182
+ },
120
183
  "titleAttribute": "title",
121
184
  "detailAttributes": {
122
185
  "Project": "project",
@@ -135,7 +198,10 @@
135
198
  {
136
199
  "id": "builder.build",
137
200
  "label": "Builder build",
138
- "match": { "attribute": "flow", "includes": "builder.build" },
201
+ "match": {
202
+ "attribute": "flow",
203
+ "includes": "builder.build"
204
+ },
139
205
  "titleAttribute": "title",
140
206
  "detailAttributes": {
141
207
  "Project": "project",
@@ -154,22 +220,51 @@
154
220
  {
155
221
  "id": "delivery",
156
222
  "label": "Delivery workflows",
157
- "match": { "attribute": "skill", "includes": "deliver" },
223
+ "match": {
224
+ "attribute": "skill",
225
+ "includes": "deliver"
226
+ },
158
227
  "titleAttribute": "title",
159
228
  "limit": 10
160
229
  },
161
230
  {
162
231
  "id": "verification",
163
232
  "label": "Verification workflows",
164
- "match": { "attribute": "skill", "includes": "verify-work" },
233
+ "match": {
234
+ "attribute": "skill",
235
+ "includes": "verify-work"
236
+ },
165
237
  "titleAttribute": "title",
166
238
  "limit": 10
167
239
  },
168
240
  {
169
241
  "id": "review",
170
242
  "label": "Review workflows",
171
- "match": { "attribute": "skill", "includes": "review-work" },
243
+ "match": {
244
+ "attribute": "skill",
245
+ "includes": "review-work"
246
+ },
247
+ "titleAttribute": "title",
248
+ "limit": 10
249
+ },
250
+ {
251
+ "id": "knowledge",
252
+ "label": "Knowledge flows",
253
+ "match": {
254
+ "attribute": "flow",
255
+ "includes": "knowledge."
256
+ },
172
257
  "titleAttribute": "title",
258
+ "detailAttributes": {
259
+ "Project": "project",
260
+ "Repository": "repo",
261
+ "Task": "taskSlug",
262
+ "Status": "status",
263
+ "Outcome": "outcome",
264
+ "Agent": "agent",
265
+ "Runtime": "runtime",
266
+ "Observed": "observedAt"
267
+ },
173
268
  "limit": 10
174
269
  }
175
270
  ]
@@ -44,6 +44,8 @@
44
44
  <a href="{{ '/workflow-usage-guide.html' | relative_url }}">Workflow Guide</a>
45
45
  <a href="{{ '/agent-system-guidebook.html' | relative_url }}">System Guidebook</a>
46
46
  <a href="{{ '/skills-map.html' | relative_url }}">Workflow Map</a>
47
+ <a href="{{ '/kit-authoring-guide.html' | relative_url }}">Kit Authoring Guide</a>
48
+ <a href="{{ '/flow-kit-repository-contract.html' | relative_url }}">Kit Contract</a>
47
49
  <a href="{{ '/north-star.html' | relative_url }}">North Star</a>
48
50
  <a href="{{ '/sandbox-policy.html' | relative_url }}">Execution Safety</a>
49
51
  <a href="{{ '/veritas-integration.html' | relative_url }}">Governance Evidence</a>
package/docs/index.md CHANGED
@@ -106,6 +106,14 @@ Use fix-bug. Reproduce the problem, diagnose root cause, implement the fix, and
106
106
  <strong>Workflow Map</strong>
107
107
  <span>See the core skills, gates, artifacts, and route-back behavior.</span>
108
108
  </a>
109
+ <a class="doc-card" href="kit-authoring-guide.html">
110
+ <strong>Kit Authoring Guide</strong>
111
+ <span>Build your own Flow Kit from scratch: directory layout, kit.json, a flow file, validation, local install, and activation.</span>
112
+ </a>
113
+ <a class="doc-card" href="flow-kit-repository-contract.html">
114
+ <strong>Flow Kit Repository Contract</strong>
115
+ <span>Full validation rules, registry schema, activation diagnostics, and the install/update/force semantics.</span>
116
+ </a>
109
117
  <a class="doc-card" href="spec/runtime-hook-surface.html">
110
118
  <strong>Runtime Hook Surface</strong>
111
119
  <span>Canonical event taxonomy, four policy classes, conformance levels L0/L1/L2, and host mapping tables for adapter authors.</span>
@@ -45,6 +45,10 @@ The <a href="../spec/runtime-hook-surface.html">Runtime Hook Surface spec</a> de
45
45
  <strong>Runtime Hook Surface Spec</strong>
46
46
  <span>Canonical event taxonomy, four policy classes, conformance levels L0/L1/L2, mapping tables, and the engine contract for adapter authors.</span>
47
47
  </a>
48
+ <a class="doc-card" href="knowledge-kit-live.html">
49
+ <strong>Knowledge Kit Live Example</strong>
50
+ <span>End-to-end proof of the Knowledge Kit ingest + compile flows against a real Strands agent (OllamaModel / qwen3:1.7b). No API key required. Includes acceptance test with telemetry and provenance assertions.</span>
51
+ </a>
48
52
  </div>
49
53
 
50
54
  ---