@kontourai/flow-agents 1.2.0 → 1.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.
Files changed (95) hide show
  1. package/.github/workflows/ci.yml +6 -1
  2. package/.github/workflows/kit-gates-demo.yml +6 -2
  3. package/CHANGELOG.md +33 -0
  4. package/CONTRIBUTING.md +30 -0
  5. package/agents/dev.json +1 -1
  6. package/agents/tool-planner.json +1 -1
  7. package/build/src/cli/console-learning-projection.d.ts +1 -0
  8. package/build/src/cli/effective-backlog-settings.d.ts +1 -0
  9. package/build/src/cli/fixture-retirement-audit.d.ts +2 -0
  10. package/build/src/cli/init.d.ts +17 -0
  11. package/build/src/cli/kit.d.ts +1 -0
  12. package/build/src/cli/promote-workflow-artifact.d.ts +1 -0
  13. package/build/src/cli/publish-change-helper.d.ts +1 -0
  14. package/build/src/cli/pull-work-provider.d.ts +1 -0
  15. package/build/src/cli/runtime-adapter.d.ts +1 -0
  16. package/build/src/cli/telemetry-doctor.d.ts +1 -0
  17. package/build/src/cli/usage-feedback.d.ts +1 -0
  18. package/build/src/cli/utterance-check.d.ts +1 -0
  19. package/build/src/cli/validate-hook-influence.d.ts +1 -0
  20. package/build/src/cli/validate-source-tree.d.ts +1 -0
  21. package/build/src/cli/validate-workflow-artifacts.d.ts +2 -0
  22. package/build/src/cli/veritas-governance.d.ts +1 -0
  23. package/build/src/cli/workflow-artifact-cleanup-audit.d.ts +1 -0
  24. package/build/src/cli/workflow-sidecar.d.ts +32 -0
  25. package/build/src/cli/workflow-sidecar.js +119 -22
  26. package/build/src/cli.d.ts +2 -0
  27. package/build/src/flow-kit/validate.d.ts +81 -0
  28. package/build/src/flow-kit/validate.js +32 -1
  29. package/build/src/index.d.ts +5 -0
  30. package/build/src/index.js +36 -0
  31. package/build/src/lib/args.d.ts +8 -0
  32. package/build/src/lib/fs.d.ts +7 -0
  33. package/build/src/lib/workflow-learning-projection.d.ts +132 -0
  34. package/build/src/runtime-adapters.d.ts +18 -0
  35. package/build/src/tools/build-universal-bundles.d.ts +2 -0
  36. package/build/src/tools/build-universal-bundles.js +14 -0
  37. package/build/src/tools/common.d.ts +9 -0
  38. package/build/src/tools/filter-installed-packs.d.ts +2 -0
  39. package/build/src/tools/generate-context-map.d.ts +2 -0
  40. package/build/src/tools/validate-package.d.ts +2 -0
  41. package/build/src/tools/validate-source-tree.d.ts +2 -0
  42. package/console.telemetry.json +1 -1
  43. package/docs/adr/0004-gates-expect-surface-claims.md +7 -7
  44. package/docs/developer-architecture.md +14 -0
  45. package/docs/kit-authoring-guide.md +99 -6
  46. package/docs/operating-layers.md +2 -2
  47. package/docs/spec/runtime-hook-surface.md +16 -1
  48. package/docs/veritas-integration.md +4 -4
  49. package/docs/workflow-eval-strategy.md +2 -2
  50. package/docs/workflow-usage-guide.md +1 -1
  51. package/evals/acceptance/test_opencode_harness.sh +18 -10
  52. package/evals/acceptance/test_pi_harness.sh +10 -6
  53. package/evals/ci/run-baseline.sh +1 -1
  54. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/flows/runtime.flow.json +4 -4
  55. package/evals/fixtures/flow-kit-repository/valid-local-kit/flows/review.flow.json +4 -4
  56. package/evals/fixtures/kit-conformance-levels/k0-flows-only/flows/review.flow.json +4 -4
  57. package/evals/fixtures/kit-conformance-levels/k1-agent-extension/flows/build.flow.json +4 -4
  58. package/evals/fixtures/kit-conformance-levels/k2-with-evals/flows/synthesize.flow.json +4 -4
  59. package/evals/fixtures/kit-conformance-levels/third-party-extension/flows/review.flow.json +4 -4
  60. package/evals/fixtures/surface-trust/accepted-claim-trust-report.json +2 -2
  61. package/evals/fixtures/surface-trust/artifact-absent.json +2 -2
  62. package/evals/fixtures/surface-trust/integrity-mismatch-trust-report.json +2 -2
  63. package/evals/fixtures/surface-trust/missing-authority-trust-report.json +2 -2
  64. package/evals/fixtures/surface-trust/provider-absent.json +2 -2
  65. package/evals/fixtures/surface-trust/rejected-claim-trust-report.json +2 -2
  66. package/evals/fixtures/surface-trust/stale-claim-trust-snapshot.json +2 -2
  67. package/evals/integration/test_console_learning_projection.sh +1 -1
  68. package/evals/integration/test_goal_fit_hook.sh +144 -0
  69. package/evals/integration/test_hook_category_behaviors.sh +14 -0
  70. package/evals/integration/test_kit_conformance_levels.sh +55 -1
  71. package/evals/integration/test_workflow_sidecar_writer.sh +9 -9
  72. package/evals/run.sh +2 -0
  73. package/evals/static/test_library_exports.sh +85 -0
  74. package/evals/static/test_package.sh +3 -3
  75. package/evals/static/test_universal_bundles.sh +15 -0
  76. package/evals/static/test_workflow_skills.sh +4 -4
  77. package/kits/builder/flows/build.flow.json +48 -48
  78. package/kits/builder/flows/shape.flow.json +36 -36
  79. package/kits/knowledge/adapters/obsidian-store/index.js +137 -26
  80. package/kits/knowledge/evals/contract-suite/suite.test.js +90 -0
  81. package/kits/knowledge/flows/compile.flow.json +12 -12
  82. package/kits/knowledge/flows/consolidate.flow.json +16 -16
  83. package/kits/knowledge/flows/ingest.flow.json +12 -12
  84. package/kits/knowledge/flows/retire.flow.json +16 -16
  85. package/kits/knowledge/flows/store-contract.flow.json +12 -12
  86. package/kits/knowledge/flows/synthesize.flow.json +16 -16
  87. package/kits/release-evidence/flows/release-evidence.flow.json +3 -3
  88. package/package.json +14 -2
  89. package/schemas/workflow-evidence.schema.json +2 -1
  90. package/scripts/hooks/stop-goal-fit.js +66 -18
  91. package/src/cli/workflow-sidecar.ts +101 -21
  92. package/src/flow-kit/validate.ts +55 -1
  93. package/src/index.ts +53 -0
  94. package/src/tools/build-universal-bundles.ts +14 -0
  95. package/tsconfig.json +1 -0
@@ -0,0 +1,81 @@
1
+ export type KitTargetConsumer = "flow" | "flow-agents" | string;
2
+ export interface KitConformanceLevel {
3
+ /** K0: valid core Flow Kit container with at least one flow (gates evaluable agentlessly). */
4
+ k0: boolean;
5
+ /** K1: K0 + at least one Flow Agents extension asset class present (skills/docs/adapters/evals/assets). */
6
+ k1: boolean;
7
+ /** K2: K1 + evals present (live evidence layer). */
8
+ k2: boolean;
9
+ }
10
+ /**
11
+ * Kit trust level — WHO vouches for a kit, orthogonal to the K-level capability axis.
12
+ *
13
+ * - "first-party": the kit is authored and published by Kontour (kontourai); its id is in the
14
+ * FIRST_PARTY_KIT_IDS allowlist maintained in this repository. These kits are built, tested,
15
+ * and distributed with the flow-agents package.
16
+ * - "verified": reserved for a future third-party verification process (e.g. self-certification
17
+ * via the conformance kit + cryptographic attestation / Veritas claims). Not yet implemented.
18
+ * - "unverified": default for all kits not in the first-party allowlist. This says nothing about
19
+ * the kit's quality — it only means Kontour has not vouched for it.
20
+ *
21
+ * The v2 path for "verified": cryptographic signing / attestation against the conformance kit
22
+ * and Veritas claims substrate is the natural next step and is intentionally deferred.
23
+ */
24
+ export type KitTrustLevel = "first-party" | "verified" | "unverified";
25
+ /**
26
+ * Allowlist of kit IDs that Kontour authors, tests, and ships with the flow-agents package.
27
+ *
28
+ * Criteria for inclusion:
29
+ * 1. The kit directory lives under kits/ in the kontourai/flow-agents repository.
30
+ * 2. The kit is published by @kontourai (npm package @kontourai/flow-agents).
31
+ * 3. Kontour owns and maintains the kit's content and release lifecycle.
32
+ *
33
+ * To add a new first-party kit: add its id here AND ensure it lives under kits/ in this repo.
34
+ * Third-party forks or community kits published elsewhere are NOT first-party, even if they
35
+ * share a similar id — first-party is tied to provenance in this specific repository.
36
+ */
37
+ export declare const FIRST_PARTY_KIT_IDS: ReadonlySet<string>;
38
+ /**
39
+ * Derive the trust level for a kit id.
40
+ *
41
+ * v1 determination: allowlist check against FIRST_PARTY_KIT_IDS.
42
+ * "verified" is reserved for future third-party verification (not yet granted to any kit).
43
+ */
44
+ export declare function deriveKitTrust(kitId: string): KitTrustLevel;
45
+ export interface KitTargetsResult {
46
+ kit_id: string;
47
+ kit_name: string;
48
+ conformance: KitConformanceLevel;
49
+ /** Derived consumer targets based on observable asset classes. */
50
+ targets: KitTargetConsumer[];
51
+ /** Extension field namespaces that are not Flow or Flow Agents-owned. */
52
+ third_party_extensions: string[];
53
+ /**
54
+ * Trust level: who vouches for this kit. Orthogonal to the K-level capability axis.
55
+ * "first-party" = Kontour-published; "verified" = reserved (future); "unverified" = default.
56
+ */
57
+ trust: KitTrustLevel;
58
+ }
59
+ /**
60
+ * Derives the consumer-target level (K0/K1/K2), target audience list, and trust level from
61
+ * observable asset classes in the kit manifest. Does not require file I/O.
62
+ *
63
+ * Derivation rules (from kontourai/flow-agents#52 and Brian's layering review):
64
+ * - K0: valid core container (schema_version, id, name, flows non-empty).
65
+ * - K1: K0 + any Flow Agents extension field present (skills/docs/adapters/evals/assets).
66
+ * - K2: K1 + evals present.
67
+ * - targets.flow: always present when K0 (any Flow consumer can evaluate gates).
68
+ * - targets.flow-agents: present when K1 (agent extension assets activate in >=1 harness).
69
+ * - third-party: any top-level keys that are not core fields and not Flow Agents extension classes.
70
+ *
71
+ * Trust derivation (from kontourai/flow-agents#79):
72
+ * - "first-party": kit id is in FIRST_PARTY_KIT_IDS (Kontour-authored kits in this repo).
73
+ * - "unverified": all other kits (default; "verified" is reserved for a future process).
74
+ *
75
+ * @param manifest The kit.json manifest object.
76
+ * @param kitDir Kit directory for flow file-existence checks. Defaults to "" (structural-only).
77
+ * Pass the real kit directory from `inspect` to get authoritative K0 validation.
78
+ */
79
+ export declare function deriveKitTargets(manifest: Record<string, unknown>, kitDir?: string): Promise<KitTargetsResult>;
80
+ export declare function validateKitRepository(kitDir: string): Promise<string[]>;
81
+ export declare function assertKitRepository(kitDir: string): Promise<Record<string, unknown>>;
@@ -7,6 +7,30 @@ const EXTENSION_ASSET_CLASSES = ["skills", "docs", "adapters", "evals", "assets"
7
7
  // agent-extension fields are skills, docs, adapters, evals, assets.
8
8
  const CORE_CONTAINER_FIELDS = new Set(["schema_version", "id", "name", "description", "product_name", "flows"]);
9
9
  const AGENT_EXTENSION_CLASSES = new Set(["skills", "docs", "adapters", "evals", "assets"]);
10
+ /**
11
+ * Allowlist of kit IDs that Kontour authors, tests, and ships with the flow-agents package.
12
+ *
13
+ * Criteria for inclusion:
14
+ * 1. The kit directory lives under kits/ in the kontourai/flow-agents repository.
15
+ * 2. The kit is published by @kontourai (npm package @kontourai/flow-agents).
16
+ * 3. Kontour owns and maintains the kit's content and release lifecycle.
17
+ *
18
+ * To add a new first-party kit: add its id here AND ensure it lives under kits/ in this repo.
19
+ * Third-party forks or community kits published elsewhere are NOT first-party, even if they
20
+ * share a similar id — first-party is tied to provenance in this specific repository.
21
+ */
22
+ export const FIRST_PARTY_KIT_IDS = new Set(["builder", "knowledge"]);
23
+ /**
24
+ * Derive the trust level for a kit id.
25
+ *
26
+ * v1 determination: allowlist check against FIRST_PARTY_KIT_IDS.
27
+ * "verified" is reserved for future third-party verification (not yet granted to any kit).
28
+ */
29
+ export function deriveKitTrust(kitId) {
30
+ if (FIRST_PARTY_KIT_IDS.has(kitId))
31
+ return "first-party";
32
+ return "unverified";
33
+ }
10
34
  let _validateKitContainerCache = null;
11
35
  async function loadValidateKitContainer() {
12
36
  if (_validateKitContainerCache)
@@ -49,7 +73,7 @@ async function delegateCoreContainerValidation(kitDir, manifest) {
49
73
  .map((d) => `${d.path}: ${d.message}`);
50
74
  }
51
75
  /**
52
- * Derives the consumer-target level (K0/K1/K2) and target audience list from
76
+ * Derives the consumer-target level (K0/K1/K2), target audience list, and trust level from
53
77
  * observable asset classes in the kit manifest. Does not require file I/O.
54
78
  *
55
79
  * Derivation rules (from kontourai/flow-agents#52 and Brian's layering review):
@@ -60,6 +84,10 @@ async function delegateCoreContainerValidation(kitDir, manifest) {
60
84
  * - targets.flow-agents: present when K1 (agent extension assets activate in >=1 harness).
61
85
  * - third-party: any top-level keys that are not core fields and not Flow Agents extension classes.
62
86
  *
87
+ * Trust derivation (from kontourai/flow-agents#79):
88
+ * - "first-party": kit id is in FIRST_PARTY_KIT_IDS (Kontour-authored kits in this repo).
89
+ * - "unverified": all other kits (default; "verified" is reserved for a future process).
90
+ *
63
91
  * @param manifest The kit.json manifest object.
64
92
  * @param kitDir Kit directory for flow file-existence checks. Defaults to "" (structural-only).
65
93
  * Pass the real kit directory from `inspect` to get authoritative K0 validation.
@@ -87,12 +115,15 @@ export async function deriveKitTargets(manifest, kitDir = "") {
87
115
  targets.push("flow-agents");
88
116
  for (const ns of thirdPartyExtensions)
89
117
  targets.push(ns);
118
+ // Derive trust level orthogonally to the K-level capability axis.
119
+ const trust = deriveKitTrust(kitId);
90
120
  return {
91
121
  kit_id: kitId,
92
122
  kit_name: kitName,
93
123
  conformance: { k0, k1, k2 },
94
124
  targets,
95
125
  third_party_extensions: thirdPartyExtensions,
126
+ trust,
96
127
  };
97
128
  }
98
129
  export async function validateKitRepository(kitDir) {
@@ -0,0 +1,5 @@
1
+ export { validateTrustBundle, normalizeCheck, normalizeFinding, normalizeLearning, normalizeEvidenceRefs, validateEvidenceRef, validateLearningCorrection, loadJson, writeJson, appendJsonl, sidecarBase, writeState, statuses, phases, checkKinds, checkStatuses, verdicts, } from "./cli/workflow-sidecar.js";
2
+ /** Read a sidecar JSON file from a workflow artifact directory; returns `{}` if absent. */
3
+ export declare function readSidecar(dir: string, name: string): Record<string, any>;
4
+ /** Write a sidecar JSON file into a workflow artifact directory (pretty-printed, trailing newline). */
5
+ export declare function writeSidecar(dir: string, name: string, payload: Record<string, any>): void;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Public library surface for `@kontourai/flow-agents`.
3
+ *
4
+ * Native orchestration hosts can import the canonical workflow-sidecar
5
+ * writer/validator here instead of shelling out to the
6
+ * `flow-agents-workflow-sidecar` CLI or reimplementing validated
7
+ * read / merge / write of workflow evidence. This is the same code the CLI
8
+ * runs — importing it does not execute the CLI.
9
+ *
10
+ * The sidecar JSON Schemas ship under `schemas/` and can be validated against
11
+ * directly; the helpers below are the canonical writer/validator that produce
12
+ * and check conforming artifacts.
13
+ *
14
+ * @module
15
+ */
16
+ import * as path from "node:path";
17
+ import { loadJson as _loadJson, writeJson as _writeJson } from "./cli/workflow-sidecar.js";
18
+ export {
19
+ // Trust-bundle (Hachure) validation — the same validator the writer uses.
20
+ validateTrustBundle,
21
+ // Evidence / check / learning validation + normalization. These throw on
22
+ // invalid input (with the same messages the CLI surfaces) and return the
23
+ // normalized object on success.
24
+ normalizeCheck, normalizeFinding, normalizeLearning, normalizeEvidenceRefs, validateEvidenceRef, validateLearningCorrection,
25
+ // Sidecar read / merge / write primitives.
26
+ loadJson, writeJson, appendJsonl, sidecarBase, writeState,
27
+ // Schema vocabularies (the allowed status/phase/kind values).
28
+ statuses, phases, checkKinds, checkStatuses, verdicts, } from "./cli/workflow-sidecar.js";
29
+ /** Read a sidecar JSON file from a workflow artifact directory; returns `{}` if absent. */
30
+ export function readSidecar(dir, name) {
31
+ return _loadJson(path.join(dir, name));
32
+ }
33
+ /** Write a sidecar JSON file into a workflow artifact directory (pretty-printed, trailing newline). */
34
+ export function writeSidecar(dir, name, payload) {
35
+ _writeJson(path.join(dir, name), payload);
36
+ }
@@ -0,0 +1,8 @@
1
+ export type ParsedArgs = {
2
+ positionals: string[];
3
+ flags: Record<string, string | boolean | string[]>;
4
+ };
5
+ export declare function parseArgs(argv: string[]): ParsedArgs;
6
+ export declare function flagString(flags: ParsedArgs["flags"], key: string, fallback?: string): string | undefined;
7
+ export declare function flagBool(flags: ParsedArgs["flags"], key: string): boolean;
8
+ export declare function flagList(flags: ParsedArgs["flags"], key: string): string[];
@@ -0,0 +1,7 @@
1
+ export declare function readJson(file: string): unknown;
2
+ export declare function writeJson(file: string, value: unknown): void;
3
+ export declare function copyDir(src: string, dest: string): void;
4
+ export declare function assertPathContained(root: string, target: string): void;
5
+ export declare function walkFiles(root: string): string[];
6
+ export declare function relPath(root: string, file: string): string;
7
+ export declare function isoNow(): string;
@@ -0,0 +1,132 @@
1
+ export type WorkflowLearningStatus = "pending" | "learned" | "followup_required" | "blocked";
2
+ export type WorkflowLearningOutcome = "success" | "failure" | "mixed" | "unknown";
3
+ export type WorkflowLearningRouteTarget = "rule" | "skill" | "power" | "agent" | "eval" | "doc" | "backlog" | "knowledge" | "none";
4
+ export type WorkflowLearningRouteStatus = "open" | "completed" | "accepted" | "deferred" | "rejected";
5
+ export type WorkflowLearningCorrectionType = "workflow" | "skill" | "agent" | "tooling" | "test" | "doc" | "process" | "product" | "provider" | "none";
6
+ export type WorkflowLearningRoute = {
7
+ target: WorkflowLearningRouteTarget;
8
+ status: WorkflowLearningRouteStatus;
9
+ ref?: string;
10
+ };
11
+ export type WorkflowLearningCorrection = {
12
+ needed: boolean;
13
+ type?: WorkflowLearningCorrectionType;
14
+ recurrence_key?: string;
15
+ intended_behavior?: string;
16
+ observed_behavior?: string;
17
+ gap?: string;
18
+ evidence?: string;
19
+ no_change_rationale?: string;
20
+ prevention?: WorkflowLearningRoute;
21
+ };
22
+ export type WorkflowLearningRecord = {
23
+ id: string;
24
+ recorded_at: string;
25
+ source_refs: string[];
26
+ outcome: WorkflowLearningOutcome;
27
+ facts: string[];
28
+ interpretation: string;
29
+ routing: WorkflowLearningRoute[];
30
+ correction?: WorkflowLearningCorrection;
31
+ };
32
+ export type WorkflowLearningSidecar = {
33
+ schema_version: "1.0";
34
+ task_slug: string;
35
+ status: WorkflowLearningStatus;
36
+ updated_at: string;
37
+ records: WorkflowLearningRecord[];
38
+ };
39
+ export type WorkflowLearningSource = {
40
+ path: string;
41
+ relativePath: string;
42
+ slug: string;
43
+ learning: WorkflowLearningSidecar;
44
+ };
45
+ export type ConsoleProjectionRef = {
46
+ product: string;
47
+ kind: string;
48
+ id: string;
49
+ label?: string;
50
+ };
51
+ export type ConsoleProjectionScope = {
52
+ kind: string;
53
+ id: string;
54
+ };
55
+ export type ConsoleLearningProjection = {
56
+ id: string;
57
+ family: "workflow";
58
+ nonAuthority: true;
59
+ subjectRef: ConsoleProjectionRef;
60
+ sourceRef: ConsoleProjectionRef;
61
+ summary: string;
62
+ extensions: {
63
+ "flow-agents": {
64
+ task_slug: string;
65
+ record_id: string;
66
+ source_refs: string[];
67
+ routing: {
68
+ count: number;
69
+ open: number;
70
+ completed: number;
71
+ accepted: number;
72
+ deferred: number;
73
+ rejected: number;
74
+ targets: WorkflowLearningRouteTarget[];
75
+ statuses: WorkflowLearningRouteStatus[];
76
+ refs: string[];
77
+ };
78
+ correction: {
79
+ needed: boolean;
80
+ type?: WorkflowLearningCorrectionType;
81
+ recurrence_key?: string;
82
+ prevention?: {
83
+ target: WorkflowLearningRouteTarget;
84
+ status: WorkflowLearningRouteStatus;
85
+ ref?: string;
86
+ };
87
+ };
88
+ outcome: WorkflowLearningOutcome;
89
+ learning_status: WorkflowLearningStatus;
90
+ recorded_at: string;
91
+ updated_at: string;
92
+ source_path: string;
93
+ };
94
+ };
95
+ };
96
+ export type ConsoleLearningProjectionEnvelope = {
97
+ schema: "kontour.console.projection";
98
+ version: "0.1";
99
+ generatedAt: string;
100
+ scope: ConsoleProjectionScope;
101
+ producer: {
102
+ id: string;
103
+ product: "flow-agents";
104
+ };
105
+ derivedFrom: {
106
+ mode: "direct_snapshot";
107
+ eventHistory: "unavailable";
108
+ directSnapshot: {
109
+ id: string;
110
+ emittedAt: string;
111
+ producer: {
112
+ id: string;
113
+ product: "flow-agents";
114
+ };
115
+ reason: string;
116
+ sourceRef: ConsoleProjectionRef;
117
+ };
118
+ };
119
+ learnings: ConsoleLearningProjection[];
120
+ };
121
+ export type BuildWorkflowLearningProjectionOptions = {
122
+ scope: string | ConsoleProjectionScope;
123
+ generatedAt?: string;
124
+ producer?: {
125
+ id?: string;
126
+ product?: "flow-agents";
127
+ };
128
+ };
129
+ export declare function readWorkflowLearningSources(artifactRoot: string): WorkflowLearningSource[];
130
+ export declare function buildWorkflowLearningProjection(sources: WorkflowLearningSource[], options: BuildWorkflowLearningProjectionOptions): ConsoleLearningProjectionEnvelope;
131
+ export declare function validateWorkflowLearningProjectionSourceShape(value: unknown, label?: string): WorkflowLearningSidecar;
132
+ export declare const validateWorkflowLearningSidecar: typeof validateWorkflowLearningProjectionSourceShape;
@@ -0,0 +1,18 @@
1
+ export type KitAsset = {
2
+ kit_id: string;
3
+ kit_name: string;
4
+ asset_class: string;
5
+ asset_id: string | null;
6
+ relative_path: string;
7
+ source_path: string;
8
+ source_kind: string;
9
+ description?: string;
10
+ };
11
+ export type KitInventory = {
12
+ assets: KitAsset[];
13
+ warnings: string[];
14
+ errors: string[];
15
+ };
16
+ export declare function readKitInventory(sourceRoot: string, dest: string): KitInventory;
17
+ export declare function activateCodexLocal(sourceRoot: string, dest: string): Record<string, unknown>;
18
+ export declare function activateStrandsLocal(sourceRoot: string, dest: string): Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(): number;
@@ -470,6 +470,7 @@ function exportOpencodePlugin() {
470
470
 
471
471
  import { spawnSync } from 'node:child_process';
472
472
  import { join, basename } from 'node:path';
473
+ import { mkdirSync, writeFileSync } from 'node:fs';
473
474
 
474
475
  // opencode runs plugins inside its own compiled (Bun-based) binary, so
475
476
  // process.execPath points at opencode itself — spawning it with a script
@@ -480,6 +481,19 @@ const NODE_BIN = basename(process.execPath).startsWith('node') ? process.execPat
480
481
  export const FlowAgentsPlugin = async ({ project, client, $, directory, worktree }) => {
481
482
  const root = directory || process.cwd();
482
483
 
484
+ // Deterministic load marker. opencode invokes this factory at startup but
485
+ // does not reliably surface plugin console output to its log file, and its
486
+ // internal "loading plugin" message was dropped in opencode 1.17.x. Write a
487
+ // marker into the workspace telemetry dir so acceptance tests can confirm the
488
+ // plugin loaded without depending on opencode internals. Best-effort only.
489
+ try {
490
+ const telemetryDir = join(root, '.telemetry');
491
+ mkdirSync(telemetryDir, { recursive: true });
492
+ writeFileSync(join(telemetryDir, 'opencode-plugin.loaded'), 'flow-agents');
493
+ } catch (_err) {
494
+ // Marker is diagnostic only; never block plugin load on a write failure.
495
+ }
496
+
483
497
  // The hook scripts read the event payload from stdin; an empty stdin makes
484
498
  // the telemetry pipeline silently skip the emit (fail-open), so every spawn
485
499
  // must pass a payload (caught by live acceptance smoke 2026-06-11).
@@ -0,0 +1,9 @@
1
+ export declare const root: string;
2
+ export declare function rel(file: string): string;
3
+ export declare function readText(file: string): string;
4
+ export declare function writeText(file: string, text: string): void;
5
+ export declare function loadJson<T = unknown>(file: string): T;
6
+ export declare function exists(file: string): boolean;
7
+ export declare function walkFiles(dir: string): string[];
8
+ export declare function oneLine(value: string, limit?: number): string;
9
+ export declare function markdownTable(headers: string[], rows: string[][]): string[];
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(argv?: string[]): number;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(argv?: string[]): number;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(argv?: string[]): number;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(argv?: string[]): number;
@@ -49,7 +49,7 @@
49
49
  },
50
50
  {
51
51
  "id": "flow-agents-evidence",
52
- "label": "Verification evidence",
52
+ "label": "Verification evidence (trust-backed refs use Hachure trust.bundle format when present)",
53
53
  "root": "product:flow-agents:.flow-agents",
54
54
  "files": [
55
55
  "evidence.json"
@@ -1,15 +1,15 @@
1
1
  ---
2
- title: ADR 0004: Gates Expect Surface Claims
2
+ title: ADR 0004: Gates Expect Hachure Trust Bundles
3
3
  ---
4
4
 
5
- # ADR 0004: Gates Expect Surface Claims
5
+ # ADR 0004: Gates Expect Hachure Trust Bundles
6
6
 
7
- Flow-backed kits will model rich gate evidence as claim expectations rather than provider-specific requirements. A gate expectation can require `kind: "surface.claim"`, a Surface claim type such as `repo.policy_compliance`, accepted trust statuses such as `verified`, and whether the expectation blocks the transition; project or runtime config maps claim types to trusted Surface producers and authority traces. This lets the Builder Kit use repo governance, command checks, CI, human decisions, or future producers without naming a specific provider in the Flow Definition.
7
+ Flow-backed kits will model rich gate evidence as claim expectations using the Hachure trust.bundle format rather than provider-specific requirements. A gate expectation can require `kind: "trust.bundle"`, a domain claim type such as `builder.verify.tests`, accepted trust statuses such as `verified`, and whether the expectation blocks the transition; project or runtime config maps claim types to trusted Surface producers and authority traces. This lets the Builder Kit use repo governance, command checks, CI, human decisions, or future producers without naming a specific provider in the Flow Definition.
8
8
 
9
- **Status**: Accepted
9
+ **Status**: Accepted (updated: vocabulary aligned to Hachure trust.bundle in hachure-align)
10
10
 
11
- **Considered Options**: Provider-aware gate rules were rejected because they would make Flow Definitions know too much about individual tools. Plain evidence strings such as `tests` or `veritas` were rejected because they cannot represent claim type, accepted status, producer authority, transparency gaps, or project-level enforcement overrides cleanly.
11
+ **Considered Options**: Provider-aware gate rules were rejected because they would make Flow Definitions know too much about individual tools. Plain evidence strings such as `tests` or `veritas` were rejected because they cannot represent claim type, accepted status, producer authority, transparency gaps, or project-level enforcement overrides cleanly. An earlier version used `kind: "surface.claim"` and `artifact_kind: "TrustReport"/"Trust Snapshot"` — those have been renamed to `kind: "trust.bundle"` and `artifact_kind: "trust.bundle"` to align with the Hachure schema standard that Flow now ships.
12
12
 
13
- **Consequences**: Trusted producer mappings belong upstream in Flow project configuration, not Flow Agents runtime configuration. Flow Agents can help author, install, and adapt that configuration for agent runtimes, but CI, framework agents, local CLIs, and humans should all evaluate gates against the same Flow-owned authority model.
13
+ **Consequences**: Trusted producer mappings belong upstream in Flow project configuration, not Flow Agents runtime configuration. Flow Agents can help author, install, and adapt that configuration for agent runtimes, but CI, framework agents, local CLIs, and humans should all evaluate gates against the same Flow-owned authority model. When hachure is installed as an optional dependency, referenced trust artifacts are validated against hachure's trust-bundle.schema.json at evidence-recording time.
14
14
 
15
- **Initial Shape**: Gate expectations should use `expects` entries with `id`, `kind: "surface.claim"`, `required`, `claim.type`, optional `claim.subject`, `claim.accepted_statuses`, `description`, and optional `explore_hint`. The Builder Kit should use intuitive subject strings such as `flow-run`, `flow-step`, `work-item`, `change`, `pull-request`, `release`, `decision`, and `artifact`, while the schema remains open to other subject values.
15
+ **Initial Shape**: Gate expectations should use `expects` entries with `id`, `kind: "trust.bundle"`, `required`, `claim.type`, optional `claim.subject`, `claim.accepted_statuses`, `description`, and optional `explore_hint`. The Builder Kit should use intuitive subject strings such as `flow-run`, `flow-step`, `work-item`, `change`, `pull-request`, `release`, `decision`, and `artifact`, while the schema remains open to other subject values.
@@ -108,6 +108,20 @@ flowchart TB
108
108
 
109
109
  **Current state:** The durable handoff surface is a pair of human-readable Markdown artifacts and machine-readable JSON sidecars under `.flow-agents/<slug>/`. Verification, critique, release, and learning records are explicit artifacts rather than hidden chat memory.
110
110
 
111
+ **Programmatic API (for native hosts):** The canonical sidecar writer/validator is importable as a library, not only via the `flow-agents-workflow-sidecar` CLI. A host that records workflow evidence natively should import the package root rather than reimplement validated read / merge / write:
112
+
113
+ ```js
114
+ import {
115
+ validateTrustBundle, // Hachure trust.bundle validation (the writer's validator)
116
+ normalizeCheck, // validate + normalize an evidence check (throws on invalid)
117
+ normalizeLearning, // validate + normalize a learning record
118
+ validateEvidenceRef, // validate a structured evidence reference
119
+ readSidecar, writeSidecar, sidecarBase, writeState,
120
+ } from "@kontourai/flow-agents";
121
+ ```
122
+
123
+ This is the same code the CLI runs; importing it does not execute the CLI. The sidecar JSON Schemas under `schemas/` remain the normative shape.
124
+
111
125
  **Future direction:** Durable workflow state should converge toward Kontour Resource Contracts with versioned identity, desired state, observed status, and condition summaries. That convergence should preserve local files and provider-backed records as first-class surfaces.
112
126
 
113
127
  ## Local Workflow Roles
@@ -74,12 +74,12 @@ A Flow Definition at minimum needs `id`, `version`, `steps`, and `gates`. Steps
74
74
  "expects": [
75
75
  {
76
76
  "id": "review-finding",
77
- "kind": "surface.claim",
77
+ "kind": "trust.bundle",
78
78
  "required": true,
79
79
  "description": "The change was reviewed and findings were recorded.",
80
- "claim": {
81
- "type": "my-kit.review.finding",
82
- "subject": "artifact",
80
+ "bundle_claim": {
81
+ "claimType": "my-kit.review.finding",
82
+ "subjectType": "artifact",
83
83
  "accepted_statuses": ["trusted", "accepted"]
84
84
  }
85
85
  }
@@ -270,7 +270,7 @@ Version constraints (e.g. minimum `flow-agents` version) are the only case where
270
270
 
271
271
  ### Evidence layering: Surface and Veritas
272
272
 
273
- Kit gates reference evidence using `"kind": "surface.claim"`. This is **Flow-native vocabulary**: Flow is built on Surface, so Surface claims are the expected evidence substrate at the Flow level. Surface claims are not a Flow Agents coupling.
273
+ Kit gates reference evidence using `"kind": "trust.bundle"` with a `bundle_claim` selector (`claimType`, optional `subjectType`, `accepted_statuses`). This is **Flow-native vocabulary** in the Hachure open trust-bundle format: Flow is built on Surface, so trust bundles are the expected evidence substrate at the Flow level, validated against Hachure's `trust-bundle.schema.json`. They are not a Flow Agents coupling. (Earlier Flow releases used `kind: "surface.claim"` with a `claim` selector; Flow 1.3.0 replaced that with `trust.bundle`, kontourai/flow#84.)
274
274
 
275
275
  Veritas is an **optional claim family** — a developer-repo specialization for evidence that has been through a trust pipeline. Kits may be opinionated about requiring Veritas-class evidence. Builder Kit requiring Veritas-class evidence is the kit's own policy choice, defined by Kontour as the kit author, not a platform requirement. Other kits may not require Veritas at all.
276
276
 
@@ -299,7 +299,8 @@ Output is stable JSON:
299
299
  "k2": false
300
300
  },
301
301
  "targets": ["flow", "flow-agents"],
302
- "third_party_extensions": []
302
+ "third_party_extensions": [],
303
+ "trust": "unverified"
303
304
  }
304
305
  ```
305
306
 
@@ -307,6 +308,98 @@ Exit code 0 when the kit is at least K0 (valid core container); exit code 1 when
307
308
 
308
309
  The `inspect` command is read-only and safe to run before install.
309
310
 
311
+ ## Trust axis: who vouches for a kit
312
+
313
+ The **trust axis** is a separate, orthogonal classification from the K-level capability axis. It answers the question "who vouches for this kit?" rather than "what does this kit contain?".
314
+
315
+ ### Two orthogonal axes
316
+
317
+ Every kit carries two independent badges:
318
+
319
+ | Axis | Values | Question answered |
320
+ |---|---|---|
321
+ | **Capability** (K-level) | K0 / K1 / K2 | What does the kit CONTAIN? (derived from assets) |
322
+ | **Trust** | first-party / verified / unverified | WHO vouches for it? (derived from provenance) |
323
+
324
+ A K2 kit can be `unverified`. A K0 kit can be `first-party`. The levels are independent.
325
+
326
+ **Marketplace listing format**: `Works with: Flow (gates-only) | K1 | ✓ First-party`
327
+
328
+ ### Trust levels
329
+
330
+ | Level | Meaning | How it is assigned (v1) |
331
+ |---|---|---|
332
+ | `first-party` | Kontour authored, tested, and ships this kit in the `@kontourai/flow-agents` package. | Kit id is in the internal FIRST_PARTY_KIT_IDS allowlist in `src/flow-kit/validate.ts`. |
333
+ | `verified` | Reserved for a future third-party verification process. | Not yet implemented; the value is reserved but not granted to any kit today. |
334
+ | `unverified` | Default for all kits not explicitly vouched for. | All other kits, including third-party community kits. |
335
+
336
+ `unverified` says nothing about the quality of a kit — it only means Kontour has not vouched for it through one of the above channels.
337
+
338
+ ### First-party kits (v1)
339
+
340
+ The first-party allowlist in v1 contains the kits authored by Kontour and distributed with the flow-agents package:
341
+
342
+ - `builder` — Builder Kit (shape, build, and deliver work)
343
+ - `knowledge` — Knowledge Kit (durable gated knowledge store)
344
+
345
+ Criteria for a kit to be first-party:
346
+ 1. Its directory lives under `kits/` in the `kontourai/flow-agents` repository.
347
+ 2. It is published as part of the `@kontourai/flow-agents` npm package.
348
+ 3. Kontour owns and maintains the kit's content and release lifecycle.
349
+
350
+ Third-party forks, community kits, or kits published under a different npm package are NOT first-party even if they share a similar id. First-party is tied to provenance in this specific repository and package.
351
+
352
+ ### Deferred: verified trust and cryptographic attestation (v2)
353
+
354
+ The `verified` value is reserved for a future verification process. The intended v2 path:
355
+
356
+ - Third-party kit authors can apply for `verified` status.
357
+ - Verification evidence: the kit passes the conformance kit self-certification + a cryptographic signature or Veritas attestation.
358
+ - The [conformance kit](https://github.com/kontourai/flow) and [Veritas claims](veritas-integration.md) are the natural substrate for this attestation layer.
359
+ - The signature or attestation would be checked by `flow-agents kit inspect` at derivation time.
360
+
361
+ v1 deliberately omits the signing/attestation mechanism and the verification process. The `verified` value is reserved so consuming tools can handle it when it arrives without a breaking schema change.
362
+
363
+ ### Inspecting trust
364
+
365
+ The `trust` field appears in `flow-agents kit inspect` output alongside `conformance`:
366
+
367
+ ```bash
368
+ npm run kit -- inspect kits/builder
369
+ ```
370
+
371
+ ```json
372
+ {
373
+ "kit_id": "builder",
374
+ "kit_name": "Builder Kit",
375
+ "conformance": {
376
+ "k0": true,
377
+ "k1": true,
378
+ "k2": false
379
+ },
380
+ "targets": ["flow", "flow-agents"],
381
+ "third_party_extensions": [],
382
+ "trust": "first-party"
383
+ }
384
+ ```
385
+
386
+ A third-party kit inspected before verification:
387
+
388
+ ```json
389
+ {
390
+ "kit_id": "my-custom-kit",
391
+ "kit_name": "My Custom Kit",
392
+ "conformance": {
393
+ "k0": true,
394
+ "k1": true,
395
+ "k2": false
396
+ },
397
+ "targets": ["flow", "flow-agents"],
398
+ "third_party_extensions": [],
399
+ "trust": "unverified"
400
+ }
401
+ ```
402
+
310
403
  ## Direction
311
404
 
312
405
  Flow Kits are designed to be shareable workflow units — authored once, carried across teams and workspaces. The intended growth path is distribution from git remotes and a curated Kontour kit catalog of Kontour-authored kits covering work modes beyond software delivery. Today install is local-path only; remote fetch is explicitly a non-goal in this version.
@@ -49,7 +49,7 @@ Governance tools such as Veritas belong at the Evidence boundary. Flow Agents sh
49
49
 
50
50
  ## Flow Kit Coordination
51
51
 
52
- Flow owns Flow Definition semantics: gates use typed `expects` entries, Surface requirements use `kind: "surface.claim"`, and project configuration owns trusted producer mappings plus gate overrides. Flow Agents should author, install, adapt, and control those assets for local runtimes; it should not become the authority source for claim trust or override semantics.
52
+ Flow owns Flow Definition semantics: gates use typed `expects` entries, Surface requirements use `kind: "trust.bundle"` (the Hachure-aligned gate kind), and project configuration owns trusted producer mappings plus gate overrides. Flow Agents should author, install, adapt, and control those assets for local runtimes; it should not become the authority source for claim trust or override semantics.
53
53
 
54
54
  The Kit Catalog is the Flow Agents index of installable Flow Kits. A Flow Kit can contain Flow Definitions, skills, docs, adapters, and evals, but the catalog points at those assets instead of defining gate behavior itself. Builder Kit is the first Kontour-authored kit and proves the path from shaping through build, verification, merge readiness, and learning.
55
55
 
@@ -65,7 +65,7 @@ Builder Kit vocabulary should be used in public and internal guidance:
65
65
  - Builder Kit: the coding/building kit shipped by this repo.
66
66
  - Probe: question-driven design and context challenge step, surfaced as `design-probe`.
67
67
 
68
- Builder Kit evidence gates can reference Surface trust state without naming a provider. A trust-backed gate may attach a TrustReport or Trust Snapshot ref for the relevant Surface claim, while Flow keeps authority over gate evaluation, trusted producer mapping, and route-back behavior. Surface remains the portable trust-state layer, and Veritas remains an optional producer rather than a required Builder Kit dependency.
68
+ Builder Kit evidence gates can reference Surface trust state without naming a provider. A trust-backed gate may attach a Hachure trust.bundle ref for the relevant Surface claim, while Flow keeps authority over gate evaluation, trusted producer mapping, and route-back behavior. Surface remains the portable trust-state layer, and Veritas remains an optional producer rather than a required Builder Kit dependency.
69
69
 
70
70
  ## Placement Rules
71
71