@devtrack-solution/codesdd 1.2.2 → 1.2.3
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/.sdd/skills/curated/api-clean-flask-langgraph/SKILL.md +17 -17
- package/.sdd/skills/curated/devtrack-api/SKILL.md +160 -28
- package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +1 -1
- package/.sdd/skills/curated/devtrack-api/references/architecture-governance.md +8 -7
- package/.sdd/skills/curated/devtrack-api/references/consumer-sync-policy.md +93 -0
- package/.sdd/skills/curated/devtrack-api/references/contract-pack.yaml +317 -0
- package/.sdd/skills/curated/devtrack-api/references/field-validation-protocol.md +95 -0
- package/.sdd/skills/curated/devtrack-api/references/foundation-layout.md +295 -0
- package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +4 -4
- package/.sdd/skills/curated/devtrack-api/references/imports-lint.md +4 -0
- package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +2 -2
- package/LICENSE +1 -1
- package/README.md +243 -51
- package/bin/codesdd.js +3 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +11 -558
- package/dist/cli/program.d.ts +14 -0
- package/dist/cli/program.js +645 -0
- package/dist/commands/change.js +5 -5
- package/dist/commands/completion.d.ts +1 -1
- package/dist/commands/completion.js +9 -2
- package/dist/commands/config.js +159 -20
- package/dist/commands/feedback.js +1 -1
- package/dist/commands/schema.d.ts +63 -0
- package/dist/commands/schema.js +12 -12
- package/dist/commands/sdd/backlog.d.ts +3 -0
- package/dist/commands/sdd/backlog.js +54 -0
- package/dist/commands/sdd/execution.js +147 -16
- package/dist/commands/sdd/plugin.d.ts +3 -0
- package/dist/commands/sdd/plugin.js +153 -0
- package/dist/commands/sdd/shared.js +2 -23
- package/dist/commands/sdd/skills.js +7 -0
- package/dist/commands/sdd.js +69 -12
- package/dist/commands/spec.js +9 -9
- package/dist/commands/validate.js +6 -6
- package/dist/commands/workflow/instructions.js +6 -6
- package/dist/commands/workflow/new-change.js +3 -3
- package/dist/commands/workflow/shared.d.ts +1 -1
- package/dist/commands/workflow/shared.js +4 -4
- package/dist/core/archive.js +15 -5
- package/dist/core/artifact-graph/instruction-loader.d.ts +1 -1
- package/dist/core/artifact-graph/instruction-loader.js +3 -3
- package/dist/core/artifact-graph/resolver.d.ts +4 -4
- package/dist/core/artifact-graph/resolver.js +6 -6
- package/dist/core/branding.js +3 -3
- package/dist/core/cli/command-matrix.js +10 -1
- package/dist/core/cli-command-quality.d.ts +27 -0
- package/dist/core/cli-command-quality.js +171 -0
- package/dist/core/command-generation/adapters/costrict.d.ts +1 -1
- package/dist/core/command-generation/adapters/costrict.js +2 -2
- package/dist/core/command-generation/types.d.ts +1 -1
- package/dist/core/completions/command-registry.d.ts +1 -1
- package/dist/core/completions/command-registry.js +155 -12
- package/dist/core/completions/completion-provider.d.ts +14 -1
- package/dist/core/completions/completion-provider.js +29 -1
- package/dist/core/completions/generators/bash-generator.d.ts +1 -1
- package/dist/core/completions/generators/bash-generator.js +20 -12
- package/dist/core/completions/generators/fish-generator.d.ts +9 -1
- package/dist/core/completions/generators/fish-generator.js +39 -25
- package/dist/core/completions/generators/powershell-generator.d.ts +1 -1
- package/dist/core/completions/generators/powershell-generator.js +21 -11
- package/dist/core/completions/generators/zsh-generator.d.ts +3 -6
- package/dist/core/completions/generators/zsh-generator.js +21 -42
- package/dist/core/completions/installers/bash-installer.js +6 -6
- package/dist/core/completions/installers/fish-installer.js +1 -1
- package/dist/core/completions/installers/powershell-installer.js +14 -14
- package/dist/core/completions/installers/zsh-installer.d.ts +7 -1
- package/dist/core/completions/installers/zsh-installer.js +36 -8
- package/dist/core/completions/templates/bash-templates.d.ts +1 -1
- package/dist/core/completions/templates/bash-templates.js +12 -6
- package/dist/core/completions/templates/fish-templates.d.ts +2 -2
- package/dist/core/completions/templates/fish-templates.js +20 -9
- package/dist/core/completions/templates/powershell-templates.d.ts +1 -1
- package/dist/core/completions/templates/powershell-templates.js +13 -4
- package/dist/core/completions/templates/zsh-templates.d.ts +1 -1
- package/dist/core/completions/templates/zsh-templates.js +18 -9
- package/dist/core/config-schema.d.ts +3 -1
- package/dist/core/config-schema.js +26 -1
- package/dist/core/config.d.ts +3 -3
- package/dist/core/config.js +4 -4
- package/dist/core/global-config.d.ts +41 -12
- package/dist/core/global-config.js +344 -27
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/init.d.ts +6 -1
- package/dist/core/init.js +99 -77
- package/dist/core/legacy-cleanup.d.ts +17 -17
- package/dist/core/legacy-cleanup.js +96 -79
- package/dist/core/list.js +18 -4
- package/dist/core/migration.d.ts +3 -1
- package/dist/core/migration.js +7 -8
- package/dist/core/parsers/change-parser.js +1 -1
- package/dist/core/parsers/markdown-parser.js +2 -2
- package/dist/core/profile-sync-drift.d.ts +1 -1
- package/dist/core/profile-sync-drift.js +13 -13
- package/dist/core/project-config.d.ts +4 -4
- package/dist/core/project-config.js +11 -11
- package/dist/core/schemas/change.schema.d.ts +1 -1
- package/dist/core/schemas/change.schema.js +1 -1
- package/dist/core/schemas/spec.schema.d.ts +1 -1
- package/dist/core/schemas/spec.schema.js +1 -1
- package/dist/core/sdd/adr.js +23 -1
- package/dist/core/sdd/agent-binding.d.ts +346 -0
- package/dist/core/sdd/agent-binding.js +343 -0
- package/dist/core/sdd/backlog-cli.d.ts +16 -0
- package/dist/core/sdd/backlog-cli.js +146 -0
- package/dist/core/sdd/backlog-conflict-policy.d.ts +58 -0
- package/dist/core/sdd/backlog-conflict-policy.js +230 -0
- package/dist/core/sdd/backlog-projection.d.ts +8 -0
- package/dist/core/sdd/backlog-projection.js +89 -0
- package/dist/core/sdd/backlog-provider-contract.d.ts +252 -0
- package/dist/core/sdd/backlog-provider-contract.js +158 -0
- package/dist/core/sdd/bootstrap.js +2 -2
- package/dist/core/sdd/check.d.ts +42 -0
- package/dist/core/sdd/check.js +22 -22
- package/dist/core/sdd/contract.d.ts +13 -0
- package/dist/core/sdd/contract.js +36 -0
- package/dist/core/sdd/coordination/coordination-adapters.d.ts +38 -0
- package/dist/core/sdd/coordination/coordination-adapters.js +139 -1
- package/dist/core/sdd/deepagent-contracts.d.ts +276 -0
- package/dist/core/sdd/deepagent-contracts.js +173 -0
- package/dist/core/sdd/deepagents/adr-governor.d.ts +2 -0
- package/dist/core/sdd/deepagents/adr-governor.js +30 -0
- package/dist/core/sdd/deepagents/backend.d.ts +63 -0
- package/dist/core/sdd/deepagents/backend.js +174 -0
- package/dist/core/sdd/deepagents/codesdd-tools.d.ts +39 -0
- package/dist/core/sdd/deepagents/codesdd-tools.js +83 -0
- package/dist/core/sdd/deepagents/evidence-mapper.d.ts +86 -0
- package/dist/core/sdd/deepagents/evidence-mapper.js +178 -0
- package/dist/core/sdd/deepagents/model-provider.d.ts +53 -0
- package/dist/core/sdd/deepagents/model-provider.js +379 -0
- package/dist/core/sdd/deepagents/policy-enforcement.d.ts +30 -0
- package/dist/core/sdd/deepagents/policy-enforcement.js +90 -0
- package/dist/core/sdd/deepagents/policy.d.ts +75 -0
- package/dist/core/sdd/deepagents/policy.js +358 -0
- package/dist/core/sdd/deepagents/quality-witness.d.ts +3 -0
- package/dist/core/sdd/deepagents/quality-witness.js +77 -0
- package/dist/core/sdd/deepagents/reversa-subagents.d.ts +75 -0
- package/dist/core/sdd/deepagents/reversa-subagents.js +182 -0
- package/dist/core/sdd/deepagents/runtime-factory.d.ts +90 -0
- package/dist/core/sdd/deepagents/runtime-factory.js +231 -0
- package/dist/core/sdd/deepagents/runtime-loader.d.ts +16 -0
- package/dist/core/sdd/deepagents/runtime-loader.js +65 -0
- package/dist/core/sdd/default-bootstrap-files.d.ts +2 -2
- package/dist/core/sdd/default-bootstrap-files.js +36 -2
- package/dist/core/sdd/default-skills.d.ts +30 -0
- package/dist/core/sdd/default-skills.js +181 -5
- package/dist/core/sdd/devtrack-api-appliance.d.ts +84 -0
- package/dist/core/sdd/devtrack-api-appliance.js +257 -0
- package/dist/core/sdd/devtrack-api-architecture.d.ts +31 -0
- package/dist/core/sdd/devtrack-api-architecture.js +608 -0
- package/dist/core/sdd/devtrack-api-import-boundary.d.ts +19 -0
- package/dist/core/sdd/devtrack-api-import-boundary.js +32 -0
- package/dist/core/sdd/diagnose.d.ts +59 -0
- package/dist/core/sdd/diagnose.js +37 -37
- package/dist/core/sdd/docs-sync.js +33 -5
- package/dist/core/sdd/domain/post-active-validation.d.ts +7 -0
- package/dist/core/sdd/domain/post-active-validation.js +61 -0
- package/dist/core/sdd/domain/transition-engine.js +1 -0
- package/dist/core/sdd/entity-reference.d.ts +5 -0
- package/dist/core/sdd/entity-reference.js +22 -0
- package/dist/core/sdd/governance-backfill.d.ts +31 -0
- package/dist/core/sdd/governance-backfill.js +359 -0
- package/dist/core/sdd/governance-parser.d.ts +21 -0
- package/dist/core/sdd/governance-parser.js +91 -0
- package/dist/core/sdd/governance-schemas.d.ts +245 -0
- package/dist/core/sdd/governance-schemas.js +143 -0
- package/dist/core/sdd/{import-openspec.d.ts → import-legacy-spec.d.ts} +7 -7
- package/dist/core/sdd/{import-openspec.js → import-legacy-spec.js} +21 -29
- package/dist/core/sdd/init.d.ts +3 -0
- package/dist/core/sdd/init.js +6 -3
- package/dist/core/sdd/json-schema.js +100 -6
- package/dist/core/sdd/knowledge-graph.d.ts +45 -0
- package/dist/core/sdd/knowledge-graph.js +288 -0
- package/dist/core/sdd/legacy-operations.js +431 -43
- package/dist/core/sdd/lenses.d.ts +1 -0
- package/dist/core/sdd/lenses.js +29 -1
- package/dist/core/sdd/migrate-workspace.js +56 -2
- package/dist/core/sdd/migrate.d.ts +1 -1
- package/dist/core/sdd/migrate.js +36 -2
- package/dist/core/sdd/package-structure-gate.d.ts +83 -0
- package/dist/core/sdd/package-structure-gate.js +362 -0
- package/dist/core/sdd/parallel-feat-automation.d.ts +152 -0
- package/dist/core/sdd/parallel-feat-automation.js +212 -0
- package/dist/core/sdd/plugin-broker.d.ts +558 -0
- package/dist/core/sdd/plugin-broker.js +482 -0
- package/dist/core/sdd/plugin-certification.d.ts +79 -0
- package/dist/core/sdd/plugin-certification.js +453 -0
- package/dist/core/sdd/plugin-cli.d.ts +109 -0
- package/dist/core/sdd/plugin-cli.js +198 -0
- package/dist/core/sdd/plugin-evidence.d.ts +275 -0
- package/dist/core/sdd/plugin-evidence.js +307 -0
- package/dist/core/sdd/plugin-manifest.d.ts +164 -0
- package/dist/core/sdd/plugin-manifest.js +215 -0
- package/dist/core/sdd/plugin-policy-pack.d.ts +88 -0
- package/dist/core/sdd/plugin-policy-pack.js +236 -0
- package/dist/core/sdd/plugin-policy.d.ts +68 -0
- package/dist/core/sdd/plugin-policy.js +212 -0
- package/dist/core/sdd/plugin-registry.d.ts +311 -0
- package/dist/core/sdd/plugin-registry.js +138 -0
- package/dist/core/sdd/plugin-skill-binding.d.ts +151 -0
- package/dist/core/sdd/plugin-skill-binding.js +339 -0
- package/dist/core/sdd/quality-artifact-manifest-validator.d.ts +28 -0
- package/dist/core/sdd/quality-artifact-manifest-validator.js +167 -0
- package/dist/core/sdd/quality-evidence-renderer.d.ts +65 -0
- package/dist/core/sdd/quality-evidence-renderer.js +218 -0
- package/dist/core/sdd/quality-scenario-runner.d.ts +42 -0
- package/dist/core/sdd/quality-scenario-runner.js +613 -0
- package/dist/core/sdd/quality-validation.d.ts +547 -0
- package/dist/core/sdd/quality-validation.js +239 -0
- package/dist/core/sdd/resolve-project-root.d.ts +2 -2
- package/dist/core/sdd/resolve-project-root.js +11 -5
- package/dist/core/sdd/sanitize.d.ts +30 -1
- package/dist/core/sdd/sanitize.js +23 -23
- package/dist/core/sdd/services/agent-run.service.d.ts +65 -0
- package/dist/core/sdd/services/agent-run.service.js +189 -0
- package/dist/core/sdd/services/breakdown.service.js +2 -1
- package/dist/core/sdd/services/context.service.js +18 -16
- package/dist/core/sdd/services/debate.service.js +15 -2
- package/dist/core/sdd/services/feature-lint.service.d.ts +22 -0
- package/dist/core/sdd/services/feature-lint.service.js +105 -5
- package/dist/core/sdd/services/finalize.service.d.ts +80 -0
- package/dist/core/sdd/services/finalize.service.js +323 -24
- package/dist/core/sdd/services/frontend-gap.service.js +22 -7
- package/dist/core/sdd/services/governance-control-plane-runtime-adapters.d.ts +17 -0
- package/dist/core/sdd/services/governance-control-plane-runtime-adapters.js +38 -0
- package/dist/core/sdd/services/governance-control-plane.service.d.ts +66 -0
- package/dist/core/sdd/services/governance-control-plane.service.js +134 -0
- package/dist/core/sdd/services/ingest-deposito.service.js +1 -1
- package/dist/core/sdd/services/legacy-capability.service.d.ts +10 -7
- package/dist/core/sdd/services/legacy-capability.service.js +38 -21
- package/dist/core/sdd/services/mcp-runtime.service.d.ts +123 -8
- package/dist/core/sdd/services/mcp-runtime.service.js +1085 -33
- package/dist/core/sdd/services/onboard.service.js +2 -1
- package/dist/core/sdd/services/rebuild.service.js +6 -1
- package/dist/core/sdd/services/skills-sync.service.d.ts +17 -5
- package/dist/core/sdd/services/skills-sync.service.js +55 -2
- package/dist/core/sdd/services/start.service.js +6 -4
- package/dist/core/sdd/skill-bundles-curation-schema.d.ts +66 -0
- package/dist/core/sdd/skill-bundles-curation-schema.js +52 -0
- package/dist/core/sdd/skill-evidence.d.ts +19 -0
- package/dist/core/sdd/skill-evidence.js +38 -0
- package/dist/core/sdd/skill-policy-pool.d.ts +46 -0
- package/dist/core/sdd/skill-policy-pool.js +185 -0
- package/dist/core/sdd/state.d.ts +22 -0
- package/dist/core/sdd/state.js +66 -41
- package/dist/core/sdd/structural-health.d.ts +42 -42
- package/dist/core/sdd/types.d.ts +33 -7
- package/dist/core/sdd/types.js +17 -0
- package/dist/core/sdd/upgrade-to-codesdd.d.ts +45 -0
- package/dist/core/sdd/upgrade-to-codesdd.js +179 -0
- package/dist/core/sdd/workspace-schemas.d.ts +285 -14
- package/dist/core/sdd/workspace-schemas.js +148 -0
- package/dist/core/sdd/write-manifest.js +22 -4
- package/dist/core/shared/skill-generation.d.ts +1 -1
- package/dist/core/shared/skill-generation.js +15 -15
- package/dist/core/shared/tool-detection.d.ts +3 -3
- package/dist/core/shared/tool-detection.js +14 -14
- package/dist/core/specs-apply.js +6 -6
- package/dist/core/templates/index.d.ts +1 -1
- package/dist/core/templates/index.js +1 -1
- package/dist/core/templates/workflows/apply-change.js +14 -14
- package/dist/core/templates/workflows/archive-change.js +32 -32
- package/dist/core/templates/workflows/bulk-archive-change.js +25 -25
- package/dist/core/templates/workflows/continue-change.js +12 -12
- package/dist/core/templates/workflows/explore.js +29 -29
- package/dist/core/templates/workflows/feedback.js +6 -6
- package/dist/core/templates/workflows/ff-change.js +24 -24
- package/dist/core/templates/workflows/new-change.js +20 -20
- package/dist/core/templates/workflows/onboard.js +33 -33
- package/dist/core/templates/workflows/propose.js +23 -23
- package/dist/core/templates/workflows/sdd.js +8 -8
- package/dist/core/templates/workflows/sync-specs.js +19 -19
- package/dist/core/templates/workflows/verify-change.js +17 -17
- package/dist/core/update.d.ts +2 -2
- package/dist/core/update.js +16 -15
- package/dist/core/validation/constants.d.ts +1 -1
- package/dist/core/validation/constants.js +1 -1
- package/dist/core/view.js +11 -11
- package/dist/telemetry/config.d.ts +2 -1
- package/dist/telemetry/config.js +17 -8
- package/dist/telemetry/index.d.ts +10 -2
- package/dist/telemetry/index.js +40 -7
- package/dist/ui/ascii-patterns.d.ts +2 -2
- package/dist/ui/ascii-patterns.js +2 -2
- package/dist/ui/welcome-screen.js +2 -2
- package/dist/utils/change-metadata.d.ts +4 -4
- package/dist/utils/change-metadata.js +6 -6
- package/dist/utils/change-utils.d.ts +3 -3
- package/dist/utils/change-utils.js +5 -5
- package/dist/utils/file-system.js +1 -1
- package/dist/utils/interactive.js +1 -1
- package/dist/utils/item-discovery.js +4 -4
- package/dist/utils/legacy-spec-compat.d.ts +2 -0
- package/dist/utils/legacy-spec-compat.js +2 -0
- package/dist/utils/shell-detection.d.ts +1 -0
- package/dist/utils/shell-detection.js +16 -0
- package/package.json +27 -17
- package/schemas/sdd/1-spec.schema.json +1 -1
- package/schemas/sdd/2-plan.schema.json +73 -1
- package/schemas/sdd/3-tasks.schema.json +73 -1
- package/schemas/sdd/4-changelog.schema.json +1 -1
- package/schemas/sdd/5-quality.schema.json +442 -2
- package/schemas/sdd/adr.schema.json +148 -0
- package/schemas/sdd/agent-binding-adapter.schema.json +210 -0
- package/schemas/sdd/agent-binding-resolution.schema.json +338 -0
- package/schemas/sdd/backlog-projection-plan.schema.json +180 -0
- package/schemas/sdd/backlog-provider-contract.schema.json +260 -0
- package/schemas/sdd/codesdd-plugin.schema.json +474 -0
- package/schemas/sdd/debate.schema.json +244 -0
- package/schemas/sdd/deepagent-decision-evidence.schema.json +58 -0
- package/schemas/sdd/deepagent-env-contract.schema.json +143 -0
- package/schemas/sdd/deepagent-quality-evidence.schema.json +108 -0
- package/schemas/sdd/deepagent-run-evidence.schema.json +192 -0
- package/schemas/sdd/deepagent-run-plan.schema.json +197 -0
- package/schemas/sdd/deepagent-run-request.schema.json +321 -0
- package/schemas/sdd/deepagent-subagent-evidence.schema.json +110 -0
- package/schemas/sdd/deepagent-tool-call-evidence.schema.json +78 -0
- package/schemas/sdd/discarded.schema.json +127 -0
- package/schemas/sdd/epic.schema.json +147 -0
- package/schemas/sdd/insight.schema.json +136 -0
- package/schemas/sdd/parallel-feat-automation-plan.schema.json +215 -0
- package/schemas/sdd/parallel-feat-automation-request.schema.json +109 -0
- package/schemas/sdd/plugin-artifact-manifest.schema.json +150 -0
- package/schemas/sdd/plugin-compliance-index.schema.json +136 -0
- package/schemas/sdd/plugin-dry-run-plan.schema.json +260 -0
- package/schemas/sdd/plugin-evidence-manifest.schema.json +569 -0
- package/schemas/sdd/plugin-policy-evaluation.schema.json +92 -0
- package/schemas/sdd/plugin-policy-pack-evaluation.schema.json +94 -0
- package/schemas/sdd/plugin-policy-pack.schema.json +196 -0
- package/schemas/sdd/plugin-registry.schema.json +558 -0
- package/schemas/sdd/plugin-rollback-manifest.schema.json +87 -0
- package/schemas/sdd/plugin-runtime-invocation-plan.schema.json +845 -0
- package/schemas/sdd/plugin-skill-binding-resolution.schema.json +305 -0
- package/schemas/sdd/plugin-skill-binding.schema.json +88 -0
- package/schemas/sdd/plugin-validation-manifest.schema.json +123 -0
- package/schemas/sdd/quality-architecture-schema.schema.json +216 -0
- package/schemas/sdd/quality-evidence-bundle.schema.json +1228 -0
- package/schemas/sdd/quality-run.schema.json +197 -0
- package/schemas/sdd/quality-scenario.schema.json +252 -0
- package/schemas/sdd/workspace-catalog.schema.json +9841 -22
- package/schemas/spec-driven/schema.yaml +4 -4
- package/schemas/spec-driven/templates/proposal.md +1 -1
- package/dist/utils/openspec-compat.d.ts +0 -2
- package/dist/utils/openspec-compat.js +0 -2
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { createDeepAgentsRuntimeAdapter, } from '../deepagents/runtime-factory.js';
|
|
2
|
+
import { createCodeSddDeepAgentsRuntimeTools } from '../deepagents/codesdd-tools.js';
|
|
3
|
+
import { mapDeepAgentsRunEvidence, mapDeepAgentsRunPlan, } from '../deepagents/evidence-mapper.js';
|
|
4
|
+
import { buildDeepAgentsOperationalPreflight, createDeepAgentsPolicySnapshot, } from '../deepagents/policy.js';
|
|
5
|
+
const FEATURE_REF_PATTERN = /^FEAT-\d{4}$/;
|
|
6
|
+
const DEEPAGENTS_RUN_MODES = [
|
|
7
|
+
'read-only',
|
|
8
|
+
'plan',
|
|
9
|
+
'validate',
|
|
10
|
+
'apply-sandbox',
|
|
11
|
+
'apply-approved',
|
|
12
|
+
];
|
|
13
|
+
const DEEPAGENTS_MUTATION_MODES = new Set(['apply-sandbox', 'apply-approved']);
|
|
14
|
+
const REQUIRED_PLUGIN_BROKER_FLOW_BASE = [
|
|
15
|
+
'plugin-inspect',
|
|
16
|
+
'plugin-plan',
|
|
17
|
+
'plugin-dry-run',
|
|
18
|
+
'policy-evaluation',
|
|
19
|
+
'artifact-manifest',
|
|
20
|
+
'evidence-manifest',
|
|
21
|
+
'validation-manifest',
|
|
22
|
+
'rollback-manifest',
|
|
23
|
+
];
|
|
24
|
+
const DEEPAGENTS_PROVIDER = 'deepagents';
|
|
25
|
+
export class DeepAgentsRunService {
|
|
26
|
+
async execute(featureId, request, options = {}) {
|
|
27
|
+
const generatedAt = new Date().toISOString();
|
|
28
|
+
const requestedProvider = request.provider.trim().toLowerCase();
|
|
29
|
+
const modeRequested = request.mode?.trim().toLowerCase() || 'plan';
|
|
30
|
+
const pluginExecutionPath = (request.plugin_execution_path || 'broker').trim().toLowerCase();
|
|
31
|
+
const completedPluginFlow = normalizeFlow(request.plugin_flow ?? []);
|
|
32
|
+
const operations = resolveOperations(request.operations, modeRequested);
|
|
33
|
+
const reasons = [];
|
|
34
|
+
const runId = `deepagents-${featureId}-${Date.now()}`;
|
|
35
|
+
if (!FEATURE_REF_PATTERN.test(featureId)) {
|
|
36
|
+
reasons.push('Feature ref must match FEAT-####.');
|
|
37
|
+
}
|
|
38
|
+
if (requestedProvider !== DEEPAGENTS_PROVIDER) {
|
|
39
|
+
reasons.push('Provider is not authorized. FEAT-0243 only allows --provider deepagents.');
|
|
40
|
+
}
|
|
41
|
+
const supportedModes = DEEPAGENTS_RUN_MODES;
|
|
42
|
+
const mode = supportedModes.includes(modeRequested)
|
|
43
|
+
? modeRequested
|
|
44
|
+
: 'read-only';
|
|
45
|
+
if (!supportedModes.includes(modeRequested)) {
|
|
46
|
+
reasons.push(`Mode '${modeRequested}' is invalid. Allowed modes: ${DEEPAGENTS_RUN_MODES.join(', ')}.`);
|
|
47
|
+
}
|
|
48
|
+
const requiredPluginFlow = resolveRequiredPluginFlow(mode);
|
|
49
|
+
const missingPluginFlow = requiredPluginFlow.filter((step) => !completedPluginFlow.includes(step));
|
|
50
|
+
if (DEEPAGENTS_MUTATION_MODES.has(mode)) {
|
|
51
|
+
if (pluginExecutionPath !== 'broker') {
|
|
52
|
+
reasons.push('Direct plugin execution is forbidden. DeepAgents must use plugin broker envelopes only.');
|
|
53
|
+
}
|
|
54
|
+
if (missingPluginFlow.length > 0) {
|
|
55
|
+
reasons.push(`Mutation mode '${mode}' requires broker evidence flow: ${requiredPluginFlow.join(', ')}. Missing: ${missingPluginFlow.join(', ')}.`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const runtime = reasons.length === 0
|
|
59
|
+
? await this.executeRuntimePath(featureId, mode, runId, request, operations, options)
|
|
60
|
+
: undefined;
|
|
61
|
+
if (runtime?.adapter.status === 'blocked' && runtime.adapter.runtime !== 'disabled') {
|
|
62
|
+
reasons.push(...runtime.adapter.reasons);
|
|
63
|
+
}
|
|
64
|
+
if (runtime?.run.status === 'failed' && runtime.error) {
|
|
65
|
+
reasons.push(`DeepAgents runtime invocation failed: ${runtime.error}`);
|
|
66
|
+
}
|
|
67
|
+
const status = reasons.length === 0 ? 'allowed' : 'blocked';
|
|
68
|
+
return {
|
|
69
|
+
schema_version: 1,
|
|
70
|
+
feature_id: featureId,
|
|
71
|
+
provider: DEEPAGENTS_PROVIDER,
|
|
72
|
+
requested_provider: requestedProvider,
|
|
73
|
+
mode_requested: modeRequested,
|
|
74
|
+
mode,
|
|
75
|
+
status,
|
|
76
|
+
fail_closed: true,
|
|
77
|
+
reasons,
|
|
78
|
+
evidence: {
|
|
79
|
+
run_id: runId,
|
|
80
|
+
generated_at: generatedAt,
|
|
81
|
+
policy: 'deepagents-run-governance/v1',
|
|
82
|
+
direct_state_write_allowed: false,
|
|
83
|
+
plugin_execution: {
|
|
84
|
+
broker_only: true,
|
|
85
|
+
requested_path: pluginExecutionPath,
|
|
86
|
+
required_flow: requiredPluginFlow,
|
|
87
|
+
completed_flow: completedPluginFlow,
|
|
88
|
+
missing_flow: missingPluginFlow,
|
|
89
|
+
},
|
|
90
|
+
runtime,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async executeRuntimePath(featureId, mode, runId, request, operations, options) {
|
|
95
|
+
const snapshot = createDeepAgentsPolicySnapshot(options.env);
|
|
96
|
+
const preflight = buildDeepAgentsOperationalPreflight(snapshot, options.env);
|
|
97
|
+
const tools = options.projectRoot && options.stores
|
|
98
|
+
? createCodeSddDeepAgentsRuntimeTools(options.stores, options.projectRoot, {
|
|
99
|
+
profile: mode === 'apply-sandbox' || mode === 'apply-approved' ? 'all' : 'read-diagnostic',
|
|
100
|
+
})
|
|
101
|
+
: [];
|
|
102
|
+
const adapter = await createDeepAgentsRuntimeAdapter({
|
|
103
|
+
featureRef: featureId,
|
|
104
|
+
objective: `Run CodeSDD governed agent mode ${mode} for ${featureId}.`,
|
|
105
|
+
mode,
|
|
106
|
+
runId,
|
|
107
|
+
projectRoot: options.projectRoot,
|
|
108
|
+
tools,
|
|
109
|
+
operations,
|
|
110
|
+
writeScope: normalizeList(request.write_scope ?? []),
|
|
111
|
+
plannedWrites: normalizeList(request.planned_writes ?? []),
|
|
112
|
+
requestedEnv: normalizeList(request.requested_env ?? []),
|
|
113
|
+
networkDomains: normalizeList(request.network_domains ?? []),
|
|
114
|
+
approvalGrants: normalizeFlow(request.approval_grants ?? []),
|
|
115
|
+
}, { env: options.env, importer: options.importer, snapshot });
|
|
116
|
+
const envelope = adapter.describe();
|
|
117
|
+
const plan = mapDeepAgentsRunPlan({ adapter: envelope });
|
|
118
|
+
const invocation = envelope.status === 'ready'
|
|
119
|
+
? await this.invokeReadyRuntime(adapter, mode, featureId)
|
|
120
|
+
: { result: undefined, error: undefined };
|
|
121
|
+
const run = mapDeepAgentsRunEvidence({
|
|
122
|
+
adapter: envelope,
|
|
123
|
+
status: invocation.error
|
|
124
|
+
? 'failed'
|
|
125
|
+
: envelope.status === 'ready'
|
|
126
|
+
? 'completed'
|
|
127
|
+
: 'blocked',
|
|
128
|
+
planRef: `${runId}:plan`,
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
preflight,
|
|
132
|
+
adapter: envelope,
|
|
133
|
+
plan,
|
|
134
|
+
run,
|
|
135
|
+
agent_result: invocation.result,
|
|
136
|
+
fake_result: envelope.runtime === 'fake' ? invocation.result : undefined,
|
|
137
|
+
error: invocation.error,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
async invokeReadyRuntime(adapter, mode, featureId) {
|
|
141
|
+
try {
|
|
142
|
+
const agent = await adapter.createAgent();
|
|
143
|
+
const result = await agent.invoke({
|
|
144
|
+
messages: [
|
|
145
|
+
{
|
|
146
|
+
role: 'user',
|
|
147
|
+
content: `Run ${mode} for ${featureId} under CodeSDD governance.`,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
});
|
|
151
|
+
return { result };
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function resolveRequiredPluginFlow(mode) {
|
|
159
|
+
if (mode === 'apply-sandbox') {
|
|
160
|
+
return [...REQUIRED_PLUGIN_BROKER_FLOW_BASE, 'apply-sandbox'];
|
|
161
|
+
}
|
|
162
|
+
if (mode === 'apply-approved') {
|
|
163
|
+
return [...REQUIRED_PLUGIN_BROKER_FLOW_BASE, 'apply-approved'];
|
|
164
|
+
}
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
function normalizeFlow(flow) {
|
|
168
|
+
return [...new Set(flow.map((step) => step.trim().toLowerCase()).filter((step) => step.length > 0))].sort();
|
|
169
|
+
}
|
|
170
|
+
function normalizeList(values) {
|
|
171
|
+
return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))].sort();
|
|
172
|
+
}
|
|
173
|
+
function resolveOperations(operations, modeRequested) {
|
|
174
|
+
const normalized = normalizeFlow(operations ?? []);
|
|
175
|
+
const candidates = normalized.length > 0
|
|
176
|
+
? normalized
|
|
177
|
+
: modeRequested === 'apply-sandbox' || modeRequested === 'apply-approved'
|
|
178
|
+
? ['plugin-apply', 'write']
|
|
179
|
+
: ['read'];
|
|
180
|
+
return candidates.filter((operation) => operation === 'read' ||
|
|
181
|
+
operation === 'write' ||
|
|
182
|
+
operation === 'execute' ||
|
|
183
|
+
operation === 'network' ||
|
|
184
|
+
operation === 'plugin-apply' ||
|
|
185
|
+
operation === 'finalize' ||
|
|
186
|
+
operation === 'dependency-change' ||
|
|
187
|
+
operation === 'process-spawn');
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=agent-run.service.js.map
|
|
@@ -54,7 +54,8 @@ export class BreakdownService {
|
|
|
54
54
|
const id = await allocateEntityId(paths, 'FEAT');
|
|
55
55
|
syncCounterFromId(snapshot.discoveryIndex, id);
|
|
56
56
|
const recommended = resolveRoutedSkills(snapshot, shape.touches);
|
|
57
|
-
const
|
|
57
|
+
const originType = radar.type === 'RAD' ? 'radar' : 'epic';
|
|
58
|
+
const item = buildBacklogItem(id, title, originType, radar.id, options?.scale || 'STANDARD', recommended, {
|
|
58
59
|
parallelGroup,
|
|
59
60
|
executionKind: shape.executionKind,
|
|
60
61
|
planningMode: shape.planningMode,
|
|
@@ -4,6 +4,7 @@ import { parse } from "yaml";
|
|
|
4
4
|
import { CLI_NAME } from "../../branding.js";
|
|
5
5
|
import { loadStateSnapshot } from "../state.js";
|
|
6
6
|
import { bundlesForSkills, getRuntime, relProjectPath, coreDocRef, planningDocRef, featureActiveDir, activeDocNamesForLayout, unresolvedDependencies, lockConflictWithActive, featureReadiness, gateSatisfied, detectContextType, pathExists, listAdrRefs } from "../legacy-operations.js";
|
|
7
|
+
import { normalizeSddEntityRef } from "../entity-reference.js";
|
|
7
8
|
import { workspacePlanSchema, workspaceSpecSchema } from "../workspace-schemas.js";
|
|
8
9
|
async function readYamlWorkspaceDoc(filePath, schema) {
|
|
9
10
|
const content = await fs.readFile(filePath, 'utf-8').catch(() => '');
|
|
@@ -62,7 +63,8 @@ export class ContextService {
|
|
|
62
63
|
async execute(projectRoot, ref) {
|
|
63
64
|
const { config, paths } = await getRuntime(projectRoot);
|
|
64
65
|
const snapshot = await loadStateSnapshot(paths, config);
|
|
65
|
-
const
|
|
66
|
+
const normalizedRef = normalizeSddEntityRef(ref);
|
|
67
|
+
const type = detectContextType(normalizedRef);
|
|
66
68
|
if (!type) {
|
|
67
69
|
throw new Error(`Referencia ${ref} invalida. Use FEAT/EPIC/RAD/FGAP/TD.`);
|
|
68
70
|
}
|
|
@@ -80,9 +82,9 @@ export class ContextService {
|
|
|
80
82
|
coreDocs.push(planningDocRef(paths, 'frontend-auditoria.md'));
|
|
81
83
|
}
|
|
82
84
|
if (type === 'FEAT') {
|
|
83
|
-
const item = snapshot.backlog.items.find((entry) => entry.id ===
|
|
85
|
+
const item = snapshot.backlog.items.find((entry) => entry.id === normalizedRef);
|
|
84
86
|
if (!item)
|
|
85
|
-
throw new Error(`Feature ${
|
|
87
|
+
throw new Error(`Feature ${normalizedRef} nao encontrada.`);
|
|
86
88
|
const unresolved = unresolvedDependencies(item, snapshot.backlog.items);
|
|
87
89
|
const lockConflicts = lockConflictWithActive(item, snapshot.backlog.items);
|
|
88
90
|
const predecessorOutputs = item.blocked_by
|
|
@@ -147,7 +149,7 @@ export class ContextService {
|
|
|
147
149
|
const requiredSkillEvidence = item.recommended_skills.filter(Boolean);
|
|
148
150
|
return {
|
|
149
151
|
sdd_pack_version: 1,
|
|
150
|
-
target_id:
|
|
152
|
+
target_id: normalizedRef,
|
|
151
153
|
target_type: type,
|
|
152
154
|
summary: `${item.title} [${item.status}]`,
|
|
153
155
|
objective: workspace.spec?.objective || item.summary || '',
|
|
@@ -166,7 +168,7 @@ export class ContextService {
|
|
|
166
168
|
origin: { type: item.origin_type, ref: item.origin_ref || '' },
|
|
167
169
|
related_discovery: item.origin_ref
|
|
168
170
|
? snapshot.discoveryIndex.records
|
|
169
|
-
.filter((record) => record.id === item.origin_ref || record.related_ids.includes(
|
|
171
|
+
.filter((record) => record.id === item.origin_ref || record.related_ids.includes(normalizedRef))
|
|
170
172
|
.map((record) => record.id)
|
|
171
173
|
: [],
|
|
172
174
|
related_gaps: item.frontend_gap_refs,
|
|
@@ -213,19 +215,19 @@ export class ContextService {
|
|
|
213
215
|
};
|
|
214
216
|
}
|
|
215
217
|
if (type === 'RAD' || type === 'EPIC') {
|
|
216
|
-
const radar = snapshot.discoveryIndex.records.find((record) => record.id ===
|
|
218
|
+
const radar = snapshot.discoveryIndex.records.find((record) => record.id === normalizedRef && (record.type === 'RAD' || record.type === 'EPIC'));
|
|
217
219
|
if (!radar)
|
|
218
|
-
throw new Error(`Epic/Radar ${
|
|
219
|
-
const relatedFeatures = snapshot.backlog.items.filter((item) => (item.origin_type === 'radar' || item.origin_type === 'epic') && item.origin_ref ===
|
|
220
|
+
throw new Error(`Epic/Radar ${normalizedRef} nao encontrado.`);
|
|
221
|
+
const relatedFeatures = snapshot.backlog.items.filter((item) => (item.origin_type === 'radar' || item.origin_type === 'epic') && item.origin_ref === normalizedRef);
|
|
220
222
|
return {
|
|
221
223
|
sdd_pack_version: 1,
|
|
222
|
-
target_id:
|
|
224
|
+
target_id: normalizedRef,
|
|
223
225
|
target_type: type,
|
|
224
226
|
summary: `${radar.title} [${radar.status}]`,
|
|
225
227
|
quality_contract: radar.quality_contract || null,
|
|
226
228
|
related_features: relatedFeatures.map((item) => item.id),
|
|
227
229
|
related_debates: snapshot.discoveryIndex.records
|
|
228
|
-
.filter((record) => record.type === 'DEB' && record.related_ids.includes(
|
|
230
|
+
.filter((record) => record.type === 'DEB' && record.related_ids.includes(normalizedRef))
|
|
229
231
|
.map((record) => record.id),
|
|
230
232
|
read_order: [
|
|
231
233
|
'README.md',
|
|
@@ -237,12 +239,12 @@ export class ContextService {
|
|
|
237
239
|
};
|
|
238
240
|
}
|
|
239
241
|
if (type === 'FGAP') {
|
|
240
|
-
const gap = snapshot.frontendGaps?.items.find((item) => item.id ===
|
|
242
|
+
const gap = snapshot.frontendGaps?.items.find((item) => item.id === normalizedRef);
|
|
241
243
|
if (!gap)
|
|
242
|
-
throw new Error(`Gap de frontend ${
|
|
244
|
+
throw new Error(`Gap de frontend ${normalizedRef} nao encontrado.`);
|
|
243
245
|
return {
|
|
244
246
|
sdd_pack_version: 1,
|
|
245
|
-
target_id:
|
|
247
|
+
target_id: normalizedRef,
|
|
246
248
|
target_type: type,
|
|
247
249
|
summary: `${gap.title} [${gap.status}]`,
|
|
248
250
|
source_feature: gap.origin_feature || '',
|
|
@@ -257,12 +259,12 @@ export class ContextService {
|
|
|
257
259
|
core_docs: coreDocs,
|
|
258
260
|
};
|
|
259
261
|
}
|
|
260
|
-
const debt = snapshot.techDebt.items.find((item) => item.id ===
|
|
262
|
+
const debt = snapshot.techDebt.items.find((item) => item.id === normalizedRef);
|
|
261
263
|
if (!debt)
|
|
262
|
-
throw new Error(`Divida tecnica ${
|
|
264
|
+
throw new Error(`Divida tecnica ${normalizedRef} nao encontrada.`);
|
|
263
265
|
return {
|
|
264
266
|
sdd_pack_version: 1,
|
|
265
|
-
target_id:
|
|
267
|
+
target_id: normalizedRef,
|
|
266
268
|
target_type: type,
|
|
267
269
|
summary: `${debt.title} [${debt.status}]`,
|
|
268
270
|
related_refs: debt.related_refs,
|
|
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { promises as fs } from "node:fs";
|
|
3
3
|
import { TransitionEngine } from "../domain/transition-engine.js";
|
|
4
4
|
import { allocateEntityId, loadStateSnapshot, nowIso, saveStateTransaction } from "../state.js";
|
|
5
|
-
import { slugify, computeCanonicalTitle, findDiscoveryRecord, markdownDebateTemplate, buildDefaultQualityContract, syncCounterFromId, getRuntime, persistAndRender, applyLoggedTransition } from "../legacy-operations.js";
|
|
5
|
+
import { slugify, computeCanonicalTitle, findDiscoveryRecord, markdownDebateTemplate, buildDefaultQualityContract, findDebateFile, syncCounterFromId, getRuntime, persistAndRender, applyLoggedTransition } from "../legacy-operations.js";
|
|
6
6
|
import { withStateLock } from "../state-lock.js";
|
|
7
7
|
export class DebateService {
|
|
8
8
|
stores;
|
|
@@ -19,10 +19,23 @@ export class DebateService {
|
|
|
19
19
|
}
|
|
20
20
|
const existingDebate = snapshot.discoveryIndex.records.find((record) => record.type === 'DEB' && record.related_ids.includes(insight.id));
|
|
21
21
|
if (existingDebate) {
|
|
22
|
+
const existingFile = await findDebateFile(paths, existingDebate.id);
|
|
23
|
+
if (existingFile) {
|
|
24
|
+
return {
|
|
25
|
+
id: existingDebate.id,
|
|
26
|
+
title: existingDebate.title,
|
|
27
|
+
filePath: existingFile,
|
|
28
|
+
reused: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const repairedFilePath = path.join(paths.discoveryDebatesDir, `${existingDebate.id}-${slugify(existingDebate.title)}.md`);
|
|
32
|
+
await fs.mkdir(paths.discoveryDebatesDir, { recursive: true });
|
|
33
|
+
await fs.writeFile(repairedFilePath, markdownDebateTemplate(insight, existingDebate.id), 'utf-8');
|
|
34
|
+
await persistAndRender(paths, config, options?.render);
|
|
22
35
|
return {
|
|
23
36
|
id: existingDebate.id,
|
|
24
37
|
title: existingDebate.title,
|
|
25
|
-
filePath:
|
|
38
|
+
filePath: repairedFilePath,
|
|
26
39
|
reused: true,
|
|
27
40
|
};
|
|
28
41
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type SddPaths, type SddRuntimeConfig } from '../state.js';
|
|
2
|
+
import type { BacklogItem } from '../types.js';
|
|
3
|
+
import { type WorkspaceQualityDocument, type WorkspaceTasksDocument } from '../workspace-schemas.js';
|
|
1
4
|
export interface FeatureLintOptions {
|
|
2
5
|
strict?: boolean;
|
|
3
6
|
}
|
|
@@ -22,6 +25,25 @@ export interface FeatureLintReport {
|
|
|
22
25
|
};
|
|
23
26
|
findings: FeatureLintFinding[];
|
|
24
27
|
}
|
|
28
|
+
export declare function isFoundationPrescriptiveFeature(feature: Pick<BacklogItem, 'title' | 'summary'>): boolean;
|
|
29
|
+
export declare function loadTasksDocument(paths: SddPaths, config: SddRuntimeConfig, featureId: string): Promise<{
|
|
30
|
+
workspacePath: string;
|
|
31
|
+
tasks?: WorkspaceTasksDocument;
|
|
32
|
+
error?: string;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function loadQualityDocument(paths: SddPaths, config: SddRuntimeConfig, featureId: string): Promise<{
|
|
35
|
+
workspacePath: string;
|
|
36
|
+
quality?: WorkspaceQualityDocument;
|
|
37
|
+
error?: string;
|
|
38
|
+
}>;
|
|
39
|
+
export declare function hasTemplatePlaceholder(content: string): boolean;
|
|
40
|
+
export declare function collectTaskCommands(tasks: WorkspaceTasksDocument | undefined): string[];
|
|
41
|
+
export declare function addFinding(findings: FeatureLintFinding[], severity: FeatureLintFinding['severity'], code: string, message: string, evidence: Record<string, unknown>): void;
|
|
42
|
+
export declare function lintFeatureShape(feature: BacklogItem, taskCount: number, workspaceError: string | undefined, qualityDocument: WorkspaceQualityDocument | undefined, qualityError: string | undefined, commands: string[], adr: {
|
|
43
|
+
exists: boolean;
|
|
44
|
+
isTemplate: boolean;
|
|
45
|
+
path: string;
|
|
46
|
+
}): FeatureLintFinding[];
|
|
25
47
|
export declare class FeatureLintService {
|
|
26
48
|
execute(projectRoot: string, featureId: string, options?: FeatureLintOptions): Promise<FeatureLintReport>;
|
|
27
49
|
}
|
|
@@ -2,8 +2,20 @@ import path from 'node:path';
|
|
|
2
2
|
import { existsSync, promises as fs } from 'node:fs';
|
|
3
3
|
import { loadProjectSddConfig, loadStateSnapshot, resolveSddPaths, } from '../state.js';
|
|
4
4
|
import { activeDocNamesForLayout, ensureMemoryInitialized, relProjectPath } from '../legacy-operations.js';
|
|
5
|
-
import { parseWorkspaceYamlDocument } from '../workspace-schemas.js';
|
|
6
|
-
|
|
5
|
+
import { parseWorkspaceYamlDocument, } from '../workspace-schemas.js';
|
|
6
|
+
const FOUNDATION_PROFILE_TOKENS = ['foundation api', 'devtrack foundation api'];
|
|
7
|
+
const FOUNDATION_ENFORCEMENT_TOKENS = ['prescriptive', 'enforcement', 'lint', 'scaffold'];
|
|
8
|
+
const ADR_TEMPLATE_PLACEHOLDERS = [
|
|
9
|
+
'Describe the context that motivated this architecture decision',
|
|
10
|
+
'Document the decision, the change scope, and the alternatives rejected.',
|
|
11
|
+
'List positive impacts, residual risks, and mitigation actions.',
|
|
12
|
+
];
|
|
13
|
+
export function isFoundationPrescriptiveFeature(feature) {
|
|
14
|
+
const source = `${feature.title} ${feature.summary || ''}`.toLowerCase();
|
|
15
|
+
return (FOUNDATION_PROFILE_TOKENS.some((token) => source.includes(token)) &&
|
|
16
|
+
FOUNDATION_ENFORCEMENT_TOKENS.some((token) => source.includes(token)));
|
|
17
|
+
}
|
|
18
|
+
export async function loadTasksDocument(paths, config, featureId) {
|
|
7
19
|
const names = activeDocNamesForLayout(config);
|
|
8
20
|
const roots = [paths.activeDir, paths.plannedDir, paths.archivedDir];
|
|
9
21
|
for (const root of roots) {
|
|
@@ -30,10 +42,47 @@ async function loadTasksDocument(paths, config, featureId) {
|
|
|
30
42
|
}
|
|
31
43
|
return { workspacePath: '', error: 'Feature workspace not found.' };
|
|
32
44
|
}
|
|
33
|
-
function
|
|
45
|
+
export async function loadQualityDocument(paths, config, featureId) {
|
|
46
|
+
const names = activeDocNamesForLayout(config);
|
|
47
|
+
const roots = [paths.activeDir, paths.plannedDir, paths.archivedDir];
|
|
48
|
+
for (const root of roots) {
|
|
49
|
+
const workspacePath = path.join(root, featureId);
|
|
50
|
+
if (!existsSync(workspacePath))
|
|
51
|
+
continue;
|
|
52
|
+
const qualityPath = path.join(workspacePath, names.quality);
|
|
53
|
+
if (!existsSync(qualityPath)) {
|
|
54
|
+
return { workspacePath: relProjectPath(paths, workspacePath), error: `${names.quality} not found.` };
|
|
55
|
+
}
|
|
56
|
+
const content = await fs.readFile(qualityPath, 'utf-8');
|
|
57
|
+
try {
|
|
58
|
+
return {
|
|
59
|
+
workspacePath: relProjectPath(paths, workspacePath),
|
|
60
|
+
quality: parseWorkspaceYamlDocument('5-quality.yaml', content),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return {
|
|
65
|
+
workspacePath: relProjectPath(paths, workspacePath),
|
|
66
|
+
error: error instanceof Error ? error.message : String(error),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { workspacePath: '', error: 'Feature workspace not found.' };
|
|
71
|
+
}
|
|
72
|
+
export function hasTemplatePlaceholder(content) {
|
|
73
|
+
return ADR_TEMPLATE_PLACEHOLDERS.some((placeholder) => content.includes(placeholder));
|
|
74
|
+
}
|
|
75
|
+
export function collectTaskCommands(tasks) {
|
|
76
|
+
if (!tasks)
|
|
77
|
+
return [];
|
|
78
|
+
return tasks.tasks
|
|
79
|
+
.flatMap((task) => task.test_scripts.map((script) => script.command.toLowerCase().trim()))
|
|
80
|
+
.filter(Boolean);
|
|
81
|
+
}
|
|
82
|
+
export function addFinding(findings, severity, code, message, evidence) {
|
|
34
83
|
findings.push({ severity, code, message, evidence });
|
|
35
84
|
}
|
|
36
|
-
function lintFeatureShape(feature, taskCount, workspaceError) {
|
|
85
|
+
export function lintFeatureShape(feature, taskCount, workspaceError, qualityDocument, qualityError, commands, adr) {
|
|
37
86
|
const findings = [];
|
|
38
87
|
if (workspaceError) {
|
|
39
88
|
addFinding(findings, 'error', 'workspace_tasks_unreadable', 'Feature tasks could not be read from the workspace.', {
|
|
@@ -87,6 +136,49 @@ function lintFeatureShape(feature, taskCount, workspaceError) {
|
|
|
87
136
|
touches: feature.touches,
|
|
88
137
|
});
|
|
89
138
|
}
|
|
139
|
+
if (isFoundationPrescriptiveFeature(feature)) {
|
|
140
|
+
if ((feature.quality_contract?.enforcement || 'blocking') !== 'blocking') {
|
|
141
|
+
addFinding(findings, 'error', 'foundation_enforcement_not_blocking', 'Foundation API prescriptive features must use blocking quality enforcement.', {
|
|
142
|
+
feature_id: feature.id,
|
|
143
|
+
enforcement: feature.quality_contract?.enforcement || 'undefined',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (qualityError) {
|
|
147
|
+
addFinding(findings, 'error', 'foundation_quality_unreadable', 'Foundation API prescriptive features require a readable 5-quality.yaml workspace document.', {
|
|
148
|
+
feature_id: feature.id,
|
|
149
|
+
error: qualityError,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (!commands.some((command) => command.includes('sdd lint feature'))) {
|
|
153
|
+
addFinding(findings, 'error', 'foundation_lint_blocker_missing', 'Foundation API prescriptive features must include a feature-lint blocker command in tasks.', {
|
|
154
|
+
feature_id: feature.id,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (!commands.some((command) => command.includes('sdd plugin devtrack-api scaffold-dry-run'))) {
|
|
158
|
+
addFinding(findings, 'error', 'foundation_scaffold_blocker_missing', 'Foundation API prescriptive features must include a devtrack-api scaffold dry-run blocker command in tasks.', {
|
|
159
|
+
feature_id: feature.id,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const exceptionCount = qualityDocument?.exceptions.length || feature.quality_contract?.exceptions.length || 0;
|
|
163
|
+
if (exceptionCount > 0 && !feature.requires_adr) {
|
|
164
|
+
addFinding(findings, 'error', 'foundation_exception_requires_adr_flag', 'Foundation API exceptions require requires_adr=true in backlog state.', {
|
|
165
|
+
feature_id: feature.id,
|
|
166
|
+
exceptions: exceptionCount,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (exceptionCount > 0 && !adr.exists) {
|
|
170
|
+
addFinding(findings, 'error', 'foundation_exception_missing_adr', 'Foundation API exceptions require ADR documentation before execution can proceed.', {
|
|
171
|
+
feature_id: feature.id,
|
|
172
|
+
expected_adr: adr.path,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (exceptionCount > 0 && adr.isTemplate) {
|
|
176
|
+
addFinding(findings, 'error', 'foundation_exception_adr_template', 'Foundation API exception ADR must be completed with concrete context, decision, and consequences.', {
|
|
177
|
+
feature_id: feature.id,
|
|
178
|
+
adr_path: adr.path,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
90
182
|
return findings;
|
|
91
183
|
}
|
|
92
184
|
export class FeatureLintService {
|
|
@@ -103,8 +195,16 @@ export class FeatureLintService {
|
|
|
103
195
|
throw new Error(`Feature ${featureId} not found in backlog.`);
|
|
104
196
|
}
|
|
105
197
|
const workspace = await loadTasksDocument(paths, config, featureId);
|
|
198
|
+
const qualityWorkspace = await loadQualityDocument(paths, config, featureId);
|
|
106
199
|
const taskCount = workspace.tasks?.tasks.length ?? 0;
|
|
107
|
-
const
|
|
200
|
+
const commandList = collectTaskCommands(workspace.tasks);
|
|
201
|
+
const adrPath = path.join(paths.coreDir, 'adrs', `ADR-${feature.id}.md`);
|
|
202
|
+
const adrContent = await fs.readFile(adrPath, 'utf-8').catch(() => '');
|
|
203
|
+
const findings = lintFeatureShape(feature, taskCount, workspace.error, qualityWorkspace.quality, qualityWorkspace.error, commandList, {
|
|
204
|
+
exists: !!adrContent.trim(),
|
|
205
|
+
isTemplate: hasTemplatePlaceholder(adrContent),
|
|
206
|
+
path: relProjectPath(paths, adrPath),
|
|
207
|
+
});
|
|
108
208
|
const hasErrors = findings.some((finding) => finding.severity === 'error');
|
|
109
209
|
const hasWarnings = findings.some((finding) => finding.severity === 'warning');
|
|
110
210
|
const ok = !hasErrors && !(options.strict && hasWarnings);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { SddPaths, SddRuntimeConfig } from "../state.js";
|
|
2
|
+
import { BacklogItem, FinalizeQueueItem } from "../types.js";
|
|
1
3
|
import { SddStores } from "../store/sdd-stores.js";
|
|
4
|
+
import { type WorkspaceQualityDocument } from "../workspace-schemas.js";
|
|
2
5
|
export declare class FinalizeService {
|
|
3
6
|
private readonly stores;
|
|
4
7
|
constructor(stores: SddStores);
|
|
@@ -30,4 +33,81 @@ export declare class FinalizeService {
|
|
|
30
33
|
}[];
|
|
31
34
|
}>;
|
|
32
35
|
}
|
|
36
|
+
export type WorkspaceQualityFeedbackResult = {
|
|
37
|
+
ok: boolean;
|
|
38
|
+
reasons: string[];
|
|
39
|
+
artifact: string;
|
|
40
|
+
};
|
|
41
|
+
export type WorkspaceTraceabilityFeedbackResult = {
|
|
42
|
+
ok: boolean;
|
|
43
|
+
reasons: string[];
|
|
44
|
+
artifact: string;
|
|
45
|
+
};
|
|
46
|
+
export type PrivacyFinalizeGuardrailResult = {
|
|
47
|
+
ok: boolean;
|
|
48
|
+
reasons: string[];
|
|
49
|
+
};
|
|
50
|
+
export type DevTrackApiPolicyGatesResult = {
|
|
51
|
+
ok: boolean;
|
|
52
|
+
reasons: string[];
|
|
53
|
+
};
|
|
54
|
+
export declare function inferFinalizeTarget(paths: SddPaths, pending: FinalizeQueueItem[], explicitRef?: string, cwd?: string): Promise<string | undefined>;
|
|
55
|
+
export declare function isPrivacyComplianceFeature(feature: BacklogItem): boolean;
|
|
56
|
+
export declare function evaluatePrivacyFinalizeGuardrail(paths: SddPaths, config: SddRuntimeConfig, feature: BacklogItem): Promise<PrivacyFinalizeGuardrailResult>;
|
|
57
|
+
export declare function evaluateDevTrackApiPolicyGates(paths: SddPaths, config: SddRuntimeConfig, feature: BacklogItem): Promise<DevTrackApiPolicyGatesResult>;
|
|
58
|
+
export declare function evaluateDevTrackApiPolicyEvidence(quality: WorkspaceQualityDocument): string[];
|
|
59
|
+
export declare function evaluateWorkspaceQualityFeedback(paths: SddPaths, config: SddRuntimeConfig, feature: BacklogItem): Promise<WorkspaceQualityFeedbackResult>;
|
|
60
|
+
export declare function evaluateWorkspaceTraceabilityFeedback(paths: SddPaths, config: SddRuntimeConfig, feature: BacklogItem): Promise<WorkspaceTraceabilityFeedbackResult>;
|
|
61
|
+
export type Q95AxisKey = 'coverage' | 'traceability' | 'integrity' | 'naming' | 'token';
|
|
62
|
+
export type Q95AxisResult = {
|
|
63
|
+
raw_score: number;
|
|
64
|
+
weighted_score: number;
|
|
65
|
+
rationale: string;
|
|
66
|
+
};
|
|
67
|
+
export type Q95Ledger = {
|
|
68
|
+
threshold: number;
|
|
69
|
+
score: number;
|
|
70
|
+
status: 'pass' | 'fail' | 'pending';
|
|
71
|
+
computed_at: string;
|
|
72
|
+
weights: Record<Q95AxisKey, number>;
|
|
73
|
+
axes: Record<Q95AxisKey, Q95AxisResult>;
|
|
74
|
+
next_best_action: string;
|
|
75
|
+
};
|
|
76
|
+
export declare function computeQ95Ledger(paths: SddPaths, config: SddRuntimeConfig, feature: BacklogItem, document: WorkspaceQualityDocument): Promise<Q95Ledger>;
|
|
77
|
+
export declare function weightedAxis(input: {
|
|
78
|
+
raw_score: number;
|
|
79
|
+
rationale: string;
|
|
80
|
+
}, weight: number): Q95AxisResult;
|
|
81
|
+
export declare function computeCoverageAxis(document: WorkspaceQualityDocument): {
|
|
82
|
+
raw_score: number;
|
|
83
|
+
rationale: string;
|
|
84
|
+
};
|
|
85
|
+
export declare function computeTraceabilityAxis(paths: SddPaths, config: SddRuntimeConfig, feature: BacklogItem, document: WorkspaceQualityDocument): Promise<{
|
|
86
|
+
raw_score: number;
|
|
87
|
+
rationale: string;
|
|
88
|
+
}>;
|
|
89
|
+
export declare function computeIntegrityAxis(document: WorkspaceQualityDocument): {
|
|
90
|
+
raw_score: number;
|
|
91
|
+
rationale: string;
|
|
92
|
+
};
|
|
93
|
+
export declare function computeNamingAxis(feature: BacklogItem, document: WorkspaceQualityDocument): {
|
|
94
|
+
raw_score: number;
|
|
95
|
+
rationale: string;
|
|
96
|
+
};
|
|
97
|
+
export declare function computeTokenAxis(document: WorkspaceQualityDocument): {
|
|
98
|
+
raw_score: number;
|
|
99
|
+
rationale: string;
|
|
100
|
+
};
|
|
101
|
+
export declare function extractCoveragePerformance(document: WorkspaceQualityDocument, kind: 'unit' | 'integration'): number;
|
|
102
|
+
export declare function integritySignalScore(value: 'not_applicable' | 'pending' | 'passed' | 'failed'): number;
|
|
103
|
+
export declare function inferQ95NextAction(axes: Record<Q95AxisKey, Q95AxisResult>): string;
|
|
104
|
+
export declare function clampPercent(value: number): number;
|
|
105
|
+
export declare function round2(value: number): number;
|
|
106
|
+
export declare function missingCoverageTargets(document: WorkspaceQualityDocument): Array<{
|
|
107
|
+
kind: 'unit' | 'integration';
|
|
108
|
+
target: number;
|
|
109
|
+
}>;
|
|
110
|
+
export declare function coverageTargetMet(document: WorkspaceQualityDocument, kind: 'unit' | 'integration', target: number): boolean;
|
|
111
|
+
export declare function countQualityEvidenceRounds(document: WorkspaceQualityDocument): number;
|
|
112
|
+
export declare function missingSkillEvidence(document: WorkspaceQualityDocument): string[];
|
|
33
113
|
//# sourceMappingURL=finalize.service.d.ts.map
|