@kontourai/flow-agents 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-please.yml +13 -1
- package/AGENTS.md +8 -1
- package/CHANGELOG.md +18 -0
- package/evals/static/test_universal_bundles.sh +10 -0
- package/kits/knowledge/adapters/default-store/index.js +93 -12
- package/kits/knowledge/adapters/flow-runner/index.js +290 -0
- package/kits/knowledge/adapters/similarity-vector/index.js +284 -0
- package/kits/knowledge/docs/README.md +193 -0
- package/kits/knowledge/docs/store-contract.md +124 -0
- package/kits/knowledge/evals/contract-suite/suite.test.js +10 -5
- package/kits/knowledge/evals/retirement/suite.test.js +1173 -0
- package/kits/knowledge/evals/similarity-vector/suite.test.js +685 -0
- package/kits/knowledge/evals/synthesis/suite.test.js +10 -3
- package/kits/knowledge/flows/retire.flow.json +77 -0
- package/kits/knowledge/kit.json +21 -1
- package/package.json +1 -1
|
@@ -252,7 +252,11 @@ describe("AC2 — rejection leaves concept BYTE-IDENTICAL", () => {
|
|
|
252
252
|
"AC2: concept body is byte-identical after rejection"
|
|
253
253
|
);
|
|
254
254
|
|
|
255
|
-
// Also verify the body
|
|
255
|
+
// Also verify the body section in the markdown file is unchanged.
|
|
256
|
+
// Note: the mutation log now correctly serializes evidence (including the
|
|
257
|
+
// proposal text in the propose log entry). We verify the BODY field is
|
|
258
|
+
// unchanged, not the entire file — the mutation log is allowed to contain
|
|
259
|
+
// the proposal text as historical evidence.
|
|
256
260
|
const fileContent = fs.readFileSync(
|
|
257
261
|
path.join(dir, "records", `${conceptId}.md`),
|
|
258
262
|
"utf8"
|
|
@@ -261,9 +265,12 @@ describe("AC2 — rejection leaves concept BYTE-IDENTICAL", () => {
|
|
|
261
265
|
fileContent.includes("Initial definition of API design principles."),
|
|
262
266
|
"AC2: original body text is present in the backing file after rejection"
|
|
263
267
|
);
|
|
268
|
+
// The body section (after the final ---) must not contain the rejected proposal.
|
|
269
|
+
// Split on the closing frontmatter delimiter to get just the body portion.
|
|
270
|
+
const bodySection = fileContent.split("\n---\n").slice(-1)[0] || "";
|
|
264
271
|
assert.ok(
|
|
265
|
-
!
|
|
266
|
-
"AC2: proposed body text is NOT
|
|
272
|
+
!bodySection.includes("Rejected body — should never appear in concept."),
|
|
273
|
+
"AC2: proposed body text is NOT in the markdown body section after rejection"
|
|
267
274
|
);
|
|
268
275
|
});
|
|
269
276
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "knowledge.retire",
|
|
3
|
+
"version": "1.0",
|
|
4
|
+
"steps": [
|
|
5
|
+
{ "id": "identify", "next": "propose-retirement" },
|
|
6
|
+
{ "id": "propose-retirement", "next": "evidence-gate" },
|
|
7
|
+
{ "id": "evidence-gate", "next": "apply-or-reject" },
|
|
8
|
+
{ "id": "apply-or-reject", "next": "done" },
|
|
9
|
+
{ "id": "done", "next": null }
|
|
10
|
+
],
|
|
11
|
+
"gates": {
|
|
12
|
+
"identify-gate": {
|
|
13
|
+
"step": "identify",
|
|
14
|
+
"expects": [
|
|
15
|
+
{
|
|
16
|
+
"id": "target-record-found",
|
|
17
|
+
"kind": "surface.claim",
|
|
18
|
+
"required": true,
|
|
19
|
+
"description": "The record to be retired has been identified and is in a retirable status (active or implemented). The record ID and current status are surfaced for the proposal step.",
|
|
20
|
+
"claim": {
|
|
21
|
+
"type": "knowledge.retire.identify",
|
|
22
|
+
"subject": "artifact",
|
|
23
|
+
"accepted_statuses": ["trusted", "accepted"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"propose-retirement-gate": {
|
|
29
|
+
"step": "propose-retirement",
|
|
30
|
+
"expects": [
|
|
31
|
+
{
|
|
32
|
+
"id": "retirement-proposal-recorded",
|
|
33
|
+
"kind": "surface.claim",
|
|
34
|
+
"required": true,
|
|
35
|
+
"description": "A retirement proposal has been recorded. The proposal carries: the target status (implemented or retired), the retirement rationale, and — when targetStatus is 'implemented' — an implementedByRef pointing to the implementing artifact (commit SHA, PR URL, issue number, etc.). The record is NOT mutated at this step — only a retirement proposal record and proposes link are created.",
|
|
36
|
+
"claim": {
|
|
37
|
+
"type": "knowledge.retire.proposal",
|
|
38
|
+
"subject": "artifact",
|
|
39
|
+
"accepted_statuses": ["trusted", "accepted"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"evidence-gate": {
|
|
45
|
+
"step": "evidence-gate",
|
|
46
|
+
"expects": [
|
|
47
|
+
{
|
|
48
|
+
"id": "retirement-evidence-valid",
|
|
49
|
+
"kind": "surface.claim",
|
|
50
|
+
"required": true,
|
|
51
|
+
"description": "The retirement proposal evidence is valid: rationale is non-empty; implementedByRef is non-empty when targetStatus is 'implemented'; the target record exists and is in a state that allows the requested transition (active→implemented, active→retired, implemented→retired). Gate rejects if any required evidence field is missing or the transition is invalid.",
|
|
52
|
+
"claim": {
|
|
53
|
+
"type": "knowledge.retire.evidence",
|
|
54
|
+
"subject": "artifact",
|
|
55
|
+
"accepted_statuses": ["trusted", "accepted"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"apply-gate": {
|
|
61
|
+
"step": "apply-or-reject",
|
|
62
|
+
"expects": [
|
|
63
|
+
{
|
|
64
|
+
"id": "retirement-gate-decision",
|
|
65
|
+
"kind": "surface.claim",
|
|
66
|
+
"required": true,
|
|
67
|
+
"description": "A gate decision (apply or reject) has been recorded. If applied: the record status is updated to the target status via the store retire op; the retirement evidence (rationale, implementedByRef, supersededByRef) is appended to the mutation log; the record body, links, and provenance remain intact; the record is excluded from default working-set queries (listByType, listByCategory, similarity detection). If rejected: the record status is byte-identical to its pre-proposal state.",
|
|
68
|
+
"claim": {
|
|
69
|
+
"type": "knowledge.retire.gate-decision",
|
|
70
|
+
"subject": "artifact",
|
|
71
|
+
"accepted_statuses": ["trusted", "accepted"]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
package/kits/knowledge/kit.json
CHANGED
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"id": "knowledge.consolidate",
|
|
30
30
|
"path": "flows/consolidate.flow.json",
|
|
31
31
|
"description": "Consolidate related compiled records into a living decision snapshot: related-event trigger -> consolidation proposal -> evidence gate -> apply-or-reject. Creates or updates a snapshot record; supersedes prior snapshots via supersede op (never deletes). Reuses S3 mutation-gate machinery."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "knowledge.retire",
|
|
35
|
+
"path": "flows/retire.flow.json",
|
|
36
|
+
"description": "Retire implemented or obsolete records from the working set via gated lifecycle: identify \u2192 propose-retirement \u2192 evidence-gate \u2192 apply-or-reject. Evidence required: retirement rationale + implementedByRef (when targeting 'implemented' status) or supersededByRef (optional, for 'retired'). Rejection leaves record status byte-identical. Retired records remain fully queryable with provenance via includeRetired flag."
|
|
32
37
|
}
|
|
33
38
|
],
|
|
34
39
|
"docs": [
|
|
@@ -50,7 +55,12 @@
|
|
|
50
55
|
{
|
|
51
56
|
"id": "knowledge.flow-runner",
|
|
52
57
|
"path": "adapters/flow-runner/index.js",
|
|
53
|
-
"description": "Executable flow logic: capture(rawText, meta) \u2192 classified raw record; compile(rawIds[]) \u2192 compiled record with provenance links; synthesize(conceptId | topicSelector, options) \u2192 concept summary proposal with mutation gate; consolidate(snapshotId | topicSelector, options) \u2192 decision snapshot consolidation with supersede-not-delete. Emits canonical telemetry events at gate points."
|
|
58
|
+
"description": "Executable flow logic: capture(rawText, meta) \u2192 classified raw record; compile(rawIds[]) \u2192 compiled record with provenance links; synthesize(conceptId | topicSelector, options) \u2192 concept summary proposal with mutation gate; consolidate(snapshotId | topicSelector, options) \u2192 decision snapshot consolidation with supersede-not-delete; retire(recordId, options) \u2192 gated status lifecycle transition (active\u2192implemented\u2192retired) with working-set exclusion. Emits canonical telemetry events at gate points."
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "knowledge.similarity-vector",
|
|
62
|
+
"path": "adapters/similarity-vector/index.js",
|
|
63
|
+
"description": "Vector similarity detector: createVectorSimilarityDetector(options) returns a drop-in SimilarityDetector backed by dense embeddings and cosine similarity. Supports injectable embed fn (tests) or ollama /api/embed (default). Fail-closed: throws EMBED_FAILURE on infrastructure errors rather than silently masking them as empty clusters."
|
|
54
64
|
}
|
|
55
65
|
],
|
|
56
66
|
"evals": [
|
|
@@ -73,6 +83,16 @@
|
|
|
73
83
|
"id": "knowledge.consolidation-suite",
|
|
74
84
|
"path": "evals/consolidation/suite.test.js",
|
|
75
85
|
"description": "Eval cases for consolidate: AC1 (related event -> proposal, not mutation); AC2 (apply updates exactly ONE snapshot, links supersedes refs, superseded sources still queryable); AC3 fixture (decision changed across 3 events -> snapshot reflects ONLY latest decision, provenance to all 3); supersede-not-delete invariant; gate telemetry; contract suite extensions for snapshot semantics."
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"id": "knowledge.similarity-vector-suite",
|
|
89
|
+
"path": "evals/similarity-vector/suite.test.js",
|
|
90
|
+
"description": "Eval cases for the vector similarity adapter: unit tests (cosineSimilarity math, injectable embed, threshold, fail-closed), drop-in proof (runner.synthesize with injected embed produces valid proposals), and live-gated tests (real ollama nomic-embed-text round-trip \u2014 skipped when ollama unavailable)."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "knowledge.retirement-suite",
|
|
94
|
+
"path": "evals/retirement/suite.test.js",
|
|
95
|
+
"description": "Eval cases for retire: AC1 (retirement only via approved proposal with rationale/ref, transition table enforcement); AC2 (retired excluded from listByType/listByCategory/similarity defaults, returned with includeRetired flag, provenance intact via get()); AC3 (consolidation after retirement reflects pruned working set; retired record still reachable from snapshot provenance history); rejection leaves status byte-identical; gate telemetry."
|
|
76
96
|
}
|
|
77
97
|
]
|
|
78
98
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kontourai/flow-agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Flow Agents — a Kontour product that applies Flow and Veritas discipline as a portable process layer inside the agent tools you already use: Claude Code, Codex, Kiro, opencode, pi, and GitHub Actions — with framework adapters (AWS Strands preview) on the same policy-engine contract.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|