@kontourai/flow-agents 3.3.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/add-to-project.yml +15 -0
- package/.github/workflows/ci.yml +161 -0
- package/CHANGELOG.md +48 -0
- package/CONTEXT.md +5 -1
- package/README.md +19 -8
- package/build/src/builder-flow-run-adapter.d.ts +80 -0
- package/build/src/builder-flow-run-adapter.js +241 -0
- package/build/src/builder-flow-runtime.d.ts +16 -0
- package/build/src/builder-flow-runtime.js +290 -0
- package/build/src/cli/builder-run.d.ts +1 -0
- package/build/src/cli/builder-run.js +27 -0
- package/build/src/cli/effective-backlog-settings.js +70 -2
- package/build/src/cli/init.d.ts +34 -0
- package/build/src/cli/init.js +341 -61
- package/build/src/cli/kit.js +55 -12
- package/build/src/cli/pull-work-provider.js +346 -5
- package/build/src/cli/skill-drift-check.d.ts +1 -0
- package/build/src/cli/skill-drift-check.js +165 -0
- package/build/src/cli/telemetry-doctor.d.ts +37 -0
- package/build/src/cli/telemetry-doctor.js +53 -6
- package/build/src/cli/validate-hook-influence.js +37 -7
- package/build/src/cli/workflow-sidecar.d.ts +93 -8
- package/build/src/cli/workflow-sidecar.js +1175 -158
- package/build/src/cli.js +5 -0
- package/build/src/flow-kit/validate.d.ts +54 -34
- package/build/src/flow-kit/validate.js +237 -26
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/lib/console-connect-options.d.ts +97 -0
- package/build/src/lib/console-connect-options.js +199 -0
- package/build/src/lib/console-telemetry-validate.d.ts +49 -0
- package/build/src/lib/console-telemetry-validate.js +91 -0
- package/build/src/lib/flow-resolver.d.ts +56 -3
- package/build/src/lib/flow-resolver.js +151 -11
- package/build/src/lib/fs.d.ts +17 -0
- package/build/src/lib/fs.js +172 -0
- package/build/src/lib/local-artifact-root.d.ts +44 -1
- package/build/src/lib/local-artifact-root.js +131 -3
- package/build/src/runtime-adapters.d.ts +39 -3
- package/build/src/runtime-adapters.js +77 -31
- package/build/src/tools/build-universal-bundles.js +40 -2
- package/build/src/tools/codex-agent-routing.d.ts +2 -0
- package/build/src/tools/codex-agent-routing.js +49 -0
- package/build/src/tools/generate-context-map.js +1 -0
- package/build/src/tools/validate-source-tree.js +27 -1
- package/context/scripts/hooks/lib/kit-catalog.js +235 -0
- package/context/scripts/hooks/lib/runnable-command.js +177 -0
- package/context/scripts/hooks/stop-goal-fit.js +278 -48
- package/context/scripts/hooks/workflow-steering.js +121 -21
- package/context/scripts/package.json +3 -0
- package/context/scripts/telemetry/install-console-config.sh +25 -4
- package/context/scripts/telemetry/lib/config.sh +102 -12
- package/context/scripts/telemetry/lib/pricing.sh +50 -0
- package/context/scripts/telemetry/lib/session.sh +3 -0
- package/context/scripts/telemetry/lib/transport.sh +87 -0
- package/context/scripts/telemetry/lib/usage.sh +205 -4
- package/context/scripts/telemetry/telemetry.conf +6 -0
- package/context/scripts/telemetry/telemetry.sh +48 -0
- package/context/settings/workspace-backlog-provider-settings.example.json +48 -0
- package/docs/agent-usage-feedback-loop.md +35 -0
- package/docs/architecture-engine-and-kits.md +110 -0
- package/docs/context-map.md +2 -0
- package/docs/decisions/embeddable-engine.md +152 -0
- package/docs/decisions/index.md +3 -1
- package/docs/decisions/trust-ledger-retention.md +88 -0
- package/docs/decisions/workflow-enforcement.md +31 -9
- package/docs/fixture-ownership.md +3 -0
- package/docs/implementing-trust-reconciliation.md +129 -0
- package/docs/index.md +19 -9
- package/docs/integrations/flow-agents-console.md +167 -0
- package/docs/kit-authoring-guide.md +52 -21
- package/docs/spec/builder-flow-runtime.md +80 -0
- package/docs/spec/runtime-hook-surface.md +45 -1
- package/docs/specs/economics-record-contract.md +270 -0
- package/docs/specs/harness-capability-matrix.md +74 -0
- package/docs/specs/learning-review-proposals-contract.md +340 -0
- package/docs/specs/routing-efficiency-review.md +59 -0
- package/docs/verifiable-trust.md +74 -25
- package/docs/workflow-usage-guide.md +10 -0
- package/evals/acceptance/prove-capture-teeth.sh +132 -0
- package/evals/ci/antigaming-suite.sh +1 -0
- package/evals/ci/run-baseline.sh +72 -4
- package/evals/fixtures/economics/acceptance.json +12 -0
- package/evals/fixtures/economics/agents/tool-worker-1/events.jsonl +2 -0
- package/evals/fixtures/economics/agents/tool-worker-2/events.jsonl +2 -0
- package/evals/fixtures/economics/agents/tool-worker-3/events.jsonl +2 -0
- package/evals/fixtures/economics/agents/tool-worker-4/events.jsonl +1 -0
- package/evals/fixtures/economics/agents/tool-worker-5/events.jsonl +2 -0
- package/evals/fixtures/economics/critique.json +22 -0
- package/evals/fixtures/economics/expected-record.json +71 -0
- package/evals/fixtures/economics/session-usage-event.json +1 -0
- package/evals/fixtures/economics/state.json +11 -0
- package/evals/fixtures/economics/transcript.jsonl +3 -0
- package/evals/fixtures/hook-influence/cases.json +7 -7
- package/evals/fixtures/learning-review-proposals/balanced/economics.jsonl +6 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/economics.jsonl +5 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-1/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-2/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-3/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-4/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-5/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/economics.jsonl +6 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.json +30 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.md +66 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/gate-review.inquiries.json +26 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-5/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-6/trust.bundle +21 -0
- package/evals/fixtures/learning-review-proposals/repeat-window/economics.jsonl +6 -0
- package/evals/fixtures/learning-review-proposals/under-threshold/economics.jsonl +3 -0
- package/evals/fixtures/telemetry/usage-transcript-sample.jsonl +4 -0
- package/evals/fixtures/trust-reconcile-exploits/mcp-degrade.json +42 -0
- package/evals/integration/test_builder_entry_enforcement.sh +241 -0
- package/evals/integration/test_builder_step_producers.sh +18 -10
- package/evals/integration/test_bundle_install.sh +172 -0
- package/evals/integration/test_console_tenant_isolation.sh +167 -0
- package/evals/integration/test_critique_supersession_roundtrip.sh +4 -1
- package/evals/integration/test_dual_emit_flow_step.sh +10 -4
- package/evals/integration/test_economics_record.sh +674 -0
- package/evals/integration/test_effective_backlog_settings.sh +1 -1
- package/evals/integration/test_evidence_capture_hook.sh +17 -2
- package/evals/integration/test_exemption_usage_review.sh +198 -0
- package/evals/integration/test_fixture_retirement_audit.sh +2 -2
- package/evals/integration/test_flow_kit_install_git.sh +83 -0
- package/evals/integration/test_flowdef_session_activation.sh +0 -1
- package/evals/integration/test_flowdef_session_history_preservation.sh +13 -3
- package/evals/integration/test_gate_lockdown.sh +7 -0
- package/evals/integration/test_gate_review_inquiry_records.sh +9 -1
- package/evals/integration/test_goal_fit_hook.sh +2031 -0
- package/evals/integration/test_hook_category_behaviors.sh +8 -1
- package/evals/integration/test_hook_influence_cases.sh +25 -1
- package/evals/integration/test_install_merge.sh +227 -2
- package/evals/integration/test_kit_conformance_levels.sh +6 -6
- package/evals/integration/test_learning_review_proposals.sh +329 -0
- package/evals/integration/test_liveness_conflict_injection.sh +26 -22
- package/evals/integration/test_liveness_console_relay.sh +166 -0
- package/evals/integration/test_liveness_heartbeat.sh +17 -17
- package/evals/integration/test_liveness_worktree_root.sh +575 -0
- package/evals/integration/test_phase_map_and_gate_claim.sh +6 -1
- package/evals/integration/test_publish_delivery.sh +331 -1
- package/evals/integration/test_pull_work_board.sh +200 -0
- package/evals/integration/test_pull_work_provider.sh +1 -1
- package/evals/integration/test_record_check.sh +378 -0
- package/evals/integration/test_routing_efficiency.sh +71 -0
- package/evals/integration/test_runtime_adapter_activation.sh +28 -0
- package/evals/integration/test_session_resume_roundtrip.sh +16 -19
- package/evals/integration/test_skill_drift_check.sh +870 -0
- package/evals/integration/test_telemetry.sh +445 -0
- package/evals/integration/test_telemetry_doctor.sh +66 -0
- package/evals/integration/test_telemetry_usage_pipeline.sh +228 -0
- package/evals/integration/test_trust_reconcile_negatives.sh +30 -13
- package/evals/integration/test_trust_reconcile_trailer_diagnostic.sh +247 -0
- package/evals/integration/test_usage_cost.sh +61 -0
- package/evals/integration/test_workflow_sidecar_writer.sh +1395 -0
- package/evals/integration/test_workflow_steering_hook.sh +157 -16
- package/evals/integration/test_workspace_settings.sh +176 -0
- package/evals/lib/env.sh +26 -0
- package/evals/lib/node.sh +8 -0
- package/evals/run.sh +29 -0
- package/evals/static/test_ci_integration_coverage.sh +115 -0
- package/evals/static/test_declared_scope_forms_documented.sh +114 -0
- package/evals/static/test_universal_bundles.sh +34 -0
- package/evals/static/test_validate_source_kit_asset_scope.sh +259 -0
- package/evals/static/test_workflow_skills.sh +1 -1
- package/kits/builder/flows/build.flow.json +9 -18
- package/kits/builder/flows/publish-learn.flow.json +5 -1
- package/kits/builder/kit.json +120 -0
- package/kits/builder/skills/deliver/SKILL.md +42 -0
- package/kits/builder/skills/evidence-gate/SKILL.md +12 -0
- package/kits/builder/skills/execute-plan/SKILL.md +9 -0
- package/kits/builder/skills/learning-review/SKILL.md +51 -0
- package/kits/builder/skills/plan-work/SKILL.md +17 -20
- package/kits/builder/skills/pull-work/SKILL.md +21 -0
- package/kits/builder/skills/release-readiness/SKILL.md +12 -0
- package/kits/knowledge/kit.json +9 -0
- package/kits/veritas-governance/docs/README.md +35 -7
- package/kits/veritas-governance/fixtures/exemption-review/mixed-fresh-stale.DECLARED.json +14 -0
- package/kits/veritas-governance/kit.json +14 -0
- package/kits/veritas-governance/skills/exemption-usage-review/SKILL.md +128 -0
- package/kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs +231 -0
- package/package.json +2 -2
- package/packaging/manifest.json +29 -0
- package/schemas/backlog-provider-settings.schema.json +13 -0
- package/schemas/workflow-state.schema.json +44 -0
- package/scripts/README.md +4 -0
- package/scripts/check-content-boundary.cjs +8 -1
- package/scripts/ci/trust-reconcile.js +136 -0
- package/scripts/hooks/codex-hook-adapter.js +77 -2
- package/scripts/hooks/evidence-capture.js +38 -5
- package/scripts/hooks/lib/codex-exit-code.js +316 -0
- package/scripts/hooks/lib/kit-catalog.js +235 -0
- package/scripts/hooks/lib/liveness-write.js +28 -1
- package/scripts/hooks/lib/local-artifact-paths.js +97 -1
- package/scripts/hooks/lib/runnable-command.js +177 -0
- package/scripts/hooks/lib/skill-drift.js +350 -0
- package/scripts/hooks/stop-goal-fit.js +278 -48
- package/scripts/hooks/workflow-steering.js +121 -21
- package/scripts/install-codex-home.sh +97 -47
- package/scripts/install-merge.js +72 -14
- package/scripts/install-owned-files.js +178 -0
- package/scripts/liveness/relay.sh +84 -0
- package/scripts/telemetry/economics-record.schema.json +145 -0
- package/scripts/telemetry/economics-record.sh +331 -0
- package/scripts/telemetry/install-console-config.sh +25 -4
- package/scripts/telemetry/learning-review-decide.sh +124 -0
- package/scripts/telemetry/learning-review-proposals.schema.json +161 -0
- package/scripts/telemetry/learning-review-proposals.sh +484 -0
- package/scripts/telemetry/lib/config.sh +102 -12
- package/scripts/telemetry/lib/pricing.sh +14 -6
- package/scripts/telemetry/lib/session.sh +3 -0
- package/scripts/telemetry/lib/transport.sh +133 -15
- package/scripts/telemetry/lib/usage.sh +121 -28
- package/scripts/telemetry/routing-efficiency.sh +0 -0
- package/scripts/telemetry/telemetry.conf +6 -0
- package/scripts/telemetry/telemetry.sh +48 -0
- package/src/builder-flow-run-adapter.ts +357 -0
- package/src/builder-flow-runtime.ts +348 -0
- package/src/cli/builder-flow-run-adapter.test.mjs +495 -0
- package/src/cli/builder-flow-runtime.test.mjs +213 -0
- package/src/cli/builder-run.ts +28 -0
- package/src/cli/codex-agent-routing.test.mjs +44 -0
- package/src/cli/codex-exit-code.test.mjs +207 -0
- package/src/cli/console-connect-options.test.mjs +329 -0
- package/src/cli/console-telemetry-validate.test.mjs +157 -0
- package/src/cli/effective-backlog-settings.ts +68 -2
- package/src/cli/flow-resolver-composition.test.mjs +101 -0
- package/src/cli/init.test.mjs +161 -0
- package/src/cli/init.ts +407 -62
- package/src/cli/kit-metadata-security.test.mjs +443 -0
- package/src/cli/kit.ts +50 -12
- package/src/cli/pull-work-provider.ts +377 -3
- package/src/cli/sidecar-pure-helpers.test.mjs +64 -0
- package/src/cli/skill-drift-check.ts +196 -0
- package/src/cli/telemetry-doctor.test.mjs +53 -0
- package/src/cli/telemetry-doctor.ts +50 -7
- package/src/cli/validate-hook-influence.ts +37 -6
- package/src/cli/workflow-sidecar.ts +1150 -151
- package/src/cli.ts +5 -0
- package/src/flow-kit/validate.ts +277 -38
- package/src/index.ts +19 -0
- package/src/lib/console-connect-options.ts +261 -0
- package/src/lib/console-telemetry-validate.ts +88 -0
- package/src/lib/flow-resolver.ts +153 -10
- package/src/lib/fs.ts +160 -0
- package/src/lib/local-artifact-root.ts +129 -3
- package/src/runtime-adapters.ts +113 -33
- package/src/tools/build-universal-bundles.ts +36 -2
- package/src/tools/codex-agent-routing.ts +48 -0
- package/src/tools/generate-context-map.ts +1 -0
- package/src/tools/validate-source-tree.ts +26 -1
package/src/cli.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { basename } from "node:path";
|
|
|
3
3
|
import { main as effectiveBacklogSettings } from "./cli/effective-backlog-settings.js";
|
|
4
4
|
import { main as effectiveAssignmentProviderSettings } from "./cli/effective-assignment-provider-settings.js";
|
|
5
5
|
import { main as assignmentProvider } from "./cli/assignment-provider.js";
|
|
6
|
+
import { main as builderRun } from "./cli/builder-run.js";
|
|
6
7
|
import { main as consoleLearningProjection } from "./cli/console-learning-projection.js";
|
|
7
8
|
import { main as kit } from "./cli/kit.js";
|
|
8
9
|
import { main as fixtureRetirementAudit } from "./cli/fixture-retirement-audit.js";
|
|
@@ -20,11 +21,13 @@ import { main as validateSource } from "./tools/validate-source-tree.js";
|
|
|
20
21
|
import { main as validatePackage } from "./tools/validate-package.js";
|
|
21
22
|
import { main as validateHookInfluence } from "./cli/validate-hook-influence.js";
|
|
22
23
|
import { main as runtimeAdapter } from "./cli/runtime-adapter.js";
|
|
24
|
+
import { main as skillDriftCheck } from "./cli/skill-drift-check.js";
|
|
23
25
|
import { main as utteranceCheck } from "./cli/utterance-check.js";
|
|
24
26
|
import { main as verify } from "./cli/verify.js";
|
|
25
27
|
|
|
26
28
|
const availableCommands = new Map<string, (argv: string[]) => number | Promise<number>>([
|
|
27
29
|
["build-bundles", () => buildBundles()],
|
|
30
|
+
["builder-run", builderRun],
|
|
28
31
|
["console-learning-projection", consoleLearningProjection],
|
|
29
32
|
["context-map", contextMap],
|
|
30
33
|
["assignment-provider", assignmentProvider],
|
|
@@ -37,6 +40,7 @@ const availableCommands = new Map<string, (argv: string[]) => number | Promise<n
|
|
|
37
40
|
["publish-change", publishChange],
|
|
38
41
|
["pull-work-provider", pullWorkProvider],
|
|
39
42
|
["runtime-adapter", runtimeAdapter],
|
|
43
|
+
["skill-drift-check", skillDriftCheck],
|
|
40
44
|
["utterance-check", utteranceCheck],
|
|
41
45
|
["telemetry-doctor", telemetryDoctor],
|
|
42
46
|
["usage-feedback", usageFeedback],
|
|
@@ -61,6 +65,7 @@ const aliases = new Map<string, string>([
|
|
|
61
65
|
["flow-agents-publish-change", "publish-change"],
|
|
62
66
|
["flow-agents-pull-work-provider", "pull-work-provider"],
|
|
63
67
|
["flow-agents-runtime-adapter", "runtime-adapter"],
|
|
68
|
+
["flow-agents-skill-drift-check", "skill-drift-check"],
|
|
64
69
|
["flow-agents-telemetry-doctor", "telemetry-doctor"],
|
|
65
70
|
["flow-agents-usage-feedback", "usage-feedback"],
|
|
66
71
|
["flow-agents-veritas-governance", "veritas-governance"],
|
package/src/flow-kit/validate.ts
CHANGED
|
@@ -13,14 +13,44 @@ const AGENT_EXTENSION_CLASSES = new Set(["skills", "docs", "adapters", "evals",
|
|
|
13
13
|
// Flow Agents-recognized metadata fields that are neither core container fields nor
|
|
14
14
|
// agent-extension asset classes. Recognized here so they are never misreported as
|
|
15
15
|
// unknown third-party extension namespaces. `dependencies` declares cross-kit skill
|
|
16
|
-
// dependencies (extension-layer ownership; see docs/adr/0019-kit-dependency-ownership.md)
|
|
17
|
-
|
|
16
|
+
// dependencies (extension-layer ownership; see docs/adr/0019-kit-dependency-ownership.md),
|
|
17
|
+
// workflow_triggers / hook_influence_expectations declare kit-owned runtime influence,
|
|
18
|
+
// and first_party is legacy catalog/marketplace metadata. It does not grant runtime
|
|
19
|
+
// capability or steering privilege.
|
|
20
|
+
const KNOWN_METADATA_FIELDS = new Set(["dependencies", "workflow_triggers", "hook_influence_expectations", "flow_step_actions", "first_party"]);
|
|
18
21
|
|
|
19
22
|
export interface KitDependencyEntry {
|
|
20
23
|
kit_id: string;
|
|
21
24
|
reason?: string;
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
export interface KitWorkflowTriggerEntry {
|
|
28
|
+
id: string;
|
|
29
|
+
when: string;
|
|
30
|
+
target_flow_id?: string;
|
|
31
|
+
default_skill?: string;
|
|
32
|
+
conditional_skills?: { when: string; skill: string }[];
|
|
33
|
+
required_sequence?: string[];
|
|
34
|
+
post_verify_targets?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface KitHookInfluenceExpectationEntry {
|
|
38
|
+
id: string;
|
|
39
|
+
description: string;
|
|
40
|
+
tier: string;
|
|
41
|
+
hook?: string;
|
|
42
|
+
event?: string;
|
|
43
|
+
must_include_guidance: string[];
|
|
44
|
+
must_include_actions: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface KitFlowStepActionEntry {
|
|
48
|
+
flow_id: string;
|
|
49
|
+
step_id: string;
|
|
50
|
+
skills: string[];
|
|
51
|
+
operations: string[];
|
|
52
|
+
}
|
|
53
|
+
|
|
24
54
|
/**
|
|
25
55
|
* Parse and shape-validate a kit manifest's `dependencies` field (Flow Agents
|
|
26
56
|
* extension-layer metadata; see docs/adr/0019-kit-dependency-ownership.md).
|
|
@@ -76,6 +106,222 @@ export function parseKitDependencies(manifest: Record<string, unknown>, manifest
|
|
|
76
106
|
return { entries, errors };
|
|
77
107
|
}
|
|
78
108
|
|
|
109
|
+
function nonEmptyStringList(value: unknown): value is string[] {
|
|
110
|
+
return Array.isArray(value) && value.length > 0 && value.every((item) => typeof item === "string" && item.trim().length > 0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const WORKFLOW_TRIGGER_IDENTIFIER_RE = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
|
|
114
|
+
|
|
115
|
+
function workflowTriggerIdentifier(value: unknown): value is string {
|
|
116
|
+
return typeof value === "string" && WORKFLOW_TRIGGER_IDENTIFIER_RE.test(value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function optionalWorkflowTriggerIdentifier(value: unknown): value is string | undefined {
|
|
120
|
+
return value === undefined || workflowTriggerIdentifier(value);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function optionalWorkflowTriggerIdentifierList(value: unknown): value is string[] | undefined {
|
|
124
|
+
return value === undefined || (Array.isArray(value) && value.length > 0 && value.every(workflowTriggerIdentifier));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function optionalConditionalSkills(value: unknown): value is { when: string; skill: string }[] | undefined {
|
|
128
|
+
return value === undefined ||
|
|
129
|
+
(Array.isArray(value) && value.every((item) =>
|
|
130
|
+
typeof item === "object" && item !== null &&
|
|
131
|
+
workflowTriggerIdentifier((item as Record<string, unknown>).when) &&
|
|
132
|
+
workflowTriggerIdentifier((item as Record<string, unknown>).skill)
|
|
133
|
+
));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function parseKitWorkflowTriggers(manifest: Record<string, unknown>, manifestPath: string): { entries: KitWorkflowTriggerEntry[]; errors: string[] } {
|
|
137
|
+
const entries: KitWorkflowTriggerEntry[] = [];
|
|
138
|
+
const errors: string[] = [];
|
|
139
|
+
const raw = manifest.workflow_triggers;
|
|
140
|
+
if (raw === undefined) return { entries, errors };
|
|
141
|
+
if (!Array.isArray(raw)) {
|
|
142
|
+
errors.push(`${manifestPath}: .workflow_triggers must be a list`);
|
|
143
|
+
return { entries, errors };
|
|
144
|
+
}
|
|
145
|
+
const seen = new Set<string>();
|
|
146
|
+
raw.forEach((entry, index) => {
|
|
147
|
+
if (typeof entry !== "object" || entry === null) {
|
|
148
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}] must be an object`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const record = entry as Record<string, unknown>;
|
|
152
|
+
const id = record.id;
|
|
153
|
+
const when = record.when;
|
|
154
|
+
if (!workflowTriggerIdentifier(id)) {
|
|
155
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].id must match ^[a-z0-9]+(?:[.-][a-z0-9]+)*$`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (seen.has(id)) errors.push(`${manifestPath}: workflow_triggers[${index}].id duplicates '${id}'`);
|
|
159
|
+
seen.add(id);
|
|
160
|
+
if (!workflowTriggerIdentifier(when)) {
|
|
161
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].when must match ^[a-z0-9]+(?:[.-][a-z0-9]+)*$`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (record.hint !== undefined) {
|
|
165
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].hint is retired; use structured steering fields`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (record.display_name !== undefined) {
|
|
169
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].display_name is not supported in workflow_triggers; use catalog/listing metadata for human-readable names`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (!optionalWorkflowTriggerIdentifier(record.target_flow_id)) {
|
|
173
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].target_flow_id must match ^[a-z0-9]+(?:[.-][a-z0-9]+)*$ when present`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (!optionalWorkflowTriggerIdentifier(record.default_skill)) {
|
|
177
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].default_skill must match ^[a-z0-9]+(?:[.-][a-z0-9]+)*$ when present`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!optionalConditionalSkills(record.conditional_skills)) {
|
|
181
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].conditional_skills must be a list of { when, skill } identifiers matching ^[a-z0-9]+(?:[.-][a-z0-9]+)*$ when present`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (!optionalWorkflowTriggerIdentifierList(record.required_sequence)) {
|
|
185
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].required_sequence must be a non-empty identifier list matching ^[a-z0-9]+(?:[.-][a-z0-9]+)*$ when present`);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (!optionalWorkflowTriggerIdentifierList(record.post_verify_targets)) {
|
|
189
|
+
errors.push(`${manifestPath}: workflow_triggers[${index}].post_verify_targets must be a non-empty identifier list matching ^[a-z0-9]+(?:[.-][a-z0-9]+)*$ when present`);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
entries.push({
|
|
193
|
+
id,
|
|
194
|
+
when,
|
|
195
|
+
...(typeof record.target_flow_id === "string" ? { target_flow_id: record.target_flow_id } : {}),
|
|
196
|
+
...(typeof record.default_skill === "string" ? { default_skill: record.default_skill } : {}),
|
|
197
|
+
...(Array.isArray(record.conditional_skills) ? { conditional_skills: record.conditional_skills as { when: string; skill: string }[] } : {}),
|
|
198
|
+
...(Array.isArray(record.required_sequence) ? { required_sequence: record.required_sequence as string[] } : {}),
|
|
199
|
+
...(Array.isArray(record.post_verify_targets) ? { post_verify_targets: record.post_verify_targets as string[] } : {}),
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
return { entries, errors };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function parseKitHookInfluenceExpectations(manifest: Record<string, unknown>, manifestPath: string): { entries: KitHookInfluenceExpectationEntry[]; errors: string[] } {
|
|
206
|
+
const entries: KitHookInfluenceExpectationEntry[] = [];
|
|
207
|
+
const errors: string[] = [];
|
|
208
|
+
const raw = manifest.hook_influence_expectations;
|
|
209
|
+
if (raw === undefined) return { entries, errors };
|
|
210
|
+
if (!Array.isArray(raw)) {
|
|
211
|
+
errors.push(`${manifestPath}: .hook_influence_expectations must be a list`);
|
|
212
|
+
return { entries, errors };
|
|
213
|
+
}
|
|
214
|
+
const seen = new Set<string>();
|
|
215
|
+
raw.forEach((entry, index) => {
|
|
216
|
+
if (typeof entry !== "object" || entry === null) {
|
|
217
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}] must be an object`);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const record = entry as Record<string, unknown>;
|
|
221
|
+
const id = record.id;
|
|
222
|
+
const description = record.description;
|
|
223
|
+
const tier = record.tier;
|
|
224
|
+
if (typeof id !== "string" || !id.trim()) {
|
|
225
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].id must be a non-empty string`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (seen.has(id)) errors.push(`${manifestPath}: hook_influence_expectations[${index}].id duplicates '${id}'`);
|
|
229
|
+
seen.add(id);
|
|
230
|
+
if (typeof description !== "string" || !description.trim()) {
|
|
231
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].description must be a non-empty string`);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (typeof tier !== "string" || !tier.trim()) {
|
|
235
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].tier must be a non-empty string`);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (record.hook !== undefined && (typeof record.hook !== "string" || !record.hook.trim())) {
|
|
239
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].hook must be a non-empty string when present`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (record.event !== undefined && (typeof record.event !== "string" || !record.event.trim())) {
|
|
243
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].event must be a non-empty string when present`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (!nonEmptyStringList(record.must_include_guidance)) {
|
|
247
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].must_include_guidance must be a non-empty string list`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!nonEmptyStringList(record.must_include_actions)) {
|
|
251
|
+
errors.push(`${manifestPath}: hook_influence_expectations[${index}].must_include_actions must be a non-empty string list`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
entries.push({
|
|
255
|
+
id,
|
|
256
|
+
description,
|
|
257
|
+
tier,
|
|
258
|
+
...(typeof record.hook === "string" ? { hook: record.hook } : {}),
|
|
259
|
+
...(typeof record.event === "string" ? { event: record.event } : {}),
|
|
260
|
+
must_include_guidance: record.must_include_guidance,
|
|
261
|
+
must_include_actions: record.must_include_actions,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
return { entries, errors };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function parseKitFlowStepActions(manifest: Record<string, unknown>, manifestPath: string): { entries: KitFlowStepActionEntry[]; errors: string[] } {
|
|
268
|
+
const entries: KitFlowStepActionEntry[] = [];
|
|
269
|
+
const errors: string[] = [];
|
|
270
|
+
const raw = manifest.flow_step_actions;
|
|
271
|
+
if (raw === undefined) return { entries, errors };
|
|
272
|
+
if (!Array.isArray(raw)) {
|
|
273
|
+
errors.push(`${manifestPath}: .flow_step_actions must be a list`);
|
|
274
|
+
return { entries, errors };
|
|
275
|
+
}
|
|
276
|
+
const seen = new Set<string>();
|
|
277
|
+
raw.forEach((entry, index) => {
|
|
278
|
+
if (typeof entry !== "object" || entry === null) {
|
|
279
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}] must be an object`);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const record = entry as Record<string, unknown>;
|
|
283
|
+
if (!workflowTriggerIdentifier(record.flow_id)) {
|
|
284
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}].flow_id must be a Flow identifier`);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (!workflowTriggerIdentifier(record.step_id)) {
|
|
288
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}].step_id must be a step identifier`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const skills = record.skills;
|
|
292
|
+
const operations = record.operations ?? [];
|
|
293
|
+
if (!Array.isArray(skills) || !skills.every(workflowTriggerIdentifier)) {
|
|
294
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}].skills must be an identifier list`);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (new Set(skills).size !== skills.length) {
|
|
298
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}].skills must not contain duplicates`);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (!Array.isArray(operations) || !operations.every(workflowTriggerIdentifier)) {
|
|
302
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}].operations must be an identifier list when present`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (new Set(operations).size !== operations.length) {
|
|
306
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}].operations must not contain duplicates`);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const key = `${record.flow_id}/${record.step_id}`;
|
|
310
|
+
if (seen.has(key)) {
|
|
311
|
+
errors.push(`${manifestPath}: flow_step_actions[${index}] duplicates '${key}'`);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
seen.add(key);
|
|
315
|
+
entries.push({
|
|
316
|
+
flow_id: record.flow_id,
|
|
317
|
+
step_id: record.step_id,
|
|
318
|
+
skills: skills as string[],
|
|
319
|
+
operations: operations as string[],
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
return { entries, errors };
|
|
323
|
+
}
|
|
324
|
+
|
|
79
325
|
export type KitTargetConsumer =
|
|
80
326
|
| "flow"
|
|
81
327
|
| "flow-agents"
|
|
@@ -92,42 +338,26 @@ export interface KitConformanceLevel {
|
|
|
92
338
|
|
|
93
339
|
/**
|
|
94
340
|
* Kit trust level — WHO vouches for a kit, orthogonal to the K-level capability axis.
|
|
95
|
-
*
|
|
96
|
-
* - "first-party": the kit is authored and published by Kontour (kontourai); its id is in the
|
|
97
|
-
* FIRST_PARTY_KIT_IDS allowlist maintained in this repository. These kits are built, tested,
|
|
98
|
-
* and distributed with the flow-agents package.
|
|
99
|
-
* - "verified": reserved for a future third-party verification process (e.g. self-certification
|
|
100
|
-
* via the conformance kit + cryptographic attestation / Veritas claims). Not yet implemented.
|
|
101
|
-
* - "unverified": default for all kits not in the first-party allowlist. This says nothing about
|
|
102
|
-
* the kit's quality — it only means Kontour has not vouched for it.
|
|
103
|
-
*
|
|
104
|
-
* The v2 path for "verified": cryptographic signing / attestation against the conformance kit
|
|
105
|
-
* and Veritas claims substrate is the natural next step and is intentionally deferred.
|
|
341
|
+
* Runtime steering and capability decisions do not branch on official/built-in provenance.
|
|
106
342
|
*/
|
|
107
|
-
export type KitTrustLevel = "
|
|
343
|
+
export type KitTrustLevel = "verified" | "unverified";
|
|
108
344
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
*
|
|
117
|
-
* To add a new first-party kit: add its id here AND ensure it lives under kits/ in this repo.
|
|
118
|
-
* Third-party forks or community kits published elsewhere are NOT first-party, even if they
|
|
119
|
-
* share a similar id — first-party is tied to provenance in this specific repository.
|
|
120
|
-
*/
|
|
121
|
-
export const FIRST_PARTY_KIT_IDS: ReadonlySet<string> = new Set(["builder", "knowledge"]);
|
|
345
|
+
export type KitSourceKind = "builtin" | "local" | "unknown";
|
|
346
|
+
|
|
347
|
+
export interface KitTrustOptions {
|
|
348
|
+
source_kind?: KitSourceKind;
|
|
349
|
+
kitDir?: string;
|
|
350
|
+
sourceRoot?: string;
|
|
351
|
+
}
|
|
122
352
|
|
|
123
353
|
/**
|
|
124
354
|
* Derive the trust level for a kit id.
|
|
125
|
-
*
|
|
126
|
-
* v1 determination: allowlist check against FIRST_PARTY_KIT_IDS.
|
|
127
|
-
* "verified" is reserved for future third-party verification (not yet granted to any kit).
|
|
355
|
+
* "verified" is reserved for future third-party verification.
|
|
128
356
|
*/
|
|
129
|
-
export function deriveKitTrust(kitId: string): KitTrustLevel {
|
|
130
|
-
|
|
357
|
+
export function deriveKitTrust(kitId: string, manifest?: Record<string, unknown>, options: KitTrustOptions = {}): KitTrustLevel {
|
|
358
|
+
void kitId;
|
|
359
|
+
void manifest;
|
|
360
|
+
void options;
|
|
131
361
|
return "unverified";
|
|
132
362
|
}
|
|
133
363
|
|
|
@@ -141,7 +371,7 @@ export interface KitTargetsResult {
|
|
|
141
371
|
third_party_extensions: string[];
|
|
142
372
|
/**
|
|
143
373
|
* Trust level: who vouches for this kit. Orthogonal to the K-level capability axis.
|
|
144
|
-
* "
|
|
374
|
+
* "verified" = reserved (future); "unverified" = default.
|
|
145
375
|
*/
|
|
146
376
|
trust: KitTrustLevel;
|
|
147
377
|
}
|
|
@@ -206,15 +436,15 @@ async function delegateCoreContainerValidation(kitDir: string, manifest: Record<
|
|
|
206
436
|
* - targets.flow-agents: present when K1 (agent extension assets activate in >=1 harness).
|
|
207
437
|
* - third-party: any top-level keys that are not core fields and not Flow Agents extension classes.
|
|
208
438
|
*
|
|
209
|
-
* Trust derivation
|
|
210
|
-
* - "
|
|
211
|
-
*
|
|
439
|
+
* Trust derivation:
|
|
440
|
+
* - "unverified": all current kits (default; "verified" is reserved for a future process).
|
|
441
|
+
* kit.json `first_party` is catalog metadata and is not trusted for runtime privilege.
|
|
212
442
|
*
|
|
213
443
|
* @param manifest The kit.json manifest object.
|
|
214
444
|
* @param kitDir Kit directory for flow file-existence checks. Defaults to "" (structural-only).
|
|
215
445
|
* Pass the real kit directory from `inspect` to get authoritative K0 validation.
|
|
216
446
|
*/
|
|
217
|
-
export async function deriveKitTargets(manifest: Record<string, unknown>, kitDir = ""): Promise<KitTargetsResult> {
|
|
447
|
+
export async function deriveKitTargets(manifest: Record<string, unknown>, kitDir = "", sourceRoot = process.cwd()): Promise<KitTargetsResult> {
|
|
218
448
|
const kitId = typeof manifest.id === "string" ? manifest.id : "<unknown>";
|
|
219
449
|
const kitName = typeof manifest.name === "string" ? manifest.name : "<unknown>";
|
|
220
450
|
|
|
@@ -242,7 +472,7 @@ export async function deriveKitTargets(manifest: Record<string, unknown>, kitDir
|
|
|
242
472
|
for (const ns of thirdPartyExtensions) targets.push(ns);
|
|
243
473
|
|
|
244
474
|
// Derive trust level orthogonally to the K-level capability axis.
|
|
245
|
-
const trust = deriveKitTrust(kitId);
|
|
475
|
+
const trust = deriveKitTrust(kitId, manifest, { kitDir, sourceRoot });
|
|
246
476
|
|
|
247
477
|
return {
|
|
248
478
|
kit_id: kitId,
|
|
@@ -319,6 +549,15 @@ export async function validateKitRepository(kitDir: string): Promise<string[]> {
|
|
|
319
549
|
// checked separately (non-blocking at install, hard error at activation).
|
|
320
550
|
const depResult = parseKitDependencies(manifest, manifestPath);
|
|
321
551
|
for (const err of depResult.errors) errors.push(err);
|
|
552
|
+
const workflowTriggerResult = parseKitWorkflowTriggers(manifest, manifestPath);
|
|
553
|
+
for (const err of workflowTriggerResult.errors) errors.push(err);
|
|
554
|
+
const hookExpectationResult = parseKitHookInfluenceExpectations(manifest, manifestPath);
|
|
555
|
+
for (const err of hookExpectationResult.errors) errors.push(err);
|
|
556
|
+
const flowStepActionResult = parseKitFlowStepActions(manifest, manifestPath);
|
|
557
|
+
for (const err of flowStepActionResult.errors) errors.push(err);
|
|
558
|
+
if (manifest.first_party !== undefined && typeof manifest.first_party !== "boolean") {
|
|
559
|
+
errors.push(`${manifestPath}: .first_party must be a boolean when present`);
|
|
560
|
+
}
|
|
322
561
|
|
|
323
562
|
return errors;
|
|
324
563
|
}
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,25 @@
|
|
|
16
16
|
import * as path from "node:path";
|
|
17
17
|
import { loadJson as _loadJson, writeJson as _writeJson } from "./cli/workflow-sidecar.js";
|
|
18
18
|
|
|
19
|
+
export {
|
|
20
|
+
BUILDER_BUILD_FLOW_ID,
|
|
21
|
+
BUILDER_BUILD_FLOW_RELATIVE_PATH,
|
|
22
|
+
BuilderBuildRunInputError,
|
|
23
|
+
BuilderBuildRunIdentityError,
|
|
24
|
+
evaluateBuilderBuildRun,
|
|
25
|
+
loadBuilderBuildRun,
|
|
26
|
+
resolveBuilderBuildFlowDefinitionPath,
|
|
27
|
+
startBuilderBuildRun,
|
|
28
|
+
} from "./builder-flow-run-adapter.js";
|
|
29
|
+
export type {
|
|
30
|
+
BuilderBuildRunResult,
|
|
31
|
+
BuilderBuildRunIdentityMismatch,
|
|
32
|
+
BuilderBuildTrustBundleEvidenceInput,
|
|
33
|
+
EvaluateBuilderBuildRunInput,
|
|
34
|
+
LoadBuilderBuildRunInput,
|
|
35
|
+
StartBuilderBuildRunInput,
|
|
36
|
+
} from "./builder-flow-run-adapter.js";
|
|
37
|
+
|
|
19
38
|
export {
|
|
20
39
|
defaultArtifactRootForRead,
|
|
21
40
|
defaultCodexHome,
|