@kontourai/flow-agents 0.1.2 → 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 (117) hide show
  1. package/.github/dependabot.yml +23 -0
  2. package/.github/workflows/release-please.yml +31 -0
  3. package/.github/workflows/runtime-compat.yml +118 -0
  4. package/CHANGELOG.md +46 -0
  5. package/CONTRIBUTING.md +4 -0
  6. package/README.md +80 -18
  7. package/build/src/cli/flow-kit.js +9 -4
  8. package/build/src/cli/init.js +215 -5
  9. package/build/src/cli/runtime-adapter.js +9 -5
  10. package/build/src/cli/telemetry-doctor.js +4 -1
  11. package/build/src/cli/utterance-check.js +65 -1
  12. package/build/src/runtime-adapters.js +34 -0
  13. package/build/src/tools/build-universal-bundles.js +285 -0
  14. package/build/src/tools/filter-installed-packs.js +3 -0
  15. package/build/src/tools/validate-source-tree.js +5 -1
  16. package/console.telemetry.json +115 -20
  17. package/context/scripts/telemetry/lib/config.sh +5 -1
  18. package/context/settings/flow-agents-settings.json +7 -0
  19. package/docs/_layouts/default.html +2 -0
  20. package/docs/context-map.md +1 -0
  21. package/docs/index.md +53 -4
  22. package/docs/integrations/conformance.md +246 -0
  23. package/docs/integrations/framework-adapter.md +275 -0
  24. package/docs/integrations/harness-install.md +213 -0
  25. package/docs/integrations/index.md +58 -0
  26. package/docs/integrations/knowledge-kit-live.md +211 -0
  27. package/docs/kit-authoring-guide.md +169 -0
  28. package/docs/north-star.md +2 -2
  29. package/docs/spec/runtime-hook-surface.md +525 -0
  30. package/docs/survey-utterance-check.md +211 -94
  31. package/docs/vision.md +45 -0
  32. package/evals/acceptance/run.sh +13 -2
  33. package/evals/acceptance/test_knowledge_kit_live.sh +221 -0
  34. package/evals/acceptance/test_opencode_harness.sh +121 -0
  35. package/evals/acceptance/test_pi_harness.sh +113 -0
  36. package/evals/integration/test_bundle_install.sh +226 -1
  37. package/evals/integration/test_bundle_lifecycle.sh +641 -0
  38. package/evals/integration/test_runtime_adapter_activation.sh +113 -1
  39. package/evals/integration/test_utterance_check.sh +291 -44
  40. package/evals/run.sh +2 -0
  41. package/evals/static/test_universal_bundles.sh +137 -2
  42. package/integrations/strands/README.md +256 -0
  43. package/integrations/strands/example.py +74 -0
  44. package/integrations/strands/examples/knowledge_kit_live.py +461 -0
  45. package/integrations/strands/flow_agents_strands/__init__.py +27 -0
  46. package/integrations/strands/flow_agents_strands/hooks.py +194 -0
  47. package/integrations/strands/flow_agents_strands/policy.py +348 -0
  48. package/integrations/strands/flow_agents_strands/steering.py +225 -0
  49. package/integrations/strands/flow_agents_strands/telemetry.py +238 -0
  50. package/integrations/strands/pyproject.toml +38 -0
  51. package/integrations/strands/tests/__init__.py +0 -0
  52. package/integrations/strands/tests/test_hooks.py +392 -0
  53. package/integrations/strands/tests/test_policy.py +315 -0
  54. package/integrations/strands/tests/test_telemetry.py +184 -0
  55. package/integrations/strands-ts/README.md +224 -0
  56. package/integrations/strands-ts/bin/conformance-shim.mjs +257 -0
  57. package/integrations/strands-ts/package.json +53 -0
  58. package/integrations/strands-ts/src/hooks.ts +312 -0
  59. package/integrations/strands-ts/src/index.ts +22 -0
  60. package/integrations/strands-ts/src/policy.ts +345 -0
  61. package/integrations/strands-ts/src/telemetry.ts +251 -0
  62. package/integrations/strands-ts/test/test-policy.ts +322 -0
  63. package/integrations/strands-ts/test/test-steering.ts +159 -0
  64. package/integrations/strands-ts/test/test-telemetry.ts +226 -0
  65. package/integrations/strands-ts/tsconfig.json +20 -0
  66. package/kits/catalog.json +6 -0
  67. package/kits/knowledge/adapters/default-store/index.js +821 -0
  68. package/kits/knowledge/adapters/flow-runner/index.js +1179 -0
  69. package/kits/knowledge/adapters/flow-runner/telemetry.js +174 -0
  70. package/kits/knowledge/docs/README.md +135 -0
  71. package/kits/knowledge/docs/store-contract.md +526 -0
  72. package/kits/knowledge/evals/consolidation/suite.test.js +1234 -0
  73. package/kits/knowledge/evals/contract-suite/suite.test.js +670 -0
  74. package/kits/knowledge/evals/ingest-compile/suite.test.js +574 -0
  75. package/kits/knowledge/evals/synthesis/suite.test.js +909 -0
  76. package/kits/knowledge/flows/compile.flow.json +60 -0
  77. package/kits/knowledge/flows/consolidate.flow.json +77 -0
  78. package/kits/knowledge/flows/ingest.flow.json +60 -0
  79. package/kits/knowledge/flows/store-contract.flow.json +48 -0
  80. package/kits/knowledge/flows/synthesize.flow.json +77 -0
  81. package/kits/knowledge/kit.json +78 -0
  82. package/package.json +7 -2
  83. package/packaging/conformance/README.md +142 -0
  84. package/packaging/conformance/fixtures/config-protection--allow-no-path.json +18 -0
  85. package/packaging/conformance/fixtures/config-protection--allow-safe-file.json +20 -0
  86. package/packaging/conformance/fixtures/config-protection--block-biome.json +20 -0
  87. package/packaging/conformance/fixtures/config-protection--block-eslintrc.json +20 -0
  88. package/packaging/conformance/fixtures/quality-gate--allow-no-path.json +17 -0
  89. package/packaging/conformance/fixtures/quality-gate--allow-nonexistent-file.json +19 -0
  90. package/packaging/conformance/fixtures/stop-goal-fit--allow-clean-cwd.json +17 -0
  91. package/packaging/conformance/fixtures/stop-goal-fit--block-strict-mode.json +23 -0
  92. package/packaging/conformance/fixtures/stop-goal-fit--warn-active-delivery.json +21 -0
  93. package/packaging/conformance/fixtures/workflow-steering--allow-no-state.json +16 -0
  94. package/packaging/conformance/fixtures/workflow-steering--inject-active-state.json +29 -0
  95. package/packaging/conformance/fixtures/workflow-steering--inject-subagent-steering.json +25 -0
  96. package/packaging/conformance/package.json +4 -0
  97. package/packaging/conformance/run-conformance.js +322 -0
  98. package/packaging/manifest.json +59 -0
  99. package/schemas/flow-agents-settings.schema.json +48 -0
  100. package/scripts/README.md +4 -0
  101. package/scripts/dogfood.js +16 -0
  102. package/scripts/hooks/opencode-hook-adapter.js +123 -0
  103. package/scripts/hooks/opencode-telemetry-hook.js +101 -0
  104. package/scripts/hooks/pi-hook-adapter.js +123 -0
  105. package/scripts/hooks/pi-telemetry-hook.js +105 -0
  106. package/scripts/hooks/run-hook.js +8 -0
  107. package/scripts/hooks/utterance-check.js +124 -22
  108. package/scripts/telemetry/lib/config.sh +5 -1
  109. package/src/cli/flow-kit.ts +10 -4
  110. package/src/cli/init.ts +219 -6
  111. package/src/cli/runtime-adapter.ts +10 -5
  112. package/src/cli/telemetry-doctor.ts +4 -1
  113. package/src/cli/utterance-check.ts +71 -1
  114. package/src/runtime-adapters.ts +35 -0
  115. package/src/tools/build-universal-bundles.ts +283 -0
  116. package/src/tools/filter-installed-packs.ts +3 -0
  117. package/src/tools/validate-source-tree.ts +5 -1
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Knowledge Kit — Telemetry Helper
3
+ *
4
+ * Emits canonical Flow Agents telemetry events (schema v0.3.0) to a JSONL
5
+ * sink file. Matches the event shape produced by telemetry.sh and the Python
6
+ * TelemetrySink in integrations/strands/flow_agents_strands/telemetry.py.
7
+ *
8
+ * Zero runtime dependencies beyond Node.js built-ins.
9
+ * Fails open: telemetry errors never block kit operations.
10
+ *
11
+ * Sink path: <workspace>/.telemetry/full.jsonl
12
+ * The workspace is resolved from FLOW_AGENTS_WORKSPACE env var, falling back
13
+ * to process.cwd().
14
+ *
15
+ * @module adapters/flow-runner/telemetry
16
+ */
17
+
18
+ import * as fs from "node:fs";
19
+ import * as path from "node:path";
20
+ import * as crypto from "node:crypto";
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Schema constants
24
+ // ---------------------------------------------------------------------------
25
+
26
+ const SCHEMA_VERSION = "0.3.0";
27
+
28
+ // Canonical event name → schema event_type (mirrors telemetry.sh schema_event_type())
29
+ const CANONICAL_TO_SCHEMA = {
30
+ agentSpawn: "session.start",
31
+ userPromptSubmit: "turn.user",
32
+ preToolUse: "tool.invoke",
33
+ permissionRequest: "tool.permission_request",
34
+ postToolUse: "tool.result",
35
+ stop: "session.end",
36
+ subagentStart: "agent.delegate",
37
+ subagentStop: "agent.delegate",
38
+ };
39
+
40
+ function schemaEventType(canonical) {
41
+ return CANONICAL_TO_SCHEMA[canonical] || "unknown";
42
+ }
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // Sink resolution
46
+ // ---------------------------------------------------------------------------
47
+
48
+ function resolveSinkPath(workspace) {
49
+ const ws = workspace || process.env.FLOW_AGENTS_WORKSPACE || process.cwd();
50
+ return path.join(ws, ".telemetry", "full.jsonl");
51
+ }
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // KnowledgeTelemetry
55
+ // ---------------------------------------------------------------------------
56
+
57
+ /**
58
+ * Thin telemetry sink for the Knowledge Kit flow runner.
59
+ *
60
+ * Usage:
61
+ * const tel = new KnowledgeTelemetry({ workspace: "/path/to/workspace" });
62
+ * tel.emitGate("knowledge.ingest", "classify-gate", { category: "research", record_id: id });
63
+ */
64
+ export class KnowledgeTelemetry {
65
+ /**
66
+ * @param {{ workspace?: string, agentName?: string, sessionId?: string }} options
67
+ */
68
+ constructor({ workspace, agentName, sessionId } = {}) {
69
+ this._sinkPath = resolveSinkPath(workspace);
70
+ this._agentName = agentName || "knowledge-kit";
71
+ this._sessionId = sessionId || crypto.randomUUID();
72
+
73
+ // Ensure the sink directory exists; fail open on error
74
+ try {
75
+ fs.mkdirSync(path.dirname(this._sinkPath), { recursive: true });
76
+ } catch {
77
+ // fail open
78
+ }
79
+ }
80
+
81
+ // -------------------------------------------------------------------------
82
+ // Core emit
83
+ // -------------------------------------------------------------------------
84
+
85
+ /**
86
+ * Build and append a canonical telemetry event to the JSONL sink.
87
+ * Returns the emitted event object (useful for tests).
88
+ * Fails open: never throws.
89
+ *
90
+ * @param {string} canonicalEvent - canonical event name (e.g. "preToolUse")
91
+ * @param {object} [extra] - additional fields merged into the event
92
+ * @returns {object} the emitted event
93
+ */
94
+ emit(canonicalEvent, extra) {
95
+ const schemaType = schemaEventType(canonicalEvent);
96
+ const event = {
97
+ schema_version: SCHEMA_VERSION,
98
+ timestamp: String(Date.now()),
99
+ session_id: this._sessionId,
100
+ event_id: crypto.randomUUID(),
101
+ event_type: schemaType,
102
+ agent: {
103
+ name: this._agentName,
104
+ runtime: "knowledge-kit",
105
+ version: "unknown",
106
+ },
107
+ hook: {
108
+ event_name: canonicalEvent,
109
+ runtime_session_id: "",
110
+ turn_id: "",
111
+ transcript_path: "",
112
+ model: "",
113
+ source: "knowledge-kit",
114
+ stop_hook_active: null,
115
+ last_assistant_message: "",
116
+ raw_input: null,
117
+ },
118
+ };
119
+
120
+ if (extra && typeof extra === "object") {
121
+ Object.assign(event, extra);
122
+ }
123
+
124
+ try {
125
+ fs.appendFileSync(this._sinkPath, JSON.stringify(event) + "\n", "utf8");
126
+ } catch {
127
+ // fail open — telemetry must never block kit operations
128
+ }
129
+
130
+ return event;
131
+ }
132
+
133
+ // -------------------------------------------------------------------------
134
+ // Semantic helpers
135
+ // -------------------------------------------------------------------------
136
+
137
+ /**
138
+ * Emit a gate event. Used at each flow gate point in the runner.
139
+ *
140
+ * @param {string} flowId - e.g. "knowledge.ingest"
141
+ * @param {string} gateId - e.g. "classify-gate"
142
+ * @param {object} [context] - gate-specific context payload
143
+ * @returns {object} the emitted event
144
+ */
145
+ emitGate(flowId, gateId, context) {
146
+ return this.emit("preToolUse", {
147
+ tool: {
148
+ name: `${flowId}.${gateId}`,
149
+ normalized_name: "flow.gate",
150
+ input: context || null,
151
+ },
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Emit a gate-result event.
157
+ *
158
+ * @param {string} flowId - e.g. "knowledge.ingest"
159
+ * @param {string} gateId - e.g. "classify-gate"
160
+ * @param {object} [result] - gate result payload
161
+ * @returns {object} the emitted event
162
+ */
163
+ emitGateResult(flowId, gateId, result) {
164
+ return this.emit("postToolUse", {
165
+ tool: {
166
+ name: `${flowId}.${gateId}`,
167
+ normalized_name: "flow.gate",
168
+ output: result || null,
169
+ },
170
+ });
171
+ }
172
+ }
173
+
174
+ export default KnowledgeTelemetry;
@@ -0,0 +1,135 @@
1
+ ---
2
+ title: Knowledge Kit
3
+ ---
4
+
5
+ # Knowledge Kit
6
+
7
+ A Flow Kit for durable, gated knowledge storage. The kit defines a store contract with precise
8
+ record types, mutation operations, and provenance requirements — then ships a default adapter
9
+ backed by markdown files, YAML frontmatter, `[[wikilink]]` inline links, and a JSON graph
10
+ index.
11
+
12
+ Any storage backend can adopt this kit by implementing the contract without forking kit flows.
13
+
14
+ ---
15
+
16
+ ## Contract Summary
17
+
18
+ See [`store-contract.md`](store-contract.md) for the full specification. Quick reference:
19
+
20
+ **Record types**
21
+
22
+ | Type | Purpose |
23
+ |---|---|
24
+ | `raw` | Unprocessed source material — excerpts, transcripts, URLs with notes. |
25
+ | `compiled` | Normalized, editor-reviewed distillations of raw records. |
26
+ | `concept` | Named ideas or principles that other records reference. |
27
+
28
+ **Mutation operations**
29
+
30
+ | Op | Required evidence fields |
31
+ |---|---|
32
+ | `create` | `type`, `title`, `body`, `category`, `provenance.agent` |
33
+ | `update` | `agent` (in evidence) + at least one mutable field |
34
+ | `link` | `agent`, non-empty `links` array |
35
+ | `propose` | `agent`, `proposal` (non-empty) |
36
+ | `apply` | `agent`, `new_body` (non-empty), `rationale` (non-empty) |
37
+ | `reject` | `agent`, `reason` (non-empty) |
38
+
39
+ Every mutation throws with `error.code === "MISSING_EVIDENCE"` when required evidence is absent.
40
+
41
+ ---
42
+
43
+ ## Running the Contract Suite
44
+
45
+ The contract suite is a `node:test` suite parameterized by adapter.
46
+
47
+ ### Default adapter (runs automatically)
48
+
49
+ ```bash
50
+ node --test kits/knowledge/evals/contract-suite/suite.test.js
51
+ ```
52
+
53
+ ### Alternative adapter
54
+
55
+ ```bash
56
+ KNOWLEDGE_ADAPTER=/path/to/my-adapter.js \
57
+ node --test kits/knowledge/evals/contract-suite/suite.test.js
58
+ ```
59
+
60
+ Or via CLI flag:
61
+
62
+ ```bash
63
+ node --test kits/knowledge/evals/contract-suite/suite.test.js \
64
+ -- --adapter=/path/to/my-adapter.js
65
+ ```
66
+
67
+ ### Expected output (default adapter)
68
+
69
+ All tests pass and exit 0. Any failure indicates a contract regression or an adapter gap.
70
+
71
+ ---
72
+
73
+ ## Acceptance Criteria Mapping
74
+
75
+ | AC | Requirement | Evidence |
76
+ |---|---|---|
77
+ | AC1 | Contract doc exists; mutation ops enumerate evidence fields. | [`docs/store-contract.md`](store-contract.md) — §6 covers all six ops with required-field tables. |
78
+ | AC2 | Default adapter passes contract suite (command evidence). | Run `node --test kits/knowledge/evals/contract-suite/suite.test.js` — exit 0, all tests pass. |
79
+ | AC3 | Record round-trips raw → stored → queried with category + links intact. | Suite §2 "create: round-trip raw → stored → queried" tests this directly. |
80
+
81
+ ---
82
+
83
+ ## Default Adapter Details
84
+
85
+ Located at `adapters/default-store/index.js`. Zero runtime dependencies; uses Node.js
86
+ built-ins only.
87
+
88
+ **Storage layout**
89
+
90
+ ```
91
+ <store_root>/
92
+ records/
93
+ <id>.md ← one markdown file per record, YAML frontmatter + body
94
+ graph-index.json ← forward + reverse link index, schema_version 1.0
95
+ ```
96
+
97
+ **Constructor**
98
+
99
+ ```js
100
+ import DefaultKnowledgeStore from './adapters/default-store/index.js';
101
+ const store = new DefaultKnowledgeStore({ storeRoot: '/path/to/store' });
102
+ ```
103
+
104
+ **Interface** (all methods return Promises):
105
+
106
+ - `create(input)` → `Promise<string>` (new id)
107
+ - `update(id, fields, evidence)` → `Promise<void>`
108
+ - `link(sourceId, links, evidence)` → `Promise<void>`
109
+ - `propose(conceptId, proposerId, evidence)` → `Promise<void>`
110
+ - `apply(conceptId, proposerId, evidence)` → `Promise<void>`
111
+ - `reject(conceptId, proposerId, evidence)` → `Promise<void>`
112
+ - `get(id)` → `Promise<Record | null>`
113
+ - `getLinks(id)` → `Promise<{ forward: Link[], reverse: Link[] }>`
114
+ - `listByCategory(category, options?)` → `Promise<Record[]>`
115
+ - `listByType(type)` → `Promise<Record[]>`
116
+
117
+ ---
118
+
119
+ ## Flow
120
+
121
+ The kit ships one flow:
122
+
123
+ **`knowledge.store-contract`** — gates on three evidence claims before a store implementation
124
+ is accepted: contract-suite pass, provenance-enforcement pass, and round-trip integrity pass.
125
+ S2 will add pipeline flows for raw ingestion, compilation, and concept management; this flow
126
+ and adapter infrastructure remain the foundation.
127
+
128
+ ---
129
+
130
+ ## Non-Goals (this iteration)
131
+
132
+ - Vector/semantic retrieval (parked as I10)
133
+ - Multi-user concurrency
134
+ - Store migrations
135
+ - Personal-KB import (parked as I11)