@devtrack-solution/codesdd 1.2.2 → 1.2.4-rc3
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 +170 -31
- package/.sdd/skills/curated/devtrack-api/agents/claude-code.yaml +8 -0
- package/.sdd/skills/curated/devtrack-api/agents/codex.yaml +8 -0
- package/.sdd/skills/curated/devtrack-api/agents/cursor.yaml +8 -0
- package/.sdd/skills/curated/devtrack-api/agents/gemini.yaml +8 -0
- package/.sdd/skills/curated/devtrack-api/agents/kimi.yaml +8 -0
- package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +4 -2
- package/.sdd/skills/curated/devtrack-api/agents/opencode.yaml +10 -0
- package/.sdd/skills/curated/devtrack-api/references/application-presentation.md +2 -2
- 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 +372 -0
- package/.sdd/skills/curated/devtrack-api/references/domain-modeling.md +13 -13
- package/.sdd/skills/curated/devtrack-api/references/field-validation-protocol.md +95 -0
- package/.sdd/skills/curated/devtrack-api/references/foundation-layout.md +294 -0
- package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +5 -5
- package/.sdd/skills/curated/devtrack-api/references/imports-lint.md +4 -0
- package/.sdd/skills/curated/devtrack-api/references/portable-agent-contract.md +41 -0
- package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +2 -2
- package/.sdd/skills/curated/devtrack-api/references/typeorm-infrastructure.md +7 -9
- package/LICENSE +1 -1
- package/README.md +399 -53
- package/bin/codesdd.js +3 -2
- package/dist/applications/sdd/index.d.ts +16 -0
- package/dist/applications/sdd/index.js +16 -0
- 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 +320 -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 +489 -28
- package/dist/commands/sdd/plugin.d.ts +3 -0
- package/dist/commands/sdd/plugin.js +158 -0
- package/dist/commands/sdd/shared.d.ts +1 -0
- package/dist/commands/sdd/shared.js +11 -22
- package/dist/commands/sdd/skills.js +7 -0
- package/dist/commands/sdd.js +107 -15
- 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 +19 -1
- package/dist/core/cli-command-quality.d.ts +27 -0
- package/dist/core/cli-command-quality.js +180 -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 +200 -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 +20 -1
- package/dist/core/config-schema.js +70 -2
- package/dist/core/config.d.ts +3 -3
- package/dist/core/config.js +4 -4
- package/dist/core/global-config.d.ts +57 -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/agent-runtime-contract.d.ts +204 -0
- package/dist/core/sdd/agent-runtime-contract.js +200 -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 +44 -0
- package/dist/core/sdd/check.js +62 -24
- 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 +53 -8
- package/dist/core/sdd/coordination/coordination-adapters.js +182 -16
- package/dist/core/sdd/coordination/index.d.ts +1 -0
- package/dist/core/sdd/coordination/index.js +1 -0
- package/dist/core/sdd/coordination/redis-runtime.d.ts +131 -0
- package/dist/core/sdd/coordination/redis-runtime.js +698 -0
- package/dist/core/sdd/deepagent-contracts.d.ts +370 -0
- package/dist/core/sdd/deepagent-contracts.js +235 -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 +3 -3
- package/dist/core/sdd/default-bootstrap-files.js +50 -10
- package/dist/core/sdd/default-skills.d.ts +30 -0
- package/dist/core/sdd/default-skills.js +288 -8
- package/dist/core/sdd/devtrack-api-appliance.d.ts +91 -0
- package/dist/core/sdd/devtrack-api-appliance.js +280 -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 +54 -20
- package/dist/core/sdd/domain/capability-diff.d.ts +63 -0
- package/dist/core/sdd/domain/capability-diff.js +200 -0
- package/dist/core/sdd/domain/change-safety-guardrails.d.ts +74 -0
- package/dist/core/sdd/domain/change-safety-guardrails.js +333 -0
- 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/semantic-intent-classifier.d.ts +29 -0
- package/dist/core/sdd/domain/semantic-intent-classifier.js +117 -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/foundation-artifact-map-validator.d.ts +16 -0
- package/dist/core/sdd/foundation-artifact-map-validator.js +71 -0
- package/dist/core/sdd/foundation-layer-manifest.d.ts +24 -0
- package/dist/core/sdd/foundation-layer-manifest.js +117 -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/intent-guard.d.ts +22 -0
- package/dist/core/sdd/intent-guard.js +67 -0
- package/dist/core/sdd/json-schema.js +108 -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 +507 -44
- package/dist/core/sdd/lenses.d.ts +1 -0
- package/dist/core/sdd/lenses.js +29 -1
- package/dist/core/sdd/migrate-workspace.js +95 -2
- package/dist/core/sdd/migrate.d.ts +1 -1
- package/dist/core/sdd/migrate.js +36 -2
- package/dist/core/sdd/package-security-gates.d.ts +21 -0
- package/dist/core/sdd/package-security-gates.js +119 -0
- package/dist/core/sdd/package-structure-gate.d.ts +83 -0
- package/dist/core/sdd/package-structure-gate.js +357 -0
- package/dist/core/sdd/parallel-feat-automation.d.ts +330 -0
- package/dist/core/sdd/parallel-feat-automation.js +424 -0
- package/dist/core/sdd/plugin-broker.d.ts +777 -0
- package/dist/core/sdd/plugin-broker.js +492 -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 +139 -0
- package/dist/core/sdd/plugin-cli.js +265 -0
- package/dist/core/sdd/plugin-evidence.d.ts +348 -0
- package/dist/core/sdd/plugin-evidence.js +307 -0
- package/dist/core/sdd/plugin-manifest.d.ts +232 -0
- package/dist/core/sdd/plugin-manifest.js +225 -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 +447 -0
- package/dist/core/sdd/plugin-registry.js +138 -0
- package/dist/core/sdd/plugin-sdk-contract.d.ts +363 -0
- package/dist/core/sdd/plugin-sdk-contract.js +268 -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 +620 -0
- package/dist/core/sdd/quality-validation.js +239 -0
- package/dist/core/sdd/release-readiness.d.ts +19 -0
- package/dist/core/sdd/release-readiness.js +472 -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/runtime-boundary-contract.d.ts +45 -0
- package/dist/core/sdd/runtime-boundary-contract.js +90 -0
- package/dist/core/sdd/sanitize.d.ts +30 -1
- package/dist/core/sdd/sanitize.js +23 -23
- package/dist/core/sdd/sdk-agent-plugin-quality-gates.d.ts +150 -0
- package/dist/core/sdd/sdk-agent-plugin-quality-gates.js +258 -0
- package/dist/core/sdd/services/agent-run.service.d.ts +97 -0
- package/dist/core/sdd/services/agent-run.service.js +261 -0
- package/dist/core/sdd/services/breakdown.service.js +2 -1
- package/dist/core/sdd/services/capability-diff.service.d.ts +18 -0
- package/dist/core/sdd/services/capability-diff.service.js +26 -0
- package/dist/core/sdd/services/change-safety-preflight.service.d.ts +17 -0
- package/dist/core/sdd/services/change-safety-preflight.service.js +17 -0
- package/dist/core/sdd/services/context.service.d.ts +43 -340
- package/dist/core/sdd/services/context.service.js +341 -25
- 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 +105 -0
- package/dist/core/sdd/services/finalize.service.js +499 -38
- package/dist/core/sdd/services/frontend-gap.service.js +22 -7
- package/dist/core/sdd/services/frontend-impact.service.d.ts +1 -1
- 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/semantic-intent-classifier.service.d.ts +6 -0
- package/dist/core/sdd/services/semantic-intent-classifier.service.js +7 -0
- 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 +23 -0
- package/dist/core/sdd/state.js +313 -66
- package/dist/core/sdd/store/sdd-stores.js +2 -2
- package/dist/core/sdd/structural-health.d.ts +55 -55
- package/dist/core/sdd/types.d.ts +60 -19
- package/dist/core/sdd/types.js +21 -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/views.js +17 -0
- package/dist/core/sdd/workspace-schemas.d.ts +670 -19
- package/dist/core/sdd/workspace-schemas.js +285 -5
- 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/domains/sdd/index.d.ts +6 -0
- package/dist/domains/sdd/index.js +6 -0
- package/dist/infrastructures/sdd/index.d.ts +7 -0
- package/dist/infrastructures/sdd/index.js +6 -0
- package/dist/presentations/cli/sdd/index.d.ts +3 -0
- package/dist/presentations/cli/sdd/index.js +3 -0
- package/dist/shared/sdd/index.d.ts +3 -0
- package/dist/shared/sdd/index.js +2 -0
- 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 +34 -21
- package/schemas/sdd/1-spec.schema.json +1 -1
- package/schemas/sdd/2-plan.schema.json +280 -3
- 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 +701 -5
- 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/agent-runtime-command-plan.schema.json +212 -0
- package/schemas/sdd/agent-runtime-opencode-run-evidence.schema.json +270 -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 +645 -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 +637 -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 +304 -0
- package/schemas/sdd/parallel-feat-automation-request.schema.json +109 -0
- package/schemas/sdd/parallel-feat-scheduler-request.schema.json +116 -0
- package/schemas/sdd/parallel-feat-scheduler-result.schema.json +404 -0
- package/schemas/sdd/plugin-artifact-manifest.schema.json +259 -0
- package/schemas/sdd/plugin-artifact-map.schema.json +223 -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 +678 -0
- package/schemas/sdd/plugin-language-runtime.schema.json +103 -0
- package/schemas/sdd/plugin-package-governance.schema.json +74 -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 +729 -0
- package/schemas/sdd/plugin-rollback-manifest.schema.json +87 -0
- package/schemas/sdd/plugin-runtime-invocation-plan.schema.json +954 -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 +1337 -0
- package/schemas/sdd/quality-run.schema.json +197 -0
- package/schemas/sdd/quality-scenario.schema.json +252 -0
- package/schemas/sdd/sdk-agent-plugin-quality-gate-input.schema.json +168 -0
- package/schemas/sdd/sdk-agent-plugin-quality-gate-report.schema.json +160 -0
- package/schemas/sdd/workspace-catalog.schema.json +13232 -35
- 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
package/dist/core/sdd/check.js
CHANGED
|
@@ -4,14 +4,14 @@ import path from 'node:path';
|
|
|
4
4
|
import { parse as parseYaml } from 'yaml';
|
|
5
5
|
import { CLI_NAME } from '../branding.js';
|
|
6
6
|
import { ID_PATTERNS, } from './types.js';
|
|
7
|
-
import { loadProjectSddConfig, loadStateSnapshot, resolveSddPaths, } from './state.js';
|
|
7
|
+
import { buildDefaultSkillRoutingState, loadProjectSddConfig, loadStateSnapshot, resolveSddPaths, } from './state.js';
|
|
8
8
|
import { DEFAULT_CURATED_SKILL_CATALOG } from './default-skills.js';
|
|
9
9
|
import { renderViews } from './views.js';
|
|
10
10
|
import { syncSddGuideDocs, validateSddGuideDocs } from './docs-sync.js';
|
|
11
11
|
import { evaluateWorkspaceTraceability } from './domain/traceability.js';
|
|
12
12
|
import { detectArchiveArchivedLifecycleCollisions } from './domain/post-active-validation.js';
|
|
13
13
|
import { parseWorkspaceYamlDocument, workspaceTasksSchema, } from './workspace-schemas.js';
|
|
14
|
-
function checkUniqueIds(items, scope, errors) {
|
|
14
|
+
export function checkUniqueIds(items, scope, errors) {
|
|
15
15
|
const seen = new Set();
|
|
16
16
|
for (const item of items) {
|
|
17
17
|
if (seen.has(item.id)) {
|
|
@@ -21,7 +21,7 @@ function checkUniqueIds(items, scope, errors) {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
const FORBIDDEN_TITLE_PATTERNS = ['debate:', 'insight:', '(preencher', '(placeholder'];
|
|
24
|
-
function hasForbiddenTitleToken(title) {
|
|
24
|
+
export function hasForbiddenTitleToken(title) {
|
|
25
25
|
const lowered = title.toLowerCase();
|
|
26
26
|
for (const token of FORBIDDEN_TITLE_PATTERNS) {
|
|
27
27
|
if (lowered.includes(token))
|
|
@@ -29,7 +29,7 @@ function hasForbiddenTitleToken(title) {
|
|
|
29
29
|
}
|
|
30
30
|
return null;
|
|
31
31
|
}
|
|
32
|
-
function validateDiscoveryRecords(records, errors) {
|
|
32
|
+
export function validateDiscoveryRecords(records, errors) {
|
|
33
33
|
for (const record of records) {
|
|
34
34
|
if (record.type === 'INS' && !ID_PATTERNS.insight.test(record.id)) {
|
|
35
35
|
errors.push(`Discovery record ${record.id} is INS but does not follow INS-####`);
|
|
@@ -51,7 +51,7 @@ function validateDiscoveryRecords(records, errors) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
function validateBacklog(items, errors, warnings) {
|
|
54
|
+
export function validateBacklog(items, errors, warnings) {
|
|
55
55
|
const ids = new Set(items.map((item) => item.id));
|
|
56
56
|
const lockOwners = new Map();
|
|
57
57
|
for (const item of items) {
|
|
@@ -79,7 +79,7 @@ function validateBacklog(items, errors, warnings) {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
function validateReferentialIntegrity(snapshot, errors, warnings, isStrict) {
|
|
82
|
+
export function validateReferentialIntegrity(snapshot, errors, warnings, isStrict) {
|
|
83
83
|
const discoveryIds = new Set(snapshot.discoveryIndex.records.map((record) => record.id));
|
|
84
84
|
const backlogIds = new Set(snapshot.backlog.items.map((item) => item.id));
|
|
85
85
|
const frontendGapIds = new Set(snapshot.frontendGaps?.items.map((gap) => gap.id) ?? []);
|
|
@@ -122,6 +122,13 @@ function validateReferentialIntegrity(snapshot, errors, warnings, isStrict) {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
+
if (snapshot.finalizeQueue?.history) {
|
|
126
|
+
for (const fq of snapshot.finalizeQueue.history) {
|
|
127
|
+
if (!backlogIds.has(fq.feature_id)) {
|
|
128
|
+
record(`Finalize history has entry for feature_id="${fq.feature_id}" blocked by an unknown feature.`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
125
132
|
if (snapshot.unblockEvents?.events) {
|
|
126
133
|
for (const ev of snapshot.unblockEvents.events) {
|
|
127
134
|
if (!backlogIds.has(ev.feature_id)) {
|
|
@@ -133,7 +140,7 @@ function validateReferentialIntegrity(snapshot, errors, warnings, isStrict) {
|
|
|
133
140
|
}
|
|
134
141
|
}
|
|
135
142
|
}
|
|
136
|
-
function validateSkillOperationalIntegrity(snapshot, errors) {
|
|
143
|
+
export function validateSkillOperationalIntegrity(snapshot, errors) {
|
|
137
144
|
const knownSkills = new Set((snapshot.skillCatalog?.skills || []).map((skill) => skill.id));
|
|
138
145
|
const currentBundles = new Map((snapshot.skillCatalog?.bundles || []).map((bundle) => [bundle.id, bundle]));
|
|
139
146
|
for (const defaultSkill of DEFAULT_CURATED_SKILL_CATALOG.skills) {
|
|
@@ -172,8 +179,28 @@ function validateSkillOperationalIntegrity(snapshot, errors) {
|
|
|
172
179
|
}
|
|
173
180
|
}
|
|
174
181
|
}
|
|
182
|
+
const currentRoutes = new Map((snapshot.skillRouting?.routes || []).map((route) => [route.domain, route]));
|
|
183
|
+
for (const defaultRoute of buildDefaultSkillRoutingState().routes) {
|
|
184
|
+
const currentRoute = currentRoutes.get(defaultRoute.domain);
|
|
185
|
+
if (!currentRoute) {
|
|
186
|
+
errors.push(`Default skill route "${defaultRoute.domain}" is missing from skill-routing.yaml`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const currentSkills = currentRoute.skills || [];
|
|
190
|
+
const currentBundles = currentRoute.bundles || [];
|
|
191
|
+
for (const skillId of defaultRoute.skills) {
|
|
192
|
+
if (!currentSkills.includes(skillId)) {
|
|
193
|
+
errors.push(`Default skill route "${defaultRoute.domain}" is missing skill "${skillId}"`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
for (const bundleId of defaultRoute.bundles) {
|
|
197
|
+
if (!currentBundles.includes(bundleId)) {
|
|
198
|
+
errors.push(`Default skill route "${defaultRoute.domain}" is missing bundle "${bundleId}"`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
175
202
|
}
|
|
176
|
-
function computeGraphSummary(items) {
|
|
203
|
+
export function computeGraphSummary(items) {
|
|
177
204
|
const byId = new Map(items.map((item) => [item.id, item]));
|
|
178
205
|
const runnable = items.filter((item) => {
|
|
179
206
|
if (item.status === 'DONE' || item.status === 'ARCHIVED')
|
|
@@ -226,12 +253,12 @@ function computeGraphSummary(items) {
|
|
|
226
253
|
lockConflicts: conflictingIds.size,
|
|
227
254
|
};
|
|
228
255
|
}
|
|
229
|
-
function roundPercent(done, total) {
|
|
256
|
+
export function roundPercent(done, total) {
|
|
230
257
|
if (total <= 0)
|
|
231
258
|
return 0;
|
|
232
259
|
return Math.round((done / total) * 100);
|
|
233
260
|
}
|
|
234
|
-
function computeProgress(items) {
|
|
261
|
+
export function computeProgress(items) {
|
|
235
262
|
const activeItems = items.filter((item) => item.status !== 'ARCHIVED');
|
|
236
263
|
const total = activeItems.length;
|
|
237
264
|
const done = activeItems.filter((item) => item.status === 'DONE').length;
|
|
@@ -262,14 +289,14 @@ function computeProgress(items) {
|
|
|
262
289
|
progressByRadar,
|
|
263
290
|
};
|
|
264
291
|
}
|
|
265
|
-
function validateTechDebt(items, errors) {
|
|
292
|
+
export function validateTechDebt(items, errors) {
|
|
266
293
|
for (const item of items) {
|
|
267
294
|
if (!ID_PATTERNS.techDebt.test(item.id)) {
|
|
268
295
|
errors.push(`Technical debt item ${item.id} does not follow TD-###`);
|
|
269
296
|
}
|
|
270
297
|
}
|
|
271
298
|
}
|
|
272
|
-
function validateFrontendReferences(gaps, backlog, errors, warnings) {
|
|
299
|
+
export function validateFrontendReferences(gaps, backlog, errors, warnings) {
|
|
273
300
|
const gapIds = new Set(gaps.map((g) => g.id));
|
|
274
301
|
for (const item of backlog) {
|
|
275
302
|
for (const gapRef of item.frontend_gap_refs) {
|
|
@@ -285,7 +312,7 @@ function validateFrontendReferences(gaps, backlog, errors, warnings) {
|
|
|
285
312
|
}
|
|
286
313
|
}
|
|
287
314
|
}
|
|
288
|
-
async function validateActiveTaskChecklist(activeDir, items, warnings) {
|
|
315
|
+
export async function validateActiveTaskChecklist(activeDir, items, warnings) {
|
|
289
316
|
for (const item of items) {
|
|
290
317
|
if (item.status !== 'IN_PROGRESS')
|
|
291
318
|
continue;
|
|
@@ -325,7 +352,7 @@ async function validateActiveTaskChecklist(activeDir, items, warnings) {
|
|
|
325
352
|
}
|
|
326
353
|
}
|
|
327
354
|
}
|
|
328
|
-
async function validateWorkspaceCoherence(activeDir, archivedDir, items, warnings) {
|
|
355
|
+
export async function validateWorkspaceCoherence(activeDir, archivedDir, items, warnings) {
|
|
329
356
|
for (const item of items) {
|
|
330
357
|
const activePath = path.join(activeDir, item.id);
|
|
331
358
|
const archivedPath = path.join(archivedDir, item.id);
|
|
@@ -342,13 +369,13 @@ async function validateWorkspaceCoherence(activeDir, archivedDir, items, warning
|
|
|
342
369
|
}
|
|
343
370
|
}
|
|
344
371
|
}
|
|
345
|
-
function isPrivacyComplianceBacklogItem(item) {
|
|
372
|
+
export function isPrivacyComplianceBacklogItem(item) {
|
|
346
373
|
if (item.origin_ref === 'EPIC-0020' || item.origin_ref === 'EPIC-0021')
|
|
347
374
|
return true;
|
|
348
375
|
const refs = new Set(item.acceptance_refs || []);
|
|
349
376
|
return refs.has('EPIC-0020') || refs.has('EPIC-0021') || refs.has('DEB-0021') || refs.has('INS-0021');
|
|
350
377
|
}
|
|
351
|
-
function validatePrivacySourceRegistry(snapshot, warnings) {
|
|
378
|
+
export function validatePrivacySourceRegistry(snapshot, warnings) {
|
|
352
379
|
const privacyItems = snapshot.backlog.items.filter((item) => item.status !== 'DONE' && item.status !== 'ARCHIVED' && isPrivacyComplianceBacklogItem(item));
|
|
353
380
|
if (privacyItems.length === 0)
|
|
354
381
|
return;
|
|
@@ -385,7 +412,7 @@ function validatePrivacySourceRegistry(snapshot, warnings) {
|
|
|
385
412
|
warnings.push(`Privacy source registry metadata incomplete for: ${missingMetadata.slice(0, 12).join(', ')}${missingMetadata.length > 12 ? ' ...' : ''}`);
|
|
386
413
|
}
|
|
387
414
|
}
|
|
388
|
-
async function validatePrivacyWorkspaceChecklist(activeDir, items, warnings) {
|
|
415
|
+
export async function validatePrivacyWorkspaceChecklist(activeDir, items, warnings) {
|
|
389
416
|
const privacyItems = items.filter((item) => item.status === 'IN_PROGRESS' && isPrivacyComplianceBacklogItem(item));
|
|
390
417
|
for (const item of privacyItems) {
|
|
391
418
|
const specPath = path.join(activeDir, item.id, '1-spec.yaml');
|
|
@@ -433,7 +460,7 @@ async function validatePrivacyWorkspaceChecklist(activeDir, items, warnings) {
|
|
|
433
460
|
}
|
|
434
461
|
}
|
|
435
462
|
}
|
|
436
|
-
async function validateTraceabilityWorkspaceChecklist(projectRoot, activeDir, items, warnings) {
|
|
463
|
+
export async function validateTraceabilityWorkspaceChecklist(projectRoot, activeDir, items, warnings) {
|
|
437
464
|
const traceabilityItems = items.filter((item) => item.status === 'IN_PROGRESS');
|
|
438
465
|
for (const item of traceabilityItems) {
|
|
439
466
|
const specPath = path.join(activeDir, item.id, '1-spec.yaml');
|
|
@@ -458,12 +485,12 @@ async function validateTraceabilityWorkspaceChecklist(projectRoot, activeDir, it
|
|
|
458
485
|
}
|
|
459
486
|
}
|
|
460
487
|
}
|
|
461
|
-
function featureRequiresQualityContract(item) {
|
|
488
|
+
export function featureRequiresQualityContract(item) {
|
|
462
489
|
if (item.status === 'ARCHIVED' || item.status === 'DONE')
|
|
463
490
|
return false;
|
|
464
491
|
return Boolean(item.quality_contract) || item.status === 'IN_PROGRESS' || item.origin_ref === 'EPIC-0013';
|
|
465
492
|
}
|
|
466
|
-
async function detectMissingQualityArtifacts(activeDir, items) {
|
|
493
|
+
export async function detectMissingQualityArtifacts(activeDir, items) {
|
|
467
494
|
const missing = [];
|
|
468
495
|
for (const item of items) {
|
|
469
496
|
if (item.status !== 'IN_PROGRESS')
|
|
@@ -477,7 +504,7 @@ async function detectMissingQualityArtifacts(activeDir, items) {
|
|
|
477
504
|
}
|
|
478
505
|
return missing;
|
|
479
506
|
}
|
|
480
|
-
function parseRouteToken(value) {
|
|
507
|
+
export function parseRouteToken(value) {
|
|
481
508
|
const token = value.trim();
|
|
482
509
|
if (!token)
|
|
483
510
|
return null;
|
|
@@ -494,7 +521,7 @@ function parseRouteToken(value) {
|
|
|
494
521
|
return inlineRoute[0];
|
|
495
522
|
return null;
|
|
496
523
|
}
|
|
497
|
-
function featureHasMetadataFrontendEvidence(item) {
|
|
524
|
+
export function featureHasMetadataFrontendEvidence(item) {
|
|
498
525
|
const routes = [
|
|
499
526
|
...item.produces.map(parseRouteToken),
|
|
500
527
|
...item.consumes.map(parseRouteToken),
|
|
@@ -506,7 +533,7 @@ function featureHasMetadataFrontendEvidence(item) {
|
|
|
506
533
|
item.touches.includes('frontend') ||
|
|
507
534
|
item.execution_kind === 'frontend_coverage');
|
|
508
535
|
}
|
|
509
|
-
async function validateCanonicalSddStructure(memoryRoot, errors) {
|
|
536
|
+
export async function validateCanonicalSddStructure(memoryRoot, errors) {
|
|
510
537
|
const forbiddenTopLevelDirs = ['backlog', 'features', 'finalize', 'queue'];
|
|
511
538
|
for (const dirName of forbiddenTopLevelDirs) {
|
|
512
539
|
const candidate = path.join(memoryRoot, dirName);
|
|
@@ -541,6 +568,8 @@ export class SddCheckCommand {
|
|
|
541
568
|
backlog: 0,
|
|
542
569
|
techDebt: 0,
|
|
543
570
|
finalizeQueue: 0,
|
|
571
|
+
finalizeQueuePending: 0,
|
|
572
|
+
finalizeQueueDone: 0,
|
|
544
573
|
frontendEnabled: false,
|
|
545
574
|
frontendGaps: 0,
|
|
546
575
|
frontendRoutes: 0,
|
|
@@ -618,6 +647,8 @@ export class SddCheckCommand {
|
|
|
618
647
|
backlog: 0,
|
|
619
648
|
techDebt: 0,
|
|
620
649
|
finalizeQueue: 0,
|
|
650
|
+
finalizeQueuePending: 0,
|
|
651
|
+
finalizeQueueDone: 0,
|
|
621
652
|
frontendEnabled: config.frontend.enabled,
|
|
622
653
|
frontendGaps: 0,
|
|
623
654
|
frontendRoutes: 0,
|
|
@@ -658,6 +689,8 @@ export class SddCheckCommand {
|
|
|
658
689
|
backlog: 0,
|
|
659
690
|
techDebt: 0,
|
|
660
691
|
finalizeQueue: 0,
|
|
692
|
+
finalizeQueuePending: 0,
|
|
693
|
+
finalizeQueueDone: 0,
|
|
661
694
|
frontendEnabled: config.frontend.enabled,
|
|
662
695
|
frontendGaps: 0,
|
|
663
696
|
frontendRoutes: 0,
|
|
@@ -796,6 +829,9 @@ export class SddCheckCommand {
|
|
|
796
829
|
featuresMissingFgapLink.length === 0;
|
|
797
830
|
const qualityContractSync = featuresMissingQualityContract.length === 0 &&
|
|
798
831
|
featuresMissingQualityArtifact.length === 0;
|
|
832
|
+
const finalizeQueuePending = snapshot.finalizeQueue.items.filter((item) => item.status === 'PENDING').length;
|
|
833
|
+
const finalizeQueueDone = snapshot.finalizeQueue.history.length +
|
|
834
|
+
snapshot.finalizeQueue.items.filter((item) => item.status === 'DONE').length;
|
|
799
835
|
return {
|
|
800
836
|
valid: errors.length === 0,
|
|
801
837
|
errors,
|
|
@@ -804,7 +840,9 @@ export class SddCheckCommand {
|
|
|
804
840
|
discovery: snapshot.discoveryIndex.records.length,
|
|
805
841
|
backlog: snapshot.backlog.items.length,
|
|
806
842
|
techDebt: snapshot.techDebt.items.length,
|
|
807
|
-
finalizeQueue:
|
|
843
|
+
finalizeQueue: finalizeQueuePending,
|
|
844
|
+
finalizeQueuePending,
|
|
845
|
+
finalizeQueueDone,
|
|
808
846
|
frontendEnabled: config.frontend.enabled,
|
|
809
847
|
frontendGaps: snapshot.frontendGaps?.items.length ?? 0,
|
|
810
848
|
frontendRoutes: snapshot.frontendMap?.routes.length ?? 0,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const CURRENT_SDD_STATE_VERSION = 3;
|
|
2
|
+
export declare const CURRENT_SDD_CONTRACT_NAME = "codesdd-sdd";
|
|
3
|
+
export declare const CURRENT_CODESDD_MIN_CLI_VERSION = "1.2.2";
|
|
4
|
+
export declare const CURRENT_SDD_LEGACY_COMPATIBILITY = "migration-only";
|
|
5
|
+
export interface SddContractConfig {
|
|
6
|
+
name: string;
|
|
7
|
+
version: number;
|
|
8
|
+
min_cli_version: string;
|
|
9
|
+
legacy_compatibility: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function buildSddContractConfig(): SddContractConfig;
|
|
12
|
+
export declare function sddContractMismatchReasons(value: unknown): string[];
|
|
13
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const CURRENT_SDD_STATE_VERSION = 3;
|
|
2
|
+
export const CURRENT_SDD_CONTRACT_NAME = 'codesdd-sdd';
|
|
3
|
+
export const CURRENT_CODESDD_MIN_CLI_VERSION = '1.2.2';
|
|
4
|
+
export const CURRENT_SDD_LEGACY_COMPATIBILITY = 'migration-only';
|
|
5
|
+
export function buildSddContractConfig() {
|
|
6
|
+
return {
|
|
7
|
+
name: CURRENT_SDD_CONTRACT_NAME,
|
|
8
|
+
version: CURRENT_SDD_STATE_VERSION,
|
|
9
|
+
min_cli_version: CURRENT_CODESDD_MIN_CLI_VERSION,
|
|
10
|
+
legacy_compatibility: CURRENT_SDD_LEGACY_COMPATIBILITY,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
export function sddContractMismatchReasons(value) {
|
|
17
|
+
if (!isRecord(value)) {
|
|
18
|
+
return ['sdd_contract ausente'];
|
|
19
|
+
}
|
|
20
|
+
const expected = buildSddContractConfig();
|
|
21
|
+
const reasons = [];
|
|
22
|
+
if (value.name !== expected.name) {
|
|
23
|
+
reasons.push(`name=${String(value.name || '') || '<empty>'}`);
|
|
24
|
+
}
|
|
25
|
+
if (value.version !== expected.version) {
|
|
26
|
+
reasons.push(`version=${String(value.version || '') || '<empty>'}`);
|
|
27
|
+
}
|
|
28
|
+
if (value.min_cli_version !== expected.min_cli_version) {
|
|
29
|
+
reasons.push(`min_cli_version=${String(value.min_cli_version || '') || '<empty>'}`);
|
|
30
|
+
}
|
|
31
|
+
if (value.legacy_compatibility !== expected.legacy_compatibility) {
|
|
32
|
+
reasons.push(`legacy_compatibility=${String(value.legacy_compatibility || '') || '<empty>'}`);
|
|
33
|
+
}
|
|
34
|
+
return reasons;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { type AcquireOptions } from '../state-lock.js';
|
|
2
|
+
import { type GlobalConfig } from '../../global-config.js';
|
|
3
|
+
import { type RedisRuntimeConfig, type RedisRuntimeStatus } from './redis-runtime.js';
|
|
4
|
+
export { resolveRedisBoundaryConfig } from './redis-runtime.js';
|
|
2
5
|
export interface CoordinationLockAdapter {
|
|
3
6
|
withLock<T>(scope: string, fn: () => Promise<T>, options?: AcquireOptions): Promise<T>;
|
|
4
7
|
}
|
|
@@ -24,15 +27,16 @@ export interface CoordinationEventBusAdapter {
|
|
|
24
27
|
publish(event: CoordinationEvent): Promise<void>;
|
|
25
28
|
drain(): Promise<CoordinationEvent[]>;
|
|
26
29
|
}
|
|
27
|
-
export
|
|
28
|
-
requested: boolean;
|
|
29
|
-
namespace: string;
|
|
30
|
-
url?: string;
|
|
31
|
-
}
|
|
30
|
+
export type RedisBoundaryConfig = RedisRuntimeConfig;
|
|
32
31
|
export interface SddCoordinationAdapters {
|
|
33
|
-
mode: 'filesystem';
|
|
32
|
+
mode: 'filesystem' | 'redis' | 'hybrid';
|
|
33
|
+
cacheTier: {
|
|
34
|
+
root: string;
|
|
35
|
+
projectFingerprint: string;
|
|
36
|
+
namespace: string;
|
|
37
|
+
};
|
|
34
38
|
redis: RedisBoundaryConfig & {
|
|
35
|
-
status:
|
|
39
|
+
status: RedisRuntimeStatus;
|
|
36
40
|
reason: string;
|
|
37
41
|
};
|
|
38
42
|
locks: CoordinationLockAdapter;
|
|
@@ -54,6 +58,36 @@ export declare class InMemoryCoordinationCache implements CoordinationCacheAdapt
|
|
|
54
58
|
delete(key: string): Promise<void>;
|
|
55
59
|
clear(): Promise<void>;
|
|
56
60
|
}
|
|
61
|
+
export declare class MultiTierCoordinationCache implements CoordinationCacheAdapter {
|
|
62
|
+
private readonly l1Cache;
|
|
63
|
+
private readonly projectFingerprint;
|
|
64
|
+
private readonly configFingerprint;
|
|
65
|
+
private readonly namespace;
|
|
66
|
+
private readonly l2Root;
|
|
67
|
+
constructor(options: {
|
|
68
|
+
projectRoot: string;
|
|
69
|
+
namespace?: string;
|
|
70
|
+
configFingerprint?: string;
|
|
71
|
+
cacheRootDir?: string;
|
|
72
|
+
});
|
|
73
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
74
|
+
set<T>(key: string, value: T, options?: {
|
|
75
|
+
ttlMs?: number;
|
|
76
|
+
}): Promise<void>;
|
|
77
|
+
delete(key: string): Promise<void>;
|
|
78
|
+
clear(): Promise<void>;
|
|
79
|
+
pruneExpired(): Promise<number>;
|
|
80
|
+
describeTierState(): {
|
|
81
|
+
root: string;
|
|
82
|
+
projectFingerprint: string;
|
|
83
|
+
namespace: string;
|
|
84
|
+
};
|
|
85
|
+
private toEntryPath;
|
|
86
|
+
private remainingTtlMs;
|
|
87
|
+
private listEntryFiles;
|
|
88
|
+
private readEntry;
|
|
89
|
+
private safeUnlink;
|
|
90
|
+
}
|
|
57
91
|
export declare class InMemoryCoordinationQueue<T = unknown> implements CoordinationQueueAdapter<T> {
|
|
58
92
|
private readonly topics;
|
|
59
93
|
enqueue(topic: string, item: T): Promise<void>;
|
|
@@ -65,9 +99,20 @@ export declare class InMemoryCoordinationEventBus implements CoordinationEventBu
|
|
|
65
99
|
publish(event: CoordinationEvent): Promise<void>;
|
|
66
100
|
drain(): Promise<CoordinationEvent[]>;
|
|
67
101
|
}
|
|
68
|
-
export declare function resolveRedisBoundaryConfig(env?: NodeJS.ProcessEnv): RedisBoundaryConfig;
|
|
69
102
|
export declare function createFilesystemFirstCoordinationAdapters(options: {
|
|
70
103
|
stateDir: string;
|
|
104
|
+
projectRoot?: string;
|
|
105
|
+
configFingerprint?: string;
|
|
106
|
+
cacheRootDir?: string;
|
|
71
107
|
env?: NodeJS.ProcessEnv;
|
|
108
|
+
globalConfig?: Partial<GlobalConfig>;
|
|
72
109
|
}): SddCoordinationAdapters;
|
|
110
|
+
export declare function createSddCoordinationAdapters(options: {
|
|
111
|
+
stateDir: string;
|
|
112
|
+
projectRoot?: string;
|
|
113
|
+
configFingerprint?: string;
|
|
114
|
+
cacheRootDir?: string;
|
|
115
|
+
env?: NodeJS.ProcessEnv;
|
|
116
|
+
globalConfig?: Partial<GlobalConfig>;
|
|
117
|
+
}): Promise<SddCoordinationAdapters>;
|
|
73
118
|
//# sourceMappingURL=coordination-adapters.d.ts.map
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { withStateLock } from '../state-lock.js';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { promises as fs } from 'node:fs';
|
|
5
|
+
import { createProjectFingerprint, ensureGlobalCacheLayout, getGlobalCacheDir } from '../../global-config.js';
|
|
6
|
+
import { buildRedisOperationalReport, RedisClientFactory, RedisCoordinationCache, RedisEventBusAdapter, RedisLockAdapter, RedisQueueAdapter, resolveRedisBoundaryConfig, } from './redis-runtime.js';
|
|
7
|
+
export { resolveRedisBoundaryConfig } from './redis-runtime.js';
|
|
2
8
|
export class FileSystemLockAdapter {
|
|
3
9
|
stateDir;
|
|
4
10
|
constructor(stateDir) {
|
|
@@ -31,6 +37,131 @@ export class InMemoryCoordinationCache {
|
|
|
31
37
|
this.entries.clear();
|
|
32
38
|
}
|
|
33
39
|
}
|
|
40
|
+
export class MultiTierCoordinationCache {
|
|
41
|
+
l1Cache = new InMemoryCoordinationCache();
|
|
42
|
+
projectFingerprint;
|
|
43
|
+
configFingerprint;
|
|
44
|
+
namespace;
|
|
45
|
+
l2Root;
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.projectFingerprint = createProjectFingerprint(options.projectRoot);
|
|
48
|
+
this.configFingerprint = options.configFingerprint ?? 'default';
|
|
49
|
+
this.namespace = options.namespace ?? 'coordination';
|
|
50
|
+
this.l2Root = path.join(options.cacheRootDir ?? getGlobalCacheDir(), 'projects', this.projectFingerprint, this.namespace);
|
|
51
|
+
}
|
|
52
|
+
async get(key) {
|
|
53
|
+
const l1Value = await this.l1Cache.get(key);
|
|
54
|
+
if (typeof l1Value !== 'undefined') {
|
|
55
|
+
return l1Value;
|
|
56
|
+
}
|
|
57
|
+
const filePath = this.toEntryPath(key);
|
|
58
|
+
const diskEntry = await this.readEntry(filePath);
|
|
59
|
+
if (!diskEntry) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const ttlMs = this.remainingTtlMs(diskEntry.expires_at);
|
|
63
|
+
if (ttlMs === 0) {
|
|
64
|
+
await this.safeUnlink(filePath);
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
await this.l1Cache.set(key, diskEntry.value, ttlMs > 0 ? { ttlMs } : {});
|
|
68
|
+
return diskEntry.value;
|
|
69
|
+
}
|
|
70
|
+
async set(key, value, options = {}) {
|
|
71
|
+
await this.l1Cache.set(key, value, options);
|
|
72
|
+
await fs.mkdir(this.l2Root, { recursive: true });
|
|
73
|
+
const entry = {
|
|
74
|
+
schema_version: 1,
|
|
75
|
+
key,
|
|
76
|
+
value,
|
|
77
|
+
created_at: new Date().toISOString(),
|
|
78
|
+
expires_at: options.ttlMs ? new Date(Date.now() + options.ttlMs).toISOString() : undefined,
|
|
79
|
+
project_fingerprint: this.projectFingerprint,
|
|
80
|
+
config_fingerprint: this.configFingerprint,
|
|
81
|
+
namespace: this.namespace,
|
|
82
|
+
};
|
|
83
|
+
await fs.writeFile(this.toEntryPath(key), JSON.stringify(entry), 'utf-8');
|
|
84
|
+
}
|
|
85
|
+
async delete(key) {
|
|
86
|
+
await this.l1Cache.delete(key);
|
|
87
|
+
await this.safeUnlink(this.toEntryPath(key));
|
|
88
|
+
}
|
|
89
|
+
async clear() {
|
|
90
|
+
await this.l1Cache.clear();
|
|
91
|
+
await fs.rm(this.l2Root, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
async pruneExpired() {
|
|
94
|
+
const files = await this.listEntryFiles();
|
|
95
|
+
let pruned = 0;
|
|
96
|
+
for (const filePath of files) {
|
|
97
|
+
const entry = await this.readEntry(filePath);
|
|
98
|
+
if (!entry) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (this.remainingTtlMs(entry.expires_at) === 0) {
|
|
102
|
+
await this.safeUnlink(filePath);
|
|
103
|
+
pruned += 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return pruned;
|
|
107
|
+
}
|
|
108
|
+
describeTierState() {
|
|
109
|
+
return {
|
|
110
|
+
root: this.l2Root,
|
|
111
|
+
projectFingerprint: this.projectFingerprint,
|
|
112
|
+
namespace: this.namespace,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
toEntryPath(key) {
|
|
116
|
+
const hashedKey = createHash('sha256').update(key).digest('hex');
|
|
117
|
+
return path.join(this.l2Root, `${hashedKey}.json`);
|
|
118
|
+
}
|
|
119
|
+
remainingTtlMs(expiresAtIso) {
|
|
120
|
+
if (!expiresAtIso) {
|
|
121
|
+
return -1;
|
|
122
|
+
}
|
|
123
|
+
const expiresAt = Date.parse(expiresAtIso);
|
|
124
|
+
if (Number.isNaN(expiresAt)) {
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
const remaining = expiresAt - Date.now();
|
|
128
|
+
return remaining > 0 ? remaining : 0;
|
|
129
|
+
}
|
|
130
|
+
async listEntryFiles() {
|
|
131
|
+
try {
|
|
132
|
+
const files = await fs.readdir(this.l2Root);
|
|
133
|
+
return files
|
|
134
|
+
.filter((fileName) => fileName.endsWith('.json'))
|
|
135
|
+
.map((fileName) => path.join(this.l2Root, fileName));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async readEntry(filePath) {
|
|
142
|
+
try {
|
|
143
|
+
const raw = await fs.readFile(filePath, 'utf-8');
|
|
144
|
+
const parsed = JSON.parse(raw);
|
|
145
|
+
if (parsed.schema_version !== 1 ||
|
|
146
|
+
parsed.project_fingerprint !== this.projectFingerprint ||
|
|
147
|
+
parsed.config_fingerprint !== this.configFingerprint) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
return parsed;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async safeUnlink(filePath) {
|
|
157
|
+
try {
|
|
158
|
+
await fs.unlink(filePath);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// best effort cleanup
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
34
165
|
export class InMemoryCoordinationQueue {
|
|
35
166
|
topics = new Map();
|
|
36
167
|
async enqueue(topic, item) {
|
|
@@ -57,31 +188,66 @@ export class InMemoryCoordinationEventBus {
|
|
|
57
188
|
return this.events.splice(0, this.events.length);
|
|
58
189
|
}
|
|
59
190
|
}
|
|
60
|
-
export function resolveRedisBoundaryConfig(env = process.env) {
|
|
61
|
-
const url = env.CODESDD_REDIS_URL?.trim() || env.REDIS_URL?.trim() || undefined;
|
|
62
|
-
const requestedByFlag = env.CODESDD_REDIS_ENABLED === 'true';
|
|
63
|
-
const namespace = env.CODESDD_REDIS_NAMESPACE?.trim() || 'codesdd';
|
|
64
|
-
return {
|
|
65
|
-
requested: Boolean(url || requestedByFlag),
|
|
66
|
-
namespace,
|
|
67
|
-
url,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
191
|
export function createFilesystemFirstCoordinationAdapters(options) {
|
|
71
|
-
|
|
192
|
+
if (!options.cacheRootDir) {
|
|
193
|
+
ensureGlobalCacheLayout();
|
|
194
|
+
}
|
|
195
|
+
const redis = resolveRedisBoundaryConfig(options.env, options.globalConfig);
|
|
196
|
+
const cache = new MultiTierCoordinationCache({
|
|
197
|
+
projectRoot: options.projectRoot ?? process.cwd(),
|
|
198
|
+
configFingerprint: options.configFingerprint,
|
|
199
|
+
cacheRootDir: options.cacheRootDir,
|
|
200
|
+
});
|
|
72
201
|
return {
|
|
73
202
|
mode: 'filesystem',
|
|
203
|
+
cacheTier: cache.describeTierState(),
|
|
74
204
|
redis: {
|
|
75
205
|
...redis,
|
|
76
|
-
status: redis.requested ? 'requested-unavailable' : 'disabled',
|
|
77
|
-
reason: redis.
|
|
78
|
-
? 'Redis
|
|
79
|
-
:
|
|
206
|
+
status: redis.validationErrors.length > 0 ? 'blocked' : redis.requested ? 'requested-unavailable' : 'disabled',
|
|
207
|
+
reason: redis.validationErrors.length > 0
|
|
208
|
+
? 'Redis configuration is invalid and was blocked fail-closed.'
|
|
209
|
+
: redis.requested
|
|
210
|
+
? 'Redis is requested but unavailable; filesystem-first defaults remain authoritative.'
|
|
211
|
+
: 'Redis is optional and disabled; filesystem-first defaults are authoritative.',
|
|
80
212
|
},
|
|
81
213
|
locks: new FileSystemLockAdapter(options.stateDir),
|
|
82
|
-
cache
|
|
214
|
+
cache,
|
|
83
215
|
queues: new InMemoryCoordinationQueue(),
|
|
84
216
|
events: new InMemoryCoordinationEventBus(),
|
|
85
217
|
};
|
|
86
218
|
}
|
|
219
|
+
export async function createSddCoordinationAdapters(options) {
|
|
220
|
+
const filesystem = createFilesystemFirstCoordinationAdapters(options);
|
|
221
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
222
|
+
const redis = resolveRedisBoundaryConfig(options.env, options.globalConfig);
|
|
223
|
+
const report = await buildRedisOperationalReport({
|
|
224
|
+
env: options.env,
|
|
225
|
+
globalConfig: options.globalConfig,
|
|
226
|
+
});
|
|
227
|
+
if (report.status !== 'ready' || !redis.url) {
|
|
228
|
+
return {
|
|
229
|
+
...filesystem,
|
|
230
|
+
redis: {
|
|
231
|
+
...redis,
|
|
232
|
+
status: report.status,
|
|
233
|
+
reason: report.reason,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const projectFingerprint = createProjectFingerprint(projectRoot);
|
|
238
|
+
const factory = new RedisClientFactory(redis);
|
|
239
|
+
return {
|
|
240
|
+
...filesystem,
|
|
241
|
+
mode: redis.fallback === 'filesystem' ? 'hybrid' : 'redis',
|
|
242
|
+
redis: {
|
|
243
|
+
...redis,
|
|
244
|
+
status: 'ready',
|
|
245
|
+
reason: report.reason,
|
|
246
|
+
},
|
|
247
|
+
cache: new RedisCoordinationCache(factory, filesystem.cache, projectFingerprint),
|
|
248
|
+
locks: new RedisLockAdapter(factory, filesystem.locks, projectFingerprint),
|
|
249
|
+
queues: new RedisQueueAdapter(factory, filesystem.queues, projectFingerprint),
|
|
250
|
+
events: new RedisEventBusAdapter(factory, filesystem.events, projectFingerprint),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
87
253
|
//# sourceMappingURL=coordination-adapters.js.map
|