@kontourai/flow-agents 4.0.0 → 4.2.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/ci.yml +8 -0
- package/CHANGELOG.md +34 -0
- package/CONTEXT.md +5 -0
- package/agents/tool-security-reviewer.json +1 -1
- package/build/src/cli/init.js +35 -3
- package/build/src/cli/kit.js +95 -2
- package/build/src/cli/pull-work-provider.js +7 -1
- package/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/build/src/cli/workflow.js +5 -1
- package/build/src/flow-kit/provision.d.ts +23 -0
- package/build/src/flow-kit/provision.js +99 -0
- package/build/src/flow-kit/validate.d.ts +52 -0
- package/build/src/flow-kit/validate.js +214 -9
- package/build/src/runtime-adapters.js +1 -1
- package/context/contracts/execution-contract.md +30 -1
- package/context/contracts/review-contract.md +4 -0
- package/context/contracts/trigger-guards.md +73 -0
- package/context/scripts/telemetry/lib/config.sh +29 -0
- package/context/settings/backlog-provider-settings.json +1 -1
- package/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/base/build/package.json +1 -1
- package/dist/base/build/src/cli/init.js +35 -3
- package/dist/base/build/src/cli/kit.js +95 -2
- package/dist/base/build/src/cli/pull-work-provider.js +7 -1
- package/dist/base/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/dist/base/build/src/cli/workflow.js +5 -1
- package/dist/base/build/src/flow-kit/provision.d.ts +23 -0
- package/dist/base/build/src/flow-kit/provision.js +99 -0
- package/dist/base/build/src/flow-kit/validate.d.ts +52 -0
- package/dist/base/build/src/flow-kit/validate.js +214 -9
- package/dist/base/build/src/runtime-adapters.js +1 -1
- package/dist/base/context/contracts/execution-contract.md +30 -1
- package/dist/base/context/contracts/review-contract.md +4 -0
- package/dist/base/context/contracts/trigger-guards.md +73 -0
- package/dist/base/context/scripts/telemetry/lib/config.sh +29 -0
- package/dist/base/context/settings/backlog-provider-settings.json +1 -1
- package/dist/base/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/base/docs/adr/0023-kit-provisioning.md +47 -0
- package/dist/base/docs/adr/index.md +1 -0
- package/dist/base/docs/architecture-engine-and-kits.md +17 -0
- package/dist/base/docs/context-map.md +3 -0
- package/dist/base/docs/decisions/backlog-readiness-source.md +89 -0
- package/dist/base/docs/decisions/index.md +1 -0
- package/dist/base/docs/developer-architecture.md +3 -3
- package/dist/base/docs/flow-kit-repository-contract.md +34 -3
- package/dist/base/docs/kit-authoring-guide.md +1 -1
- package/dist/base/docs/veritas-integration.md +12 -0
- package/dist/base/evals/ci/run-baseline.sh +4 -0
- package/dist/base/evals/integration/test_kit_provisioning.sh +112 -0
- package/dist/base/evals/integration/test_liveness_console_relay.sh +91 -1
- package/dist/base/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/dist/base/evals/integration/test_pull_work_provider.sh +18 -0
- package/dist/base/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/dist/base/evals/integration/test_workflow_artifacts.sh +257 -0
- package/dist/base/evals/static/test_package.sh +6 -0
- package/dist/base/evals/static/test_workflow_skills.sh +16 -0
- package/dist/base/install.sh +1 -1
- package/dist/base/kits/builder/flows/publish-learn.flow.json +9 -1
- package/dist/base/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/dist/base/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/dist/base/kits/builder/skills/review-work/SKILL.md +11 -0
- package/dist/base/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/dist/base/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/dist/base/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/dist/base/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/dist/base/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/dist/base/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/dist/base/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/dist/base/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/dist/base/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/dist/base/kits/veritas-governance/docs/README.md +141 -10
- package/dist/base/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/dist/base/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/dist/base/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/dist/base/kits/veritas-governance/kit.json +65 -0
- package/dist/base/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/dist/base/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/dist/base/schemas/backlog-provider-settings.schema.json +1 -1
- package/dist/base/schemas/workflow-waves.schema.json +347 -0
- package/dist/base/scripts/check-layer-boundary.mjs +98 -0
- package/dist/base/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/dist/base/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/dist/base/scripts/hooks/lib/liveness-write.js +109 -9
- package/dist/base/scripts/liveness/relay.sh +23 -11
- package/dist/base/scripts/telemetry/lib/config.sh +29 -0
- package/dist/catalog.json +2 -0
- package/dist/claude-code/.claude/agents/tool-security-reviewer.md +2 -1
- package/dist/claude-code/.claude/skills/consult-standards/SKILL.md +73 -0
- package/dist/claude-code/.claude/skills/execute-plan/SKILL.md +4 -3
- package/dist/claude-code/.claude/skills/pull-work/SKILL.md +12 -0
- package/dist/claude-code/.claude/skills/review-work/SKILL.md +11 -0
- package/dist/claude-code/.claude/skills/standards-authoring/SKILL.md +87 -0
- package/dist/claude-code/build/package.json +1 -1
- package/dist/claude-code/build/src/cli/init.js +35 -3
- package/dist/claude-code/build/src/cli/kit.js +95 -2
- package/dist/claude-code/build/src/cli/pull-work-provider.js +7 -1
- package/dist/claude-code/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/dist/claude-code/build/src/cli/workflow.js +5 -1
- package/dist/claude-code/build/src/flow-kit/provision.d.ts +23 -0
- package/dist/claude-code/build/src/flow-kit/provision.js +99 -0
- package/dist/claude-code/build/src/flow-kit/validate.d.ts +52 -0
- package/dist/claude-code/build/src/flow-kit/validate.js +214 -9
- package/dist/claude-code/build/src/runtime-adapters.js +1 -1
- package/dist/claude-code/context/contracts/execution-contract.md +30 -1
- package/dist/claude-code/context/contracts/review-contract.md +4 -0
- package/dist/claude-code/context/contracts/trigger-guards.md +73 -0
- package/dist/claude-code/context/scripts/telemetry/lib/config.sh +29 -0
- package/dist/claude-code/context/settings/backlog-provider-settings.json +1 -1
- package/dist/claude-code/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/claude-code/docs/adr/0023-kit-provisioning.md +47 -0
- package/dist/claude-code/docs/adr/index.md +1 -0
- package/dist/claude-code/docs/architecture-engine-and-kits.md +17 -0
- package/dist/claude-code/docs/context-map.md +3 -0
- package/dist/claude-code/docs/decisions/backlog-readiness-source.md +89 -0
- package/dist/claude-code/docs/decisions/index.md +1 -0
- package/dist/claude-code/docs/developer-architecture.md +3 -3
- package/dist/claude-code/docs/flow-kit-repository-contract.md +34 -3
- package/dist/claude-code/docs/kit-authoring-guide.md +1 -1
- package/dist/claude-code/docs/veritas-integration.md +12 -0
- package/dist/claude-code/evals/ci/run-baseline.sh +4 -0
- package/dist/claude-code/evals/integration/test_kit_provisioning.sh +112 -0
- package/dist/claude-code/evals/integration/test_liveness_console_relay.sh +91 -1
- package/dist/claude-code/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/dist/claude-code/evals/integration/test_pull_work_provider.sh +18 -0
- package/dist/claude-code/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/dist/claude-code/evals/integration/test_workflow_artifacts.sh +257 -0
- package/dist/claude-code/evals/static/test_package.sh +6 -0
- package/dist/claude-code/evals/static/test_workflow_skills.sh +16 -0
- package/dist/claude-code/install.sh +1 -1
- package/dist/claude-code/kits/builder/flows/publish-learn.flow.json +9 -1
- package/dist/claude-code/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/dist/claude-code/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/dist/claude-code/kits/builder/skills/review-work/SKILL.md +11 -0
- package/dist/claude-code/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/dist/claude-code/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/dist/claude-code/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/dist/claude-code/kits/veritas-governance/docs/README.md +141 -10
- package/dist/claude-code/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/dist/claude-code/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/dist/claude-code/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/dist/claude-code/kits/veritas-governance/kit.json +65 -0
- package/dist/claude-code/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/dist/claude-code/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/dist/claude-code/schemas/backlog-provider-settings.schema.json +1 -1
- package/dist/claude-code/schemas/workflow-waves.schema.json +347 -0
- package/dist/claude-code/scripts/check-layer-boundary.mjs +98 -0
- package/dist/claude-code/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/dist/claude-code/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/dist/claude-code/scripts/hooks/lib/liveness-write.js +109 -9
- package/dist/claude-code/scripts/liveness/relay.sh +23 -11
- package/dist/claude-code/scripts/telemetry/lib/config.sh +29 -0
- package/dist/codex/.agents/skills/builder-shape/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/consult-standards/SKILL.md +73 -0
- package/dist/codex/.agents/skills/deliver/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/design-probe/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/execute-plan/SKILL.md +4 -3
- package/dist/codex/.agents/skills/execute-plan/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/fix-bug/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/idea-to-backlog/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/plan-work/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/pull-work/SKILL.md +12 -0
- package/dist/codex/.agents/skills/pull-work/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/review-work/SKILL.md +11 -0
- package/dist/codex/.agents/skills/review-work/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/standards-authoring/SKILL.md +87 -0
- package/dist/codex/.agents/skills/tdd-workflow/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.agents/skills/verify-work/context/contracts/execution-contract.md +30 -1
- package/dist/codex/.codex/agents/tool-security-reviewer.toml +1 -1
- package/dist/codex/build/package.json +1 -1
- package/dist/codex/build/src/cli/init.js +35 -3
- package/dist/codex/build/src/cli/kit.js +95 -2
- package/dist/codex/build/src/cli/pull-work-provider.js +7 -1
- package/dist/codex/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/dist/codex/build/src/cli/workflow.js +5 -1
- package/dist/codex/build/src/flow-kit/provision.d.ts +23 -0
- package/dist/codex/build/src/flow-kit/provision.js +99 -0
- package/dist/codex/build/src/flow-kit/validate.d.ts +52 -0
- package/dist/codex/build/src/flow-kit/validate.js +214 -9
- package/dist/codex/build/src/runtime-adapters.js +1 -1
- package/dist/codex/context/contracts/execution-contract.md +30 -1
- package/dist/codex/context/contracts/review-contract.md +4 -0
- package/dist/codex/context/contracts/trigger-guards.md +73 -0
- package/dist/codex/context/scripts/telemetry/lib/config.sh +29 -0
- package/dist/codex/context/settings/backlog-provider-settings.json +1 -1
- package/dist/codex/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/codex/docs/adr/0023-kit-provisioning.md +47 -0
- package/dist/codex/docs/adr/index.md +1 -0
- package/dist/codex/docs/architecture-engine-and-kits.md +17 -0
- package/dist/codex/docs/context-map.md +3 -0
- package/dist/codex/docs/decisions/backlog-readiness-source.md +89 -0
- package/dist/codex/docs/decisions/index.md +1 -0
- package/dist/codex/docs/developer-architecture.md +3 -3
- package/dist/codex/docs/flow-kit-repository-contract.md +34 -3
- package/dist/codex/docs/kit-authoring-guide.md +1 -1
- package/dist/codex/docs/veritas-integration.md +12 -0
- package/dist/codex/evals/ci/run-baseline.sh +4 -0
- package/dist/codex/evals/integration/test_kit_provisioning.sh +112 -0
- package/dist/codex/evals/integration/test_liveness_console_relay.sh +91 -1
- package/dist/codex/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/dist/codex/evals/integration/test_pull_work_provider.sh +18 -0
- package/dist/codex/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/dist/codex/evals/integration/test_workflow_artifacts.sh +257 -0
- package/dist/codex/evals/static/test_package.sh +6 -0
- package/dist/codex/evals/static/test_workflow_skills.sh +16 -0
- package/dist/codex/install.sh +1 -1
- package/dist/codex/kits/builder/flows/publish-learn.flow.json +9 -1
- package/dist/codex/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/dist/codex/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/dist/codex/kits/builder/skills/review-work/SKILL.md +11 -0
- package/dist/codex/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/dist/codex/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/dist/codex/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/dist/codex/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/dist/codex/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/dist/codex/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/dist/codex/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/dist/codex/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/dist/codex/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/dist/codex/kits/veritas-governance/docs/README.md +141 -10
- package/dist/codex/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/dist/codex/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/dist/codex/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/dist/codex/kits/veritas-governance/kit.json +65 -0
- package/dist/codex/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/dist/codex/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/dist/codex/schemas/backlog-provider-settings.schema.json +1 -1
- package/dist/codex/schemas/workflow-waves.schema.json +347 -0
- package/dist/codex/scripts/check-layer-boundary.mjs +98 -0
- package/dist/codex/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/dist/codex/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/dist/codex/scripts/hooks/lib/liveness-write.js +109 -9
- package/dist/codex/scripts/liveness/relay.sh +23 -11
- package/dist/codex/scripts/telemetry/lib/config.sh +29 -0
- package/dist/kiro/agents/tool-security-reviewer.json +1 -1
- package/dist/kiro/build/package.json +1 -1
- package/dist/kiro/build/src/cli/init.js +35 -3
- package/dist/kiro/build/src/cli/kit.js +95 -2
- package/dist/kiro/build/src/cli/pull-work-provider.js +7 -1
- package/dist/kiro/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/dist/kiro/build/src/cli/workflow.js +5 -1
- package/dist/kiro/build/src/flow-kit/provision.d.ts +23 -0
- package/dist/kiro/build/src/flow-kit/provision.js +99 -0
- package/dist/kiro/build/src/flow-kit/validate.d.ts +52 -0
- package/dist/kiro/build/src/flow-kit/validate.js +214 -9
- package/dist/kiro/build/src/runtime-adapters.js +1 -1
- package/dist/kiro/context/contracts/execution-contract.md +30 -1
- package/dist/kiro/context/contracts/review-contract.md +4 -0
- package/dist/kiro/context/contracts/trigger-guards.md +73 -0
- package/dist/kiro/context/scripts/telemetry/lib/config.sh +29 -0
- package/dist/kiro/context/settings/backlog-provider-settings.json +1 -1
- package/dist/kiro/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/kiro/docs/adr/0023-kit-provisioning.md +47 -0
- package/dist/kiro/docs/adr/index.md +1 -0
- package/dist/kiro/docs/architecture-engine-and-kits.md +17 -0
- package/dist/kiro/docs/context-map.md +3 -0
- package/dist/kiro/docs/decisions/backlog-readiness-source.md +89 -0
- package/dist/kiro/docs/decisions/index.md +1 -0
- package/dist/kiro/docs/developer-architecture.md +3 -3
- package/dist/kiro/docs/flow-kit-repository-contract.md +34 -3
- package/dist/kiro/docs/kit-authoring-guide.md +1 -1
- package/dist/kiro/docs/veritas-integration.md +12 -0
- package/dist/kiro/evals/ci/run-baseline.sh +4 -0
- package/dist/kiro/evals/integration/test_kit_provisioning.sh +112 -0
- package/dist/kiro/evals/integration/test_liveness_console_relay.sh +91 -1
- package/dist/kiro/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/dist/kiro/evals/integration/test_pull_work_provider.sh +18 -0
- package/dist/kiro/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/dist/kiro/evals/integration/test_workflow_artifacts.sh +257 -0
- package/dist/kiro/evals/static/test_package.sh +6 -0
- package/dist/kiro/evals/static/test_workflow_skills.sh +16 -0
- package/dist/kiro/install.sh +1 -1
- package/dist/kiro/kits/builder/flows/publish-learn.flow.json +9 -1
- package/dist/kiro/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/dist/kiro/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/dist/kiro/kits/builder/skills/review-work/SKILL.md +11 -0
- package/dist/kiro/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/dist/kiro/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/dist/kiro/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/dist/kiro/kits/veritas-governance/docs/README.md +141 -10
- package/dist/kiro/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/dist/kiro/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/dist/kiro/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/dist/kiro/kits/veritas-governance/kit.json +65 -0
- package/dist/kiro/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/dist/kiro/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/dist/kiro/schemas/backlog-provider-settings.schema.json +1 -1
- package/dist/kiro/schemas/workflow-waves.schema.json +347 -0
- package/dist/kiro/scripts/check-layer-boundary.mjs +98 -0
- package/dist/kiro/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/dist/kiro/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/dist/kiro/scripts/hooks/lib/liveness-write.js +109 -9
- package/dist/kiro/scripts/liveness/relay.sh +23 -11
- package/dist/kiro/scripts/telemetry/lib/config.sh +29 -0
- package/dist/opencode/.opencode/agents/tool-security-reviewer.md +2 -1
- package/dist/opencode/.opencode/skills/consult-standards/SKILL.md +73 -0
- package/dist/opencode/.opencode/skills/execute-plan/SKILL.md +4 -3
- package/dist/opencode/.opencode/skills/pull-work/SKILL.md +12 -0
- package/dist/opencode/.opencode/skills/review-work/SKILL.md +11 -0
- package/dist/opencode/.opencode/skills/standards-authoring/SKILL.md +87 -0
- package/dist/opencode/build/package.json +1 -1
- package/dist/opencode/build/src/cli/init.js +35 -3
- package/dist/opencode/build/src/cli/kit.js +95 -2
- package/dist/opencode/build/src/cli/pull-work-provider.js +7 -1
- package/dist/opencode/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/dist/opencode/build/src/cli/workflow.js +5 -1
- package/dist/opencode/build/src/flow-kit/provision.d.ts +23 -0
- package/dist/opencode/build/src/flow-kit/provision.js +99 -0
- package/dist/opencode/build/src/flow-kit/validate.d.ts +52 -0
- package/dist/opencode/build/src/flow-kit/validate.js +214 -9
- package/dist/opencode/build/src/runtime-adapters.js +1 -1
- package/dist/opencode/context/contracts/execution-contract.md +30 -1
- package/dist/opencode/context/contracts/review-contract.md +4 -0
- package/dist/opencode/context/contracts/trigger-guards.md +73 -0
- package/dist/opencode/context/scripts/telemetry/lib/config.sh +29 -0
- package/dist/opencode/context/settings/backlog-provider-settings.json +1 -1
- package/dist/opencode/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/opencode/docs/adr/0023-kit-provisioning.md +47 -0
- package/dist/opencode/docs/adr/index.md +1 -0
- package/dist/opencode/docs/architecture-engine-and-kits.md +17 -0
- package/dist/opencode/docs/context-map.md +3 -0
- package/dist/opencode/docs/decisions/backlog-readiness-source.md +89 -0
- package/dist/opencode/docs/decisions/index.md +1 -0
- package/dist/opencode/docs/developer-architecture.md +3 -3
- package/dist/opencode/docs/flow-kit-repository-contract.md +34 -3
- package/dist/opencode/docs/kit-authoring-guide.md +1 -1
- package/dist/opencode/docs/veritas-integration.md +12 -0
- package/dist/opencode/evals/ci/run-baseline.sh +4 -0
- package/dist/opencode/evals/integration/test_kit_provisioning.sh +112 -0
- package/dist/opencode/evals/integration/test_liveness_console_relay.sh +91 -1
- package/dist/opencode/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/dist/opencode/evals/integration/test_pull_work_provider.sh +18 -0
- package/dist/opencode/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/dist/opencode/evals/integration/test_workflow_artifacts.sh +257 -0
- package/dist/opencode/evals/static/test_package.sh +6 -0
- package/dist/opencode/evals/static/test_workflow_skills.sh +16 -0
- package/dist/opencode/install.sh +1 -1
- package/dist/opencode/kits/builder/flows/publish-learn.flow.json +9 -1
- package/dist/opencode/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/dist/opencode/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/dist/opencode/kits/builder/skills/review-work/SKILL.md +11 -0
- package/dist/opencode/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/dist/opencode/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/dist/opencode/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/dist/opencode/kits/veritas-governance/docs/README.md +141 -10
- package/dist/opencode/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/dist/opencode/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/dist/opencode/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/dist/opencode/kits/veritas-governance/kit.json +65 -0
- package/dist/opencode/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/dist/opencode/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/dist/opencode/schemas/backlog-provider-settings.schema.json +1 -1
- package/dist/opencode/schemas/workflow-waves.schema.json +347 -0
- package/dist/opencode/scripts/check-layer-boundary.mjs +98 -0
- package/dist/opencode/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/dist/opencode/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/dist/opencode/scripts/hooks/lib/liveness-write.js +109 -9
- package/dist/opencode/scripts/liveness/relay.sh +23 -11
- package/dist/opencode/scripts/telemetry/lib/config.sh +29 -0
- package/dist/pi/.pi/skills/consult-standards/SKILL.md +73 -0
- package/dist/pi/.pi/skills/execute-plan/SKILL.md +4 -3
- package/dist/pi/.pi/skills/pull-work/SKILL.md +12 -0
- package/dist/pi/.pi/skills/review-work/SKILL.md +11 -0
- package/dist/pi/.pi/skills/standards-authoring/SKILL.md +87 -0
- package/dist/pi/build/package.json +1 -1
- package/dist/pi/build/src/cli/init.js +35 -3
- package/dist/pi/build/src/cli/kit.js +95 -2
- package/dist/pi/build/src/cli/pull-work-provider.js +7 -1
- package/dist/pi/build/src/cli/validate-workflow-artifacts.js +53 -0
- package/dist/pi/build/src/cli/workflow.js +5 -1
- package/dist/pi/build/src/flow-kit/provision.d.ts +23 -0
- package/dist/pi/build/src/flow-kit/provision.js +99 -0
- package/dist/pi/build/src/flow-kit/validate.d.ts +52 -0
- package/dist/pi/build/src/flow-kit/validate.js +214 -9
- package/dist/pi/build/src/runtime-adapters.js +1 -1
- package/dist/pi/context/contracts/execution-contract.md +30 -1
- package/dist/pi/context/contracts/review-contract.md +4 -0
- package/dist/pi/context/contracts/trigger-guards.md +73 -0
- package/dist/pi/context/scripts/telemetry/lib/config.sh +29 -0
- package/dist/pi/context/settings/backlog-provider-settings.json +1 -1
- package/dist/pi/context/settings/workspace-backlog-provider-settings.example.json +1 -1
- package/dist/pi/docs/adr/0023-kit-provisioning.md +47 -0
- package/dist/pi/docs/adr/index.md +1 -0
- package/dist/pi/docs/architecture-engine-and-kits.md +17 -0
- package/dist/pi/docs/context-map.md +3 -0
- package/dist/pi/docs/decisions/backlog-readiness-source.md +89 -0
- package/dist/pi/docs/decisions/index.md +1 -0
- package/dist/pi/docs/developer-architecture.md +3 -3
- package/dist/pi/docs/flow-kit-repository-contract.md +34 -3
- package/dist/pi/docs/kit-authoring-guide.md +1 -1
- package/dist/pi/docs/veritas-integration.md +12 -0
- package/dist/pi/evals/ci/run-baseline.sh +4 -0
- package/dist/pi/evals/integration/test_kit_provisioning.sh +112 -0
- package/dist/pi/evals/integration/test_liveness_console_relay.sh +91 -1
- package/dist/pi/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/dist/pi/evals/integration/test_pull_work_provider.sh +18 -0
- package/dist/pi/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/dist/pi/evals/integration/test_workflow_artifacts.sh +257 -0
- package/dist/pi/evals/static/test_package.sh +6 -0
- package/dist/pi/evals/static/test_workflow_skills.sh +16 -0
- package/dist/pi/install.sh +1 -1
- package/dist/pi/kits/builder/flows/publish-learn.flow.json +9 -1
- package/dist/pi/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/dist/pi/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/dist/pi/kits/builder/skills/review-work/SKILL.md +11 -0
- package/dist/pi/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/dist/pi/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/dist/pi/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/dist/pi/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/dist/pi/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/dist/pi/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/dist/pi/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/dist/pi/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/dist/pi/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/dist/pi/kits/veritas-governance/docs/README.md +141 -10
- package/dist/pi/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/dist/pi/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/dist/pi/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/dist/pi/kits/veritas-governance/kit.json +65 -0
- package/dist/pi/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/dist/pi/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/dist/pi/schemas/backlog-provider-settings.schema.json +1 -1
- package/dist/pi/schemas/workflow-waves.schema.json +347 -0
- package/dist/pi/scripts/check-layer-boundary.mjs +98 -0
- package/dist/pi/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/dist/pi/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/dist/pi/scripts/hooks/lib/liveness-write.js +109 -9
- package/dist/pi/scripts/liveness/relay.sh +23 -11
- package/dist/pi/scripts/telemetry/lib/config.sh +29 -0
- package/docs/adr/0023-kit-provisioning.md +47 -0
- package/docs/adr/index.md +1 -0
- package/docs/architecture-engine-and-kits.md +17 -0
- package/docs/context-map.md +3 -0
- package/docs/decisions/backlog-readiness-source.md +89 -0
- package/docs/decisions/index.md +1 -0
- package/docs/developer-architecture.md +3 -3
- package/docs/flow-kit-repository-contract.md +34 -3
- package/docs/kit-authoring-guide.md +1 -1
- package/docs/veritas-integration.md +12 -0
- package/evals/ci/run-baseline.sh +4 -0
- package/evals/integration/test_kit_provisioning.sh +112 -0
- package/evals/integration/test_liveness_console_relay.sh +91 -1
- package/evals/integration/test_liveness_heartbeat.sh +66 -0
- package/evals/integration/test_pull_work_provider.sh +18 -0
- package/evals/integration/test_veritas_governance_kit.sh +256 -0
- package/evals/integration/test_workflow_artifacts.sh +257 -0
- package/evals/static/test_package.sh +6 -0
- package/evals/static/test_workflow_skills.sh +16 -0
- package/kits/builder/flows/publish-learn.flow.json +9 -1
- package/kits/builder/skills/execute-plan/SKILL.md +4 -3
- package/kits/builder/skills/pull-work/SKILL.md +12 -0
- package/kits/builder/skills/review-work/SKILL.md +11 -0
- package/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +19 -20
- package/kits/veritas-governance/assets/starter-hooks/githooks/post-commit +13 -0
- package/kits/veritas-governance/assets/starter-hooks/githooks/pre-push +13 -0
- package/kits/veritas-governance/assets/starter-standards/veritas/GOVERNANCE.md +23 -0
- package/kits/veritas-governance/assets/starter-standards/veritas/README.md +58 -0
- package/kits/veritas-governance/assets/starter-standards/veritas/authority/default.authority-settings.json +30 -0
- package/kits/veritas-governance/assets/starter-standards/veritas/repo-map.json +115 -0
- package/kits/veritas-governance/assets/starter-standards/veritas/repo-standards/default.repo-standards.json +54 -0
- package/kits/veritas-governance/assets/starter-standards/veritas.claims.json +179 -0
- package/kits/veritas-governance/docs/README.md +141 -10
- package/kits/veritas-governance/fixtures/standards-authoring/approved.trust-bundle.json +74 -0
- package/kits/veritas-governance/fixtures/standards-authoring/not-approved.trust-bundle.json +74 -0
- package/kits/veritas-governance/flows/standards-authoring.flow.json +35 -0
- package/kits/veritas-governance/kit.json +65 -0
- package/kits/veritas-governance/skills/consult-standards/SKILL.md +73 -0
- package/kits/veritas-governance/skills/standards-authoring/SKILL.md +87 -0
- package/package.json +2 -1
- package/schemas/backlog-provider-settings.schema.json +1 -1
- package/schemas/workflow-waves.schema.json +347 -0
- package/scripts/check-layer-boundary.mjs +98 -0
- package/scripts/hooks/claude-telemetry-hook.js +6 -0
- package/scripts/hooks/lib/liveness-heartbeat.js +42 -1
- package/scripts/hooks/lib/liveness-write.js +109 -9
- package/scripts/liveness/relay.sh +23 -11
- package/scripts/telemetry/lib/config.sh +29 -0
- package/src/cli/builder-flow-runtime.test.mjs +86 -0
- package/src/cli/flow-resolver-composition.test.mjs +20 -1
- package/src/cli/init.ts +31 -3
- package/src/cli/kit-metadata-security.test.mjs +163 -1
- package/src/cli/kit-provisioning.test.mjs +122 -0
- package/src/cli/kit.ts +83 -2
- package/src/cli/pull-work-provider.ts +7 -1
- package/src/cli/validate-waves.test.mjs +134 -0
- package/src/cli/validate-workflow-artifacts.ts +47 -0
- package/src/cli/workflow.ts +7 -1
- package/src/flow-kit/provision.ts +118 -0
- package/src/flow-kit/validate.ts +233 -10
- package/src/runtime-adapters.ts +1 -1
|
@@ -18,6 +18,7 @@ const sidecarSchemas = {
|
|
|
18
18
|
"critique.json": "schemas/workflow-critique.schema.json",
|
|
19
19
|
"release.json": "schemas/workflow-release.schema.json",
|
|
20
20
|
"learning.json": "schemas/workflow-learning.schema.json",
|
|
21
|
+
"waves.json": "schemas/workflow-waves.schema.json",
|
|
21
22
|
};
|
|
22
23
|
// Runtime coordination records live below a session but are not workflow
|
|
23
24
|
// sidecars. Recursing into them would validate continuation-driver/state.json
|
|
@@ -386,11 +387,63 @@ function validateSidecar(file) {
|
|
|
386
387
|
issues.push({ path: file, message: "deploy decision requires post_deploy_checks to be planned or pass" });
|
|
387
388
|
}
|
|
388
389
|
}
|
|
390
|
+
if (path.basename(file) === "waves.json") {
|
|
391
|
+
validateWaves(file, value, issues);
|
|
392
|
+
}
|
|
389
393
|
if (path.basename(file) === "state.json" && value && typeof value === "object" && !Array.isArray(value) && !("branch" in value)) {
|
|
390
394
|
warnings.push({ path: file, message: "state.json has no branch field (legacy/pre-#289 session) — re-run `ensure-session` to backfill agent/<actor>/<slug>." });
|
|
391
395
|
}
|
|
392
396
|
return { issues, warnings };
|
|
393
397
|
}
|
|
398
|
+
// #663 slice 1: wave-result reconciliation is machine-checkable, not prose. The schema
|
|
399
|
+
// (schemas/workflow-waves.schema.json) validates the shape; these semantic checks enforce the
|
|
400
|
+
// cross-record arithmetic the mini schema engine cannot express: exactly one terminal status
|
|
401
|
+
// record per declared worker, no undeclared reporters, reconciliation counts that match the
|
|
402
|
+
// records, and a `complete` claim that is impossible while any expected worker lacks a
|
|
403
|
+
// worker-landed terminal status. Missing workers must be recorded explicitly as not_reported —
|
|
404
|
+
// a reconciled wave never silently absorbs a dropped worker. Enforcement here is data-level
|
|
405
|
+
// validation only; stop-hook refusal of wave completion is #663 part 3 (slice 2).
|
|
406
|
+
function validateWaves(file, value, issues) {
|
|
407
|
+
const waves = Array.isArray(value?.waves) ? value.waves : [];
|
|
408
|
+
waves.forEach((wave, index) => {
|
|
409
|
+
const loc = `waves.json.waves[${index}]`;
|
|
410
|
+
const expected = Array.isArray(wave?.expected_workers) ? wave.expected_workers : [];
|
|
411
|
+
const results = Array.isArray(wave?.worker_results) ? wave.worker_results : [];
|
|
412
|
+
const expectedIds = expected.map((w) => w?.worker_id).filter((id) => typeof id === "string" && id.length > 0);
|
|
413
|
+
const expectedIdSet = new Set(expectedIds);
|
|
414
|
+
if (expectedIdSet.size !== expectedIds.length)
|
|
415
|
+
issues.push({ path: file, message: `${loc}.expected_workers must declare unique worker_id values` });
|
|
416
|
+
const resultIds = results.map((r) => r?.worker_id).filter((id) => typeof id === "string" && id.length > 0);
|
|
417
|
+
const seen = new Set();
|
|
418
|
+
for (const id of resultIds) {
|
|
419
|
+
if (seen.has(id))
|
|
420
|
+
issues.push({ path: file, message: `${loc}.worker_results has more than one terminal status record for worker ${id}; each worker lands exactly one` });
|
|
421
|
+
seen.add(id);
|
|
422
|
+
if (!expectedIdSet.has(id))
|
|
423
|
+
issues.push({ path: file, message: `${loc}.worker_results records worker ${id} that is not declared in expected_workers; declare every worker in the manifest before dispatch` });
|
|
424
|
+
}
|
|
425
|
+
const reconciliation = wave?.reconciliation;
|
|
426
|
+
if (!reconciliation || typeof reconciliation !== "object" || Array.isArray(reconciliation))
|
|
427
|
+
return;
|
|
428
|
+
const expectedCount = expectedIds.length;
|
|
429
|
+
const reportedIds = new Set(results.filter((r) => ["completed", "failed", "blocked"].includes(r?.status) && expectedIdSet.has(r?.worker_id)).map((r) => r.worker_id));
|
|
430
|
+
const reportedCount = reportedIds.size;
|
|
431
|
+
if (reconciliation.expected_count !== expectedCount)
|
|
432
|
+
issues.push({ path: file, message: `${loc}.reconciliation.expected_count is ${reconciliation.expected_count} but expected_workers declares ${expectedCount}` });
|
|
433
|
+
if (reconciliation.reported_count !== reportedCount)
|
|
434
|
+
issues.push({ path: file, message: `${loc}.reconciliation.reported_count is ${reconciliation.reported_count} but ${reportedCount} of ${expectedCount} expected workers have a worker-landed terminal status (completed|failed|blocked)` });
|
|
435
|
+
const missing = expectedIds.filter((id) => !results.some((r) => r?.worker_id === id));
|
|
436
|
+
for (const id of missing)
|
|
437
|
+
issues.push({ path: file, message: `${loc} is reconciled but worker ${id} has no terminal status record; record it explicitly as not_reported — never silently absorb a missing worker` });
|
|
438
|
+
const notReported = results.filter((r) => r?.status === "not_reported" && expectedIdSet.has(r?.worker_id));
|
|
439
|
+
if (reconciliation.status === "complete" && (missing.length > 0 || notReported.length > 0 || reportedCount !== expectedCount)) {
|
|
440
|
+
issues.push({ path: file, message: `${loc}.reconciliation.status complete requires every expected worker to have a worker-landed terminal status; got ${reportedCount} of ${expectedCount} reported` });
|
|
441
|
+
}
|
|
442
|
+
if (reconciliation.status === "incomplete" && missing.length === 0 && notReported.length === 0 && reportedCount === expectedCount) {
|
|
443
|
+
issues.push({ path: file, message: `${loc}.reconciliation.status incomplete contradicts the records: all ${expectedCount} expected workers reported` });
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
394
447
|
function validateLearningCorrections(file, status, records, issues) {
|
|
395
448
|
records.forEach((record, index) => {
|
|
396
449
|
const correction = record?.correction;
|
|
@@ -733,7 +733,11 @@ function assertDistinctReviewActor(sessionDir, slug) {
|
|
|
733
733
|
const assignment = readActiveAssignment(sessionDir, slug);
|
|
734
734
|
const caller = resolveCurrentAssignmentActor();
|
|
735
735
|
if (assignment.actor_key === caller.actorKey) {
|
|
736
|
-
throw new Error("workflow critique requires a reviewer identity distinct from the active implementation assignment actor"
|
|
736
|
+
throw new Error("workflow critique requires a reviewer identity distinct from the active implementation assignment actor. " +
|
|
737
|
+
"The reviewer identity is derived from the runtime actor, so an orchestrator that implemented and now reviews " +
|
|
738
|
+
"resolves to the same actor. To record an independent review, run the reviewer under a distinct actor: set " +
|
|
739
|
+
"FLOW_AGENTS_ACTOR=<reviewer-id> on the reviewing process, or run the reviewer in a separate runtime session " +
|
|
740
|
+
"(the runtime session id seeds the actor).");
|
|
737
741
|
}
|
|
738
742
|
return caller;
|
|
739
743
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type ProvisionedFile = {
|
|
2
|
+
id: string;
|
|
3
|
+
target: string;
|
|
4
|
+
};
|
|
5
|
+
export type ProvisionPlanEntry = ProvisionedFile & {
|
|
6
|
+
source: string;
|
|
7
|
+
destination: string;
|
|
8
|
+
};
|
|
9
|
+
export type ProvisionResult = {
|
|
10
|
+
kit_id: string;
|
|
11
|
+
kit_hash?: string;
|
|
12
|
+
files: ProvisionPlanEntry[];
|
|
13
|
+
manifest_path?: string;
|
|
14
|
+
dry_run: boolean;
|
|
15
|
+
};
|
|
16
|
+
export declare class ProvisionConflictError extends Error {
|
|
17
|
+
readonly conflicts: ProvisionPlanEntry[];
|
|
18
|
+
constructor(conflicts: ProvisionPlanEntry[]);
|
|
19
|
+
}
|
|
20
|
+
export declare function provisionKit(kitDir: string, targetDir: string, options?: {
|
|
21
|
+
force?: boolean;
|
|
22
|
+
dryRun?: boolean;
|
|
23
|
+
}): Promise<ProvisionResult>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { atomicCopyFile, atomicWriteJson, canonicalProspectivePath, walkFiles } from "../lib/fs.js";
|
|
5
|
+
import { PROVISION_MANIFEST_DIR, assertKitRepository } from "./validate.js";
|
|
6
|
+
export class ProvisionConflictError extends Error {
|
|
7
|
+
conflicts;
|
|
8
|
+
constructor(conflicts) {
|
|
9
|
+
super(`provisioning conflicts with ${conflicts.length} existing destination(s)`);
|
|
10
|
+
this.name = "ProvisionConflictError";
|
|
11
|
+
this.conflicts = conflicts;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function kitContentHash(kitDir) {
|
|
15
|
+
const hash = crypto.createHash("sha256");
|
|
16
|
+
for (const file of walkFiles(kitDir)) {
|
|
17
|
+
const rel = path.relative(kitDir, file).split(path.sep).join("/");
|
|
18
|
+
if (rel.split("/").some((part) => [".git", "__pycache__", ".pytest_cache"].includes(part)))
|
|
19
|
+
continue;
|
|
20
|
+
hash.update(rel);
|
|
21
|
+
hash.update("\0");
|
|
22
|
+
hash.update(fs.readFileSync(file));
|
|
23
|
+
hash.update("\0");
|
|
24
|
+
}
|
|
25
|
+
return `sha256:${hash.digest("hex")}`;
|
|
26
|
+
}
|
|
27
|
+
function isContained(root, candidate) {
|
|
28
|
+
const relative = path.relative(root, candidate);
|
|
29
|
+
return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
30
|
+
}
|
|
31
|
+
function assertSafeDestination(rootReal, destination) {
|
|
32
|
+
const prospective = canonicalProspectivePath(destination);
|
|
33
|
+
if (!isContained(rootReal, prospective))
|
|
34
|
+
throw new Error(`provision target escapes consumer repository: ${destination}`);
|
|
35
|
+
if (!fs.existsSync(destination))
|
|
36
|
+
return;
|
|
37
|
+
const stat = fs.lstatSync(destination);
|
|
38
|
+
if (stat.isSymbolicLink())
|
|
39
|
+
throw new Error(`refusing provision target symlink: ${destination}`);
|
|
40
|
+
if (!stat.isFile())
|
|
41
|
+
throw new Error(`provision target is not a regular file: ${destination}`);
|
|
42
|
+
}
|
|
43
|
+
function manifestProvisions(manifest) {
|
|
44
|
+
if (!Array.isArray(manifest.provisions))
|
|
45
|
+
return [];
|
|
46
|
+
return manifest.provisions.map((entry) => {
|
|
47
|
+
const record = entry;
|
|
48
|
+
return {
|
|
49
|
+
id: String(record.id),
|
|
50
|
+
path: String(record.path),
|
|
51
|
+
target: path.posix.normalize(String(record.target).replace(/\\/g, "/")),
|
|
52
|
+
...(typeof record.description === "string" ? { description: record.description } : {}),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export async function provisionKit(kitDir, targetDir, options = {}) {
|
|
57
|
+
const kitRoot = fs.realpathSync(path.resolve(kitDir));
|
|
58
|
+
const targetPath = path.resolve(targetDir);
|
|
59
|
+
if (!fs.existsSync(targetPath) || !fs.statSync(targetPath).isDirectory()) {
|
|
60
|
+
throw new Error(`provision target must exist and be a directory: ${targetPath}`);
|
|
61
|
+
}
|
|
62
|
+
const targetRoot = fs.realpathSync(targetPath);
|
|
63
|
+
const manifest = await assertKitRepository(kitRoot);
|
|
64
|
+
const kitId = String(manifest.id);
|
|
65
|
+
const files = manifestProvisions(manifest).map((entry) => ({
|
|
66
|
+
id: entry.id,
|
|
67
|
+
target: entry.target,
|
|
68
|
+
source: path.resolve(kitRoot, entry.path),
|
|
69
|
+
destination: path.resolve(targetRoot, ...entry.target.split("/")),
|
|
70
|
+
}));
|
|
71
|
+
for (const file of files)
|
|
72
|
+
assertSafeDestination(targetRoot, file.destination);
|
|
73
|
+
// Defense in depth against a source swapped to a link after validation: re-assert the
|
|
74
|
+
// link-resolved source stays inside the kit before we read and copy its bytes.
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
const realSource = fs.realpathSync(file.source);
|
|
77
|
+
if (realSource !== kitRoot && !realSource.startsWith(`${kitRoot}${path.sep}`)) {
|
|
78
|
+
throw new Error(`provision source escapes the kit directory: ${file.id}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const conflicts = options.force ? [] : files.filter((file) => fs.existsSync(file.destination));
|
|
82
|
+
if (conflicts.length)
|
|
83
|
+
throw new ProvisionConflictError(conflicts);
|
|
84
|
+
const kitHash = kitContentHash(kitRoot);
|
|
85
|
+
if (options.dryRun || files.length === 0)
|
|
86
|
+
return { kit_id: kitId, kit_hash: kitHash, files, dry_run: Boolean(options.dryRun) };
|
|
87
|
+
const manifestPath = path.join(targetRoot, ...PROVISION_MANIFEST_DIR.split("/"), `${kitId}.json`);
|
|
88
|
+
assertSafeDestination(targetRoot, manifestPath);
|
|
89
|
+
for (const file of files)
|
|
90
|
+
atomicCopyFile(targetRoot, file.source, file.destination);
|
|
91
|
+
atomicWriteJson(targetRoot, manifestPath, {
|
|
92
|
+
schema_version: "1.0",
|
|
93
|
+
kit_id: kitId,
|
|
94
|
+
kit_hash: kitHash,
|
|
95
|
+
provisioned_at: new Date().toISOString(),
|
|
96
|
+
files: files.map(({ id, target }) => ({ id, target })),
|
|
97
|
+
});
|
|
98
|
+
return { kit_id: kitId, kit_hash: kitHash, files, manifest_path: manifestPath, dry_run: false };
|
|
99
|
+
}
|
|
@@ -4,6 +4,13 @@ export interface KitDependencyEntry {
|
|
|
4
4
|
kit_id: string;
|
|
5
5
|
reason?: string;
|
|
6
6
|
}
|
|
7
|
+
export interface KitProvisionEntry {
|
|
8
|
+
id: string;
|
|
9
|
+
path: string;
|
|
10
|
+
target: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const PROVISION_MANIFEST_DIR = ".kontourai/flow-agents/provisions";
|
|
7
14
|
export interface KitWorkflowTriggerEntry {
|
|
8
15
|
id: string;
|
|
9
16
|
when: string;
|
|
@@ -25,6 +32,18 @@ export interface KitHookInfluenceExpectationEntry {
|
|
|
25
32
|
must_include_guidance: string[];
|
|
26
33
|
must_include_actions: string[];
|
|
27
34
|
}
|
|
35
|
+
export interface KitAgentSpawnTriggerGuards {
|
|
36
|
+
dedup_key: string;
|
|
37
|
+
cooldown_seconds: number;
|
|
38
|
+
daily_cap: number;
|
|
39
|
+
max_concurrent: number;
|
|
40
|
+
}
|
|
41
|
+
export interface KitAgentSpawnTriggerEntry {
|
|
42
|
+
id: string;
|
|
43
|
+
description: string;
|
|
44
|
+
spawns_agent_runs: boolean;
|
|
45
|
+
guards?: KitAgentSpawnTriggerGuards;
|
|
46
|
+
}
|
|
28
47
|
export type KitSkillRole = "entrypoint" | "profile" | "step" | "shared-primitive" | "extension";
|
|
29
48
|
export interface KitSkillRoleEntry {
|
|
30
49
|
skill_id: string;
|
|
@@ -61,6 +80,29 @@ export declare function parseKitHookInfluenceExpectations(manifest: Record<strin
|
|
|
61
80
|
entries: KitHookInfluenceExpectationEntry[];
|
|
62
81
|
errors: string[];
|
|
63
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* Parse and shape-validate a kit manifest's optional `agent_spawn_triggers` field:
|
|
85
|
+
* perimeter trigger surfaces (check failures, schedules, watchers) that spawn agent
|
|
86
|
+
* runs, plus their guard config. Contract: context/contracts/trigger-guards.md.
|
|
87
|
+
*
|
|
88
|
+
* Shape rules (ERRORS):
|
|
89
|
+
* - `agent_spawn_triggers` (if present) must be an array of objects.
|
|
90
|
+
* - `id` must match the workflow-trigger identifier pattern and be unique.
|
|
91
|
+
* - `description` must be a non-empty string.
|
|
92
|
+
* - `spawns_agent_runs` must be a boolean.
|
|
93
|
+
* - `guards` (if present) must be an object with exactly the four guard fields when
|
|
94
|
+
* complete: `dedup_key` non-empty string; `cooldown_seconds`, `daily_cap`,
|
|
95
|
+
* `max_concurrent` integers >= 1. Unknown guard fields are errors.
|
|
96
|
+
*
|
|
97
|
+
* Guard-completeness (WARNINGS, never errors — declaration-first rollout, #664):
|
|
98
|
+
* - an entry with `spawns_agent_runs: true` and missing or incomplete `guards`
|
|
99
|
+
* produces a warning naming the missing guard fields and the contract doc.
|
|
100
|
+
*/
|
|
101
|
+
export declare function parseKitAgentSpawnTriggers(manifest: Record<string, unknown>, manifestPath: string): {
|
|
102
|
+
entries: KitAgentSpawnTriggerEntry[];
|
|
103
|
+
errors: string[];
|
|
104
|
+
warnings: string[];
|
|
105
|
+
};
|
|
64
106
|
export declare function parseKitSkillRoles(manifest: Record<string, unknown>, manifestPath: string): {
|
|
65
107
|
entries: KitSkillRoleEntry[];
|
|
66
108
|
errors: string[];
|
|
@@ -126,4 +168,14 @@ export interface KitTargetsResult {
|
|
|
126
168
|
*/
|
|
127
169
|
export declare function deriveKitTargets(manifest: Record<string, unknown>, kitDir?: string, sourceRoot?: string): Promise<KitTargetsResult>;
|
|
128
170
|
export declare function validateKitRepository(kitDir: string): Promise<string[]>;
|
|
171
|
+
/**
|
|
172
|
+
* Repository validation with a non-blocking warnings channel alongside the blocking
|
|
173
|
+
* errors `validateKitRepository` has always returned. Warnings are advisory quality
|
|
174
|
+
* findings (today: an agent-spawning trigger surface declared without complete guard
|
|
175
|
+
* config — context/contracts/trigger-guards.md); they never fail validation.
|
|
176
|
+
*/
|
|
177
|
+
export declare function validateKitRepositoryDiagnostics(kitDir: string): Promise<{
|
|
178
|
+
errors: string[];
|
|
179
|
+
warnings: string[];
|
|
180
|
+
}>;
|
|
129
181
|
export declare function assertKitRepository(kitDir: string): Promise<Record<string, unknown>>;
|
|
@@ -5,19 +5,24 @@ import { parseKitFlowStepActions, workflowTriggerIdentifier } from "./action-met
|
|
|
5
5
|
import { validateActionRepositoryMetadata } from "./action-repository-validation.js";
|
|
6
6
|
export { isObservableBuilderArtifactRef, isSafeBuilderArtifactRef, parseKitFlowStepActions } from "./action-metadata.js";
|
|
7
7
|
// Extension-only asset classes: validated by Flow Agents. Flows are validated by @kontourai/flow.
|
|
8
|
-
const EXTENSION_ASSET_CLASSES = ["skills", "docs", "adapters", "evals", "assets"];
|
|
8
|
+
const EXTENSION_ASSET_CLASSES = ["skills", "docs", "adapters", "evals", "assets", "provisions"];
|
|
9
9
|
// Core container fields owned by kontourai/flow (flow-kit-container.schema.json).
|
|
10
10
|
// agent-extension fields are skills, docs, adapters, evals, assets.
|
|
11
11
|
const CORE_CONTAINER_FIELDS = new Set(["schema_version", "id", "name", "description", "product_name", "flows"]);
|
|
12
|
-
const AGENT_EXTENSION_CLASSES = new Set(["skills", "docs", "adapters", "evals", "assets"]);
|
|
12
|
+
const AGENT_EXTENSION_CLASSES = new Set(["skills", "docs", "adapters", "evals", "assets", "provisions"]);
|
|
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
16
|
// dependencies (extension-layer ownership; see docs/adr/0019-kit-dependency-ownership.md),
|
|
17
17
|
// workflow_triggers / hook_influence_expectations declare kit-owned runtime influence,
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
18
|
+
// agent_spawn_triggers declares perimeter trigger surfaces that spawn agent runs plus
|
|
19
|
+
// their guard config (context/contracts/trigger-guards.md), and first_party is legacy
|
|
20
|
+
// catalog/marketplace metadata. It does not grant runtime capability or steering privilege.
|
|
21
|
+
const KNOWN_METADATA_FIELDS = new Set(["dependencies", "workflow_triggers", "hook_influence_expectations", "flow_step_actions", "skill_roles", "first_party", "agent_spawn_triggers"]);
|
|
22
|
+
// Consumer-repo-relative directory (posix, lowercase) where the engine writes its own
|
|
23
|
+
// per-kit provision manifest. Reserved: a provision may not target inside it. Shared with
|
|
24
|
+
// provision.ts so the reservation and the actual manifest write stay in agreement.
|
|
25
|
+
export const PROVISION_MANIFEST_DIR = ".kontourai/flow-agents/provisions";
|
|
21
26
|
/**
|
|
22
27
|
* Parse and shape-validate a kit manifest's `dependencies` field (Flow Agents
|
|
23
28
|
* extension-layer metadata; see docs/adr/0019-kit-dependency-ownership.md).
|
|
@@ -221,6 +226,120 @@ export function parseKitHookInfluenceExpectations(manifest, manifestPath) {
|
|
|
221
226
|
});
|
|
222
227
|
return { entries, errors };
|
|
223
228
|
}
|
|
229
|
+
const AGENT_SPAWN_TRIGGER_GUARD_FIELDS = ["dedup_key", "cooldown_seconds", "daily_cap", "max_concurrent"];
|
|
230
|
+
/**
|
|
231
|
+
* Parse and shape-validate a kit manifest's optional `agent_spawn_triggers` field:
|
|
232
|
+
* perimeter trigger surfaces (check failures, schedules, watchers) that spawn agent
|
|
233
|
+
* runs, plus their guard config. Contract: context/contracts/trigger-guards.md.
|
|
234
|
+
*
|
|
235
|
+
* Shape rules (ERRORS):
|
|
236
|
+
* - `agent_spawn_triggers` (if present) must be an array of objects.
|
|
237
|
+
* - `id` must match the workflow-trigger identifier pattern and be unique.
|
|
238
|
+
* - `description` must be a non-empty string.
|
|
239
|
+
* - `spawns_agent_runs` must be a boolean.
|
|
240
|
+
* - `guards` (if present) must be an object with exactly the four guard fields when
|
|
241
|
+
* complete: `dedup_key` non-empty string; `cooldown_seconds`, `daily_cap`,
|
|
242
|
+
* `max_concurrent` integers >= 1. Unknown guard fields are errors.
|
|
243
|
+
*
|
|
244
|
+
* Guard-completeness (WARNINGS, never errors — declaration-first rollout, #664):
|
|
245
|
+
* - an entry with `spawns_agent_runs: true` and missing or incomplete `guards`
|
|
246
|
+
* produces a warning naming the missing guard fields and the contract doc.
|
|
247
|
+
*/
|
|
248
|
+
export function parseKitAgentSpawnTriggers(manifest, manifestPath) {
|
|
249
|
+
const entries = [];
|
|
250
|
+
const errors = [];
|
|
251
|
+
const warnings = [];
|
|
252
|
+
const raw = manifest.agent_spawn_triggers;
|
|
253
|
+
if (raw === undefined)
|
|
254
|
+
return { entries, errors, warnings };
|
|
255
|
+
if (!Array.isArray(raw)) {
|
|
256
|
+
errors.push(`${manifestPath}: .agent_spawn_triggers must be a list`);
|
|
257
|
+
return { entries, errors, warnings };
|
|
258
|
+
}
|
|
259
|
+
const fields = new Set(["id", "description", "spawns_agent_runs", "guards"]);
|
|
260
|
+
const seen = new Set();
|
|
261
|
+
raw.forEach((entry, index) => {
|
|
262
|
+
if (typeof entry !== "object" || entry === null) {
|
|
263
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}] must be an object`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const record = entry;
|
|
267
|
+
const unknown = Object.keys(record).filter((field) => !fields.has(field));
|
|
268
|
+
if (unknown.length > 0) {
|
|
269
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}] contains unsupported field(s): ${unknown.join(", ")}`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const id = record.id;
|
|
273
|
+
if (!workflowTriggerIdentifier(id)) {
|
|
274
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].id must match ^[a-z0-9]+(?:[.-][a-z0-9]+)*$`);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (seen.has(id)) {
|
|
278
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].id duplicates '${id}'`);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
seen.add(id);
|
|
282
|
+
if (typeof record.description !== "string" || !record.description.trim()) {
|
|
283
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].description must be a non-empty string`);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (typeof record.spawns_agent_runs !== "boolean") {
|
|
287
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].spawns_agent_runs must be a boolean`);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
let guards;
|
|
291
|
+
let guardsShapeValid = true;
|
|
292
|
+
const missingGuardFields = [];
|
|
293
|
+
if (record.guards !== undefined) {
|
|
294
|
+
if (typeof record.guards !== "object" || record.guards === null || Array.isArray(record.guards)) {
|
|
295
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].guards must be an object when present`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const guardRecord = record.guards;
|
|
299
|
+
const guardFieldSet = new Set(AGENT_SPAWN_TRIGGER_GUARD_FIELDS);
|
|
300
|
+
const unknownGuards = Object.keys(guardRecord).filter((field) => !guardFieldSet.has(field));
|
|
301
|
+
if (unknownGuards.length > 0) {
|
|
302
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].guards contains unsupported field(s): ${unknownGuards.join(", ")}`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (guardRecord.dedup_key !== undefined && (typeof guardRecord.dedup_key !== "string" || !guardRecord.dedup_key.trim())) {
|
|
306
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].guards.dedup_key must be a non-empty string`);
|
|
307
|
+
guardsShapeValid = false;
|
|
308
|
+
}
|
|
309
|
+
for (const field of ["cooldown_seconds", "daily_cap", "max_concurrent"]) {
|
|
310
|
+
const value = guardRecord[field];
|
|
311
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value < 1)) {
|
|
312
|
+
errors.push(`${manifestPath}: agent_spawn_triggers[${index}].guards.${field} must be an integer >= 1`);
|
|
313
|
+
guardsShapeValid = false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (!guardsShapeValid)
|
|
317
|
+
return;
|
|
318
|
+
for (const field of AGENT_SPAWN_TRIGGER_GUARD_FIELDS) {
|
|
319
|
+
if (guardRecord[field] === undefined)
|
|
320
|
+
missingGuardFields.push(field);
|
|
321
|
+
}
|
|
322
|
+
if (missingGuardFields.length === 0) {
|
|
323
|
+
guards = {
|
|
324
|
+
dedup_key: guardRecord.dedup_key,
|
|
325
|
+
cooldown_seconds: guardRecord.cooldown_seconds,
|
|
326
|
+
daily_cap: guardRecord.daily_cap,
|
|
327
|
+
max_concurrent: guardRecord.max_concurrent,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
missingGuardFields.push(...AGENT_SPAWN_TRIGGER_GUARD_FIELDS);
|
|
333
|
+
}
|
|
334
|
+
if (record.spawns_agent_runs === true && missingGuardFields.length > 0) {
|
|
335
|
+
warnings.push(`${manifestPath}: agent_spawn_triggers[${index}] ('${id}') spawns agent runs without complete guard config` +
|
|
336
|
+
` (missing: ${missingGuardFields.join(", ")}); declare dedup_key, cooldown_seconds, daily_cap, and max_concurrent` +
|
|
337
|
+
` per context/contracts/trigger-guards.md`);
|
|
338
|
+
}
|
|
339
|
+
entries.push({ id, description: record.description, spawns_agent_runs: record.spawns_agent_runs, ...(guards ? { guards } : {}) });
|
|
340
|
+
});
|
|
341
|
+
return { entries, errors, warnings };
|
|
342
|
+
}
|
|
224
343
|
export function parseKitSkillRoles(manifest, manifestPath) {
|
|
225
344
|
const entries = [];
|
|
226
345
|
const errors = [];
|
|
@@ -393,7 +512,17 @@ export async function deriveKitTargets(manifest, kitDir = "", sourceRoot = proce
|
|
|
393
512
|
};
|
|
394
513
|
}
|
|
395
514
|
export async function validateKitRepository(kitDir) {
|
|
515
|
+
return (await validateKitRepositoryDiagnostics(kitDir)).errors;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Repository validation with a non-blocking warnings channel alongside the blocking
|
|
519
|
+
* errors `validateKitRepository` has always returned. Warnings are advisory quality
|
|
520
|
+
* findings (today: an agent-spawning trigger surface declared without complete guard
|
|
521
|
+
* config — context/contracts/trigger-guards.md); they never fail validation.
|
|
522
|
+
*/
|
|
523
|
+
export async function validateKitRepositoryDiagnostics(kitDir) {
|
|
396
524
|
const errors = [];
|
|
525
|
+
const warnings = [];
|
|
397
526
|
const manifestPath = path.join(kitDir, "kit.json");
|
|
398
527
|
let manifest;
|
|
399
528
|
try {
|
|
@@ -401,14 +530,16 @@ export async function validateKitRepository(kitDir) {
|
|
|
401
530
|
}
|
|
402
531
|
catch (error) {
|
|
403
532
|
errors.push(`${manifestPath}: invalid JSON: ${error.message}`);
|
|
404
|
-
return errors;
|
|
533
|
+
return { errors, warnings };
|
|
405
534
|
}
|
|
406
535
|
errors.push(...await delegateCoreContainerValidation(kitDir, manifest));
|
|
407
536
|
errors.push(...validateExtensionAssets(kitDir, manifestPath, manifest));
|
|
408
|
-
|
|
537
|
+
const metadata = validateAgentMetadata(kitDir, manifestPath, manifest);
|
|
538
|
+
errors.push(...metadata.errors);
|
|
539
|
+
warnings.push(...metadata.warnings);
|
|
409
540
|
if (manifest.first_party !== undefined && typeof manifest.first_party !== "boolean")
|
|
410
541
|
errors.push(`${manifestPath}: .first_party must be a boolean when present`);
|
|
411
|
-
return errors;
|
|
542
|
+
return { errors, warnings };
|
|
412
543
|
}
|
|
413
544
|
function validateExtensionAssets(kitDir, manifestPath, manifest) {
|
|
414
545
|
const errors = [];
|
|
@@ -429,11 +560,15 @@ function validateExtensionAssets(kitDir, manifestPath, manifest) {
|
|
|
429
560
|
const record = entry;
|
|
430
561
|
const id = record.id;
|
|
431
562
|
const rel = record.path;
|
|
563
|
+
const kitId = typeof manifest.id === "string" ? manifest.id : "";
|
|
432
564
|
if (typeof id === "string") {
|
|
433
565
|
if (seen.has(id))
|
|
434
566
|
errors.push(`${manifestPath}: ${section}[${index}].id duplicates`);
|
|
435
567
|
seen.add(id);
|
|
436
568
|
}
|
|
569
|
+
if (section === "provisions" && (typeof id !== "string" || !kitId || !id.startsWith(`${kitId}.`))) {
|
|
570
|
+
errors.push(`${manifestPath}: provisions[${index}].id must be prefixed with '${kitId}.'`);
|
|
571
|
+
}
|
|
437
572
|
if (typeof rel !== "string" || !rel) {
|
|
438
573
|
errors.push(`${manifestPath}: ${section}[${index}].path must be a string`);
|
|
439
574
|
return;
|
|
@@ -442,6 +577,10 @@ function validateExtensionAssets(kitDir, manifestPath, manifest) {
|
|
|
442
577
|
errors.push(`${manifestPath}: ${section}[${index}].path must be relative`);
|
|
443
578
|
return;
|
|
444
579
|
}
|
|
580
|
+
if (rel.replace(/\\/g, "/").split("/").includes("..")) {
|
|
581
|
+
errors.push(`${manifestPath}: ${section}[${index}].path must not contain traversal segments`);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
445
584
|
const resolved = path.resolve(kitDir, rel);
|
|
446
585
|
const root = path.resolve(kitDir);
|
|
447
586
|
if (resolved !== root && !resolved.startsWith(`${root}${path.sep}`)) {
|
|
@@ -451,12 +590,73 @@ function validateExtensionAssets(kitDir, manifestPath, manifest) {
|
|
|
451
590
|
if (!fs.existsSync(resolved)) {
|
|
452
591
|
errors.push(`${manifestPath}: ${section}[${index}].path points at missing asset: ${rel}`);
|
|
453
592
|
}
|
|
593
|
+
else if (section === "provisions") {
|
|
594
|
+
if (!fs.statSync(resolved).isFile()) {
|
|
595
|
+
errors.push(`${manifestPath}: provisions[${index}].path must point at a file: ${rel}`);
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
// A provisioned source is copied byte-for-byte into a consumer repo, so a symlink that
|
|
599
|
+
// resolves outside the kit would exfiltrate arbitrary readable host files. Require the
|
|
600
|
+
// link-resolved real path to stay inside the kit.
|
|
601
|
+
const realResolved = fs.realpathSync(resolved);
|
|
602
|
+
const realRoot = fs.realpathSync(root);
|
|
603
|
+
if (realResolved !== realRoot && !realResolved.startsWith(`${realRoot}${path.sep}`)) {
|
|
604
|
+
errors.push(`${manifestPath}: provisions[${index}].path must not resolve outside the kit directory`);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
const rawProvisions = manifest.provisions;
|
|
611
|
+
if (Array.isArray(rawProvisions)) {
|
|
612
|
+
const targets = new Set();
|
|
613
|
+
rawProvisions.forEach((entry, index) => {
|
|
614
|
+
if (typeof entry !== "object" || entry === null)
|
|
615
|
+
return;
|
|
616
|
+
const record = entry;
|
|
617
|
+
if (record.description !== undefined && typeof record.description !== "string") {
|
|
618
|
+
errors.push(`${manifestPath}: provisions[${index}].description must be a string when present`);
|
|
619
|
+
}
|
|
620
|
+
const target = record.target;
|
|
621
|
+
if (typeof target !== "string" || target.trim().length === 0) {
|
|
622
|
+
errors.push(`${manifestPath}: provisions[${index}].target must be a non-empty string`);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
if (path.isAbsolute(target) || path.win32.isAbsolute(target)) {
|
|
626
|
+
errors.push(`${manifestPath}: provisions[${index}].target must be relative`);
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const segments = target.replace(/\\/g, "/").split("/");
|
|
630
|
+
if (segments.includes("..")) {
|
|
631
|
+
errors.push(`${manifestPath}: provisions[${index}].target must not contain traversal segments`);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const normalized = path.posix.normalize(segments.join("/"));
|
|
635
|
+
if (normalized === "." || normalized.startsWith("..")) {
|
|
636
|
+
errors.push(`${manifestPath}: provisions[${index}].target must stay inside the consumer repository`);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
// Case-fold reserved-directory and collision checks: on a case-insensitive filesystem
|
|
640
|
+
// `.GIT/` still lands in the real `.git`, and README.md/readme.md still collide.
|
|
641
|
+
const lowered = normalized.toLowerCase();
|
|
642
|
+
if (lowered === ".git" || lowered.startsWith(".git/")) {
|
|
643
|
+
errors.push(`${manifestPath}: provisions[${index}].target must not be inside .git`);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (lowered === PROVISION_MANIFEST_DIR || lowered.startsWith(`${PROVISION_MANIFEST_DIR}/`)) {
|
|
647
|
+
errors.push(`${manifestPath}: provisions[${index}].target must not be inside the provision manifest namespace (${PROVISION_MANIFEST_DIR}/)`);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (targets.has(lowered))
|
|
651
|
+
errors.push(`${manifestPath}: provisions[${index}].target duplicates '${normalized}'`);
|
|
652
|
+
targets.add(lowered);
|
|
454
653
|
});
|
|
455
654
|
}
|
|
456
655
|
return errors;
|
|
457
656
|
}
|
|
458
657
|
function validateAgentMetadata(kitDir, manifestPath, manifest) {
|
|
459
658
|
const errors = [];
|
|
659
|
+
const warnings = [];
|
|
460
660
|
const depResult = parseKitDependencies(manifest, manifestPath);
|
|
461
661
|
for (const err of depResult.errors)
|
|
462
662
|
errors.push(err);
|
|
@@ -466,6 +666,11 @@ function validateAgentMetadata(kitDir, manifestPath, manifest) {
|
|
|
466
666
|
const hookExpectationResult = parseKitHookInfluenceExpectations(manifest, manifestPath);
|
|
467
667
|
for (const err of hookExpectationResult.errors)
|
|
468
668
|
errors.push(err);
|
|
669
|
+
const agentSpawnTriggerResult = parseKitAgentSpawnTriggers(manifest, manifestPath);
|
|
670
|
+
for (const err of agentSpawnTriggerResult.errors)
|
|
671
|
+
errors.push(err);
|
|
672
|
+
for (const warning of agentSpawnTriggerResult.warnings)
|
|
673
|
+
warnings.push(warning);
|
|
469
674
|
const flowStepActionResult = parseKitFlowStepActions(manifest, manifestPath);
|
|
470
675
|
for (const err of flowStepActionResult.errors)
|
|
471
676
|
errors.push(err);
|
|
@@ -475,7 +680,7 @@ function validateAgentMetadata(kitDir, manifestPath, manifest) {
|
|
|
475
680
|
if ((manifest.skill_roles !== undefined || manifest.flow_step_actions !== undefined) && skillRoleResult.errors.length === 0) {
|
|
476
681
|
errors.push(...validateActionRepositoryMetadata({ kitDir, manifestPath, manifest, actions: flowStepActionResult.entries, skillRoles: skillRoleResult.entries }));
|
|
477
682
|
}
|
|
478
|
-
return errors;
|
|
683
|
+
return { errors, warnings };
|
|
479
684
|
}
|
|
480
685
|
export async function assertKitRepository(kitDir) {
|
|
481
686
|
const errors = await validateKitRepository(kitDir);
|
|
@@ -3,7 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { atomicCopyFile, atomicWriteJson, ensureSafeDirectory, readJson, relPath } from "./lib/fs.js";
|
|
4
4
|
import { flowAgentsArtifactRoot } from "./lib/local-artifact-root.js";
|
|
5
5
|
import { parseKitDependencies, parseKitHookInfluenceExpectations, parseKitWorkflowTriggers } from "./flow-kit/validate.js";
|
|
6
|
-
const ASSET_CLASSES = ["flows", "skills", "docs", "adapters", "evals", "assets"];
|
|
6
|
+
const ASSET_CLASSES = ["flows", "skills", "docs", "adapters", "evals", "assets", "provisions"];
|
|
7
7
|
const KIT_ID_RE = /^[a-z][a-z0-9-]*$/;
|
|
8
8
|
function assetPath(root, value) {
|
|
9
9
|
if (path.isAbsolute(value))
|
|
@@ -42,7 +42,36 @@ Execution may upgrade to a stronger mode when risk increases. Downgrades require
|
|
|
42
42
|
- Independent tasks with no shared files can run in the same wave.
|
|
43
43
|
- Shared files, generated artifacts, migrations, and cross-cutting contracts should be serialized unless the plan gives explicit file ownership.
|
|
44
44
|
- Worker delegation must name the exact worker role (`tool-worker`) rather than spawning an unnamed/default implementation agent.
|
|
45
|
-
- After each wave,
|
|
45
|
+
- After each wave, reconcile results against the wave manifest (below), check conflicts, and update the session artifact before starting the next wave.
|
|
46
|
+
|
|
47
|
+
## Wave Manifest And Reconciliation
|
|
48
|
+
|
|
49
|
+
Fan-out collection is machine-checkable, not prose. A reduce step that silently
|
|
50
|
+
drops a worker's stream is worse than one that errors.
|
|
51
|
+
|
|
52
|
+
- **Declare before dispatch.** Before dispatching a wave that delegates work,
|
|
53
|
+
declare it in the session's `waves.json` sidecar (schema:
|
|
54
|
+
`schemas/workflow-waves.schema.json`): `wave_id`, owning step, and one
|
|
55
|
+
`expected_workers` entry per worker. The expected count (M) must exist before
|
|
56
|
+
any result arrives.
|
|
57
|
+
- **One terminal record per worker.** Each worker lands exactly one terminal
|
|
58
|
+
status record: `completed`, `failed`, or `blocked`. Duplicate records and
|
|
59
|
+
undeclared reporters are validation errors.
|
|
60
|
+
- **Reconcile at wave close.** The orchestrator's collect step is
|
|
61
|
+
reconcile-against-manifest: record every declared worker that has no terminal
|
|
62
|
+
record as `not_reported` — never silently absorb a missing worker — then
|
|
63
|
+
record the wave's `reconciliation` with `expected_count` M, `reported_count`
|
|
64
|
+
N, and an explicit "N of M reported" summary naming the `not_reported`
|
|
65
|
+
workers (for example "2 of 3 reported; worker-3 not_reported").
|
|
66
|
+
- **Incomplete is visible, never silent.** A wave is `complete` only when N
|
|
67
|
+
equals M. An incomplete wave stays visible data and routes to re-dispatch, a
|
|
68
|
+
blocker report, or an explicit accepted gap; it must never be treated as
|
|
69
|
+
complete because the missing worker was forgotten.
|
|
70
|
+
- **Enforcement boundary (slice 1).** `validate-workflow-artifacts` enforces
|
|
71
|
+
the shape and the cross-record arithmetic (counts, exactly-one-record,
|
|
72
|
+
undeclared reporters, impossible `complete` claims) as data-level validation.
|
|
73
|
+
Stop-hook refusal of wave completion is #663 part 3 (slice 2), deferred until
|
|
74
|
+
the hook correctness issues (#453/#450/#494) are resolved.
|
|
46
75
|
|
|
47
76
|
## Delegation: Model Routing
|
|
48
77
|
|
|
@@ -100,6 +100,10 @@ npm run workflow:sidecar -- import-critique .kontourai/flow-agents/<slug> \
|
|
|
100
100
|
--reviewer tool-code-reviewer
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
+
A security-review finding is recorded as a structured verdict + reference — `{severity, file_refs: ["path:line"], description: "<one-line weakness>"}` — not as reproduced exploit payloads or copied vulnerable-code blocks. A precise reference is sufficient evidence; the fuller remediation detail belongs in the fix pass, not the recorded finding. This keeps security findings recordable even when the reviewer runtime's provider content-filters exploit-shaped prose.
|
|
104
|
+
|
|
105
|
+
Recording a review requires a reviewer identity distinct from the active implementation-assignment actor (anti-self-review). The identity is derived from the runtime actor, so an orchestrator that implemented cannot also review under the same actor: run the reviewer under a distinct actor — set `FLOW_AGENTS_ACTOR=<reviewer-id>` on the reviewing process, or run it in a separate runtime session.
|
|
106
|
+
|
|
103
107
|
## Gate Rules
|
|
104
108
|
|
|
105
109
|
- Critical or high findings block delivery until fixed, accepted by the user, deferred with explicit rationale, or marked false positive.
|