diff --git a/.github/workflows/community-smoke.yml b/.github/workflows/community-smoke.yml index 9dfe27d3bf..896ab21913 100644 --- a/.github/workflows/community-smoke.yml +++ b/.github/workflows/community-smoke.yml @@ -93,18 +93,8 @@ jobs: test -f .specify/presets/workflow-preset/.composed/speckit.tasks.md for arch_skill in \ - speckit-arch-scenario-generate \ - speckit-arch-logical-generate \ - speckit-arch-process-generate \ - speckit-arch-development-generate \ - speckit-arch-physical-generate \ - speckit-arch-full-generate \ - speckit-arch-full-reverse \ - speckit-arch-scenario-reverse \ - speckit-arch-logical-reverse \ - speckit-arch-process-reverse \ - speckit-arch-development-reverse \ - speckit-arch-physical-reverse; do + speckit-arch-generate \ + speckit-arch-reverse; do test -f ".claude/skills/$arch_skill/SKILL.md" done for preview_skill in \ @@ -171,11 +161,9 @@ jobs: /tmp/specify-community-smoke-venv/bin/specify extension add "$GITHUB_WORKSPACE/extensions/$extension_id" --dev case "$extension_id" in arch) - test -f .claude/skills/speckit-arch-scenario-generate/SKILL.md - test -f .claude/skills/speckit-arch-full-generate/SKILL.md - test -f .claude/skills/speckit-arch-full-reverse/SKILL.md - test -f .claude/skills/speckit-arch-scenario-reverse/SKILL.md - grep -q "scenario view" .claude/skills/speckit-arch-scenario-generate/SKILL.md + test -f .claude/skills/speckit-arch-generate/SKILL.md + test -f .claude/skills/speckit-arch-reverse/SKILL.md + grep -q "architecture planning contract" .claude/skills/speckit-arch-generate/SKILL.md ;; preview) for preview_skill in \ @@ -212,4 +200,4 @@ jobs: /tmp/specify-community-smoke-venv/bin/specify preset resolve plan-template | tee resolve-plan-template.txt grep -q "workflow-preset" resolve-plan-template.txt - grep -q "Composition chain" resolve-plan-template.txt + grep -q "plan-template" resolve-plan-template.txt diff --git a/README.md b/README.md index 274c07bd8c..988e88ae1b 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ specify init my-project --integration codex --ignore-agent-tools | 类型 | ID | 来源目录 | 作用 | | --- | --- | --- | --- | | 自动扩展 | `agent-context` | `extensions/agent-context` | 维护 AGENTS、CLAUDE、Copilot 等 agent context 文件里的 Spec Kit 受管段。 | -| 默认扩展 | `arch` | `extensions/arch` | 生成或反向生成项目级 4+1 架构视图,形成架构 SSOT。 | +| 默认扩展 | `arch` | `extensions/arch` | 生成或反向生成面向 `/speckit.plan` 的架构规划契约。 | | 默认扩展 | `discovery` | `extensions/discovery` | 在正式计划前做可行性、技术选型、旧代码评估、接口理解、PoC 和场景化技术决策。 | | 默认扩展 | `intake` | `extensions/intake` | 把 PRD、设计稿、Figma、视觉规格资产包、preview 覆盖证据、测试用例等来源归一化为 SDD 可消费的证据包。 | | 默认扩展 | `preview` | `extensions/preview` | 从规格和计划生成低、中、高保真 Markdown 或自包含 HTML 预览。 | @@ -77,40 +77,26 @@ specify init my-project --integration codex --ignore-agent-tools ### `arch` -`arch` 给项目补一层架构记忆。它不是 feature 计划,也不是实现设计;它负责把项目级边界、运行时职责、部署假设、约束和架构缺口写成稳定 SSOT。 +`arch` 给项目补一层架构记忆。它不是 feature 计划,也不是实现设计;它负责把项目级边界、约束、已定决策、禁止方向、开放问题和 plan review checklist 写成唯一的规划契约。 常用命令: ```text -/speckit.arch.scenario-generate -/speckit.arch.logical-generate -/speckit.arch.process-generate -/speckit.arch.development-generate -/speckit.arch.physical-generate -/speckit.arch.scenario-reverse -/speckit.arch.logical-reverse -/speckit.arch.process-reverse -/speckit.arch.development-reverse -/speckit.arch.physical-reverse +/speckit.arch.generate +/speckit.arch.reverse ``` 主要产物: ```text .specify/memory/architecture.md -.specify/memory/architecture-scenario-view.md -.specify/memory/architecture-logical-view.md -.specify/memory/architecture-process-view.md -.specify/memory/architecture-development-view.md -.specify/memory/architecture-physical-view.md -.specify/memory/architecture-repo-facts.md ``` 使用建议: -- 新项目先跑 `*-generate`,把目标架构讲清楚。 -- 旧仓库先跑 `*-reverse`,从真实文件、入口、配置、测试和部署线索反推架构事实。 -- 五个视图都足够具体后,再让 `architecture.md` 成为后续规划的架构摘要。 +- 新项目跑 `/speckit.arch.generate`,把目标架构约束整理成下游 plan 可消费的契约。 +- 旧仓库跑 `/speckit.arch.reverse`,从真实文件、入口、配置、测试和部署线索反推可证据支撑的规划规则。 +- 每条规则都应带 `Source / Basis`;开放问题用 `BLOCKS_PLAN` 或 `CAN_PROCEED_WITH_GUARDRAIL` 标明对规划的影响。 ### `discovery` @@ -369,28 +355,6 @@ specify extension add git specify preset add lean ``` -### `arch-governance` - -`arch-governance` 位于: - -```text -extensions/arch/presets/arch-governance/ -``` - -它包装 `/speckit.plan`,让规划阶段显式读取 `arch` 扩展产出的架构 SSOT。适合已经用 `arch` 维护架构记忆,并希望每次 feature plan 都检查架构边界的项目。 - -从本地目录安装: - -```bash -specify preset add --dev .specify/extensions/arch/presets/arch-governance -``` - -如果是在这个仓库源码中测试,可使用源码路径: - -```bash -specify preset add --dev extensions/arch/presets/arch-governance -``` - ## 开发和测试用本地包 这些目录主要服务扩展/预设作者或测试,不建议作为普通项目主流程: @@ -445,11 +409,7 @@ specify bundle build --path ./my-bundle ```text /speckit.constitution -/speckit.arch.scenario-generate -/speckit.arch.logical-generate -/speckit.arch.process-generate -/speckit.arch.development-generate -/speckit.arch.physical-generate +/speckit.arch.generate /speckit.specify /speckit.clarify /speckit.discovery.feasibility @@ -465,11 +425,7 @@ specify bundle build --path ./my-bundle ```text /speckit.constitution /speckit.discovery.codebase -/speckit.arch.scenario-reverse -/speckit.arch.logical-reverse -/speckit.arch.process-reverse -/speckit.arch.development-reverse -/speckit.arch.physical-reverse +/speckit.arch.reverse /speckit.repository-governance.generate /speckit.specify /speckit.plan @@ -543,8 +499,7 @@ specify extension add bug | 目录或文件 | 来源 | 含义 | | --- | --- | --- | -| `.specify/memory/architecture*.md` | `arch` | 4+1 架构视图和综合架构 SSOT。 | -| `.specify/memory/architecture-repo-facts.md` | `arch` reverse 命令 | 从既有仓库提取的架构事实。 | +| `.specify/memory/architecture.md` | `arch` | 面向 `/speckit.plan` 的架构规划契约。 | | `.specify/memory/repository-governance.md` | `repository-governance` | 内部仓库治理 SSOT。 | | `specs//intake/` | `intake` | PRD、视觉设计、测试用例的结构化证据包。 | | `specs//preview/` | `preview` | Markdown wireflow 和自包含 HTML 预览。 | diff --git a/docs/community/extensions.md b/docs/community/extensions.md index 5ef6d67f4c..cc51e4e71f 100644 --- a/docs/community/extensions.md +++ b/docs/community/extensions.md @@ -30,7 +30,7 @@ The following community-contributed extensions are available in [`catalog.commun | API Evolve | Managed API contract evolution — breaking-change detection, semver enforcement, deprecation orchestration, and lifecycle gates across REST, GraphQL, and gRPC | `process` | Read+Write | [spec-kit-api-evolve](https://github.com/Quratulain-bilal/spec-kit-api-evolve) | | Architect Impact Previewer | Predicts architectural impact, complexity, and risks of proposed changes before implementation. | `visibility` | Read-only | [spec-kit-architect-preview](https://github.com/UmmeHabiba1312/spec-kit-architect-preview) | | Architecture Guard | Framework-agnostic architecture review extension for validating implementation against governance and architecture constitutions, detecting architectural drift, and generating non-blocking refactor tasks | `process` | Read+Write | [spec-kit-architecture-guard](https://github.com/DyanGalih/spec-kit-architecture-guard) | -| Architecture Workflow | Generate or reverse project-level 4+1 architecture views with per-view and full-workflow commands | `docs` | Read+Write | [spec-kit-arch](https://github.com/bigsmartben/spec-kit-arch) | +| Architecture Planning Contract | Generate or reverse a planning-focused architecture contract that guides downstream Spec Kit plans | `docs` | Read+Write | [spec-kit-arch](https://github.com/bigsmartben/spec-kit-arch) | | Archive Extension | Archive merged features into main project memory. | `docs` | Read+Write | [spec-kit-archive](https://github.com/stn1slv/spec-kit-archive) | | Azure DevOps Integration | Sync user stories and tasks to Azure DevOps work items using OAuth authentication | `integration` | Read+Write | [spec-kit-azure-devops](https://github.com/pragya247/spec-kit-azure-devops) | | Blueprint | Stay code-literate in AI-driven development: review a complete code blueprint for every task from spec artifacts before /speckit.implement runs | `docs` | Read+Write | [spec-kit-blueprint](https://github.com/chordpli/spec-kit-blueprint) | diff --git a/docs/quickstart.md b/docs/quickstart.md index c6bac96155..ef93733cc6 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -1,6 +1,6 @@ # 快速开始 -这份指南面向本仓库分发版的 Spec Kit。它保留核心 Spec-Driven Development 流程,同时默认带上架构 SSOT、仓库治理、BDD/UIF 行为契约、HTML 预览、实现期 handoff 和最终 code review receipt。 +这份指南面向本仓库分发版的 Spec Kit。它保留核心 Spec-Driven Development 流程,同时默认带上架构规划契约、仓库治理、BDD/UIF 行为契约、HTML 预览、实现期 handoff 和最终 code review receipt。 > [!NOTE] > 自动化脚本同时提供 Bash (`.sh`) 和 PowerShell (`.ps1`) 版本。`specify` CLI 会按系统自动选择,也可以通过 `--script sh|ps` 显式指定。 @@ -14,11 +14,7 @@ ```text /speckit.constitution -/speckit.arch.scenario-generate -/speckit.arch.logical-generate -/speckit.arch.process-generate -/speckit.arch.development-generate -/speckit.arch.physical-generate +/speckit.arch.generate /speckit.repository-governance.generate /speckit.specify /speckit.clarify @@ -33,7 +29,7 @@ `/speckit.clarify` 用来在规划前降低需求歧义;`/speckit.checklist` 在计划形成后生成质量检查清单;`/speckit.analyze` 在实现前检查 spec、plan 和 tasks 的一致性;`/speckit.converge` 在实现后对照 feature artifacts 检查剩余缺口。如果 converge 追加了新任务,继续运行 `/speckit.implement` 并再次 converge,直到功能收敛。 -接手旧仓库时,把五个 `/speckit.arch.*-generate` 换成对应的 `/speckit.arch.*-reverse`,先从仓库事实反向生成架构 SSOT。 +接手旧仓库时,把 `/speckit.arch.generate` 换成 `/speckit.arch.reverse`,先从仓库证据反向生成架构规划契约。 小实验可以安装 `lean` 预设后走轻量路径: @@ -127,41 +123,27 @@ specify integration list 它用于约束 SSOT 读取顺序、目录责任、agent 平台适配和仓库事实证据。 -## 4. 生成 ARCH SSOT +## 4. 生成架构规划契约 新项目或架构正在重塑时: ```text -/speckit.arch.scenario-generate -/speckit.arch.logical-generate -/speckit.arch.process-generate -/speckit.arch.development-generate -/speckit.arch.physical-generate +/speckit.arch.generate ``` 接手已有仓库时: ```text -/speckit.arch.scenario-reverse -/speckit.arch.logical-reverse -/speckit.arch.process-reverse -/speckit.arch.development-reverse -/speckit.arch.physical-reverse +/speckit.arch.reverse ``` 主要产物: ```text .specify/memory/architecture.md -.specify/memory/architecture-scenario-view.md -.specify/memory/architecture-logical-view.md -.specify/memory/architecture-process-view.md -.specify/memory/architecture-development-view.md -.specify/memory/architecture-physical-view.md -.specify/memory/architecture-repo-facts.md # reverse 额外使用 ``` -后续 `/speckit.plan` 会基于这些架构边界、约束、反模式和未解缺口进行规划。 +后续 `/speckit.plan` 会基于这份唯一架构文件中的边界、约束、反模式、开放问题和 review checklist 进行规划。 ## 5. 创建并澄清规格 diff --git a/extensions/arch/CATALOG-SUBMISSION.md b/extensions/arch/CATALOG-SUBMISSION.md index 51538d0ea3..c213500119 100644 --- a/extensions/arch/CATALOG-SUBMISSION.md +++ b/extensions/arch/CATALOG-SUBMISSION.md @@ -1,33 +1,30 @@ # Spec Kit Extension Submission Extension ID: arch -Name: Architecture Workflow -Version: 1.2.2 -Description: Generate or reverse project-level 4+1 architecture views with per-view and full-workflow commands +Name: Architecture Planning Contract +Version: 2.0.0 +Description: Generate or reverse a planning-focused architecture contract that guides downstream Spec Kit plans Author: bigsmartben Repository URL: https://github.com/bigsmartben/spec-kit-arch -Download URL: https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v1.2.2.zip +Download URL: https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v2.0.0.zip Documentation URL: https://github.com/bigsmartben/spec-kit-arch#readme License: MIT Required Spec Kit version: >=0.8.10.dev0 -Commands count: 12 +Commands count: 2 Hooks count: 0 -Tags: architecture, 4plus1, workflow, design +Tags: architecture, planning-contract, workflow, design Key features: -- Provides `.arch` namespaced commands for each 4+1 view: scenario, logical, process, development, and physical. -- Provides `/speckit.arch.full-generate` for one-command forward generation of all 4+1 views and synthesis. -- Provides `/speckit.arch.full-reverse` for one-command reverse generation of repo facts, all 4+1 views, and synthesis. -- Provides separate forward-generation and reverse-generation commands for every view. -- Records reverse workflow evidence in `.specify/memory/architecture-repo-facts.md`. -- Uses optional repository-first evidence in the reverse workflow, with dependency matrix interpretation owned by the development view rather than consumed evenly by every 4+1 view. -- Requires the Development View commands to produce a `Dependency Matrix` section in the development-view artifact. -- Allows teams to update one architecture view at a time while preserving the cross-view synthesis boundary. -- Defines synthesis readiness, repo-facts merge behavior, and source traceability expectations for repeatable command runs. -- Ships a schema-backed artifact contract plus bash and PowerShell readiness validators that emit `ready_gate` and stable blocker codes. -- Restricts writes to documented `.specify/memory/architecture*.md` files, including repo facts for reverse generation. +- Provides `/speckit.arch.generate` for forward generation of `.specify/memory/architecture.md` as a planning contract. +- Provides `/speckit.arch.reverse` for reverse generation from observable repository evidence. +- Keeps `.specify/memory/architecture.md` as the only generated architecture artifact. +- Uses 4+1 only as an internal reasoning lens so default output stays focused on downstream planning constraints. +- Defines plan-facing sections for planning scope rules, capability boundaries, required constraints, existing decisions, extension points, prohibited plan directions, open questions, and a plan review checklist. +- Ships a schema-backed artifact contract plus bash and PowerShell readiness validators that emit `planning_gate`, compatibility `ready_gate`, and stable blocker codes. +- Requires rule-bearing rows to include `Source / Basis`, validates open-question planning status, and blocks implementation-level conclusions from the architecture artifact. +- Restricts writes to `.specify/memory/architecture.md`. Testing performed: -- Local development install with `specify extension add --dev /home/administrator/github/spec-kit-arch`. - Bash setup helper verified with `.specify/extensions/arch/scripts/bash/setup-arch.sh --json`. -- Release ZIP install to verify after publishing `v1.2.2`: `specify extension add arch --from https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v1.2.2.zip`. +- Bash readiness validator verified with `.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json`. +- Repository contract test: `bash tests/repository-first-contract.sh`. diff --git a/extensions/arch/CHANGELOG.md b/extensions/arch/CHANGELOG.md index ecb897fa50..14ee057ed7 100644 --- a/extensions/arch/CHANGELOG.md +++ b/extensions/arch/CHANGELOG.md @@ -2,6 +2,22 @@ ## Unreleased +- Strengthen the planning contract quality gate with required `Source / Basis` support on rule-bearing sections. +- Add open-question planning status validation with `BLOCKS_PLAN` and `CAN_PROCEED_WITH_GUARDRAIL`. +- Block implementation-level conclusions such as source file edits, API schemas, database schemas, task lists, runbooks, and deployment manifests from passing planning readiness. +- Tighten the JSON working-model schema with per-section record contracts. + +## v2.0.0 - 2026-07-06 + +- Change the default extension experience from generated 4+1 artifacts to a planning-focused architecture contract. +- Register only `/speckit.arch.generate` and `/speckit.arch.reverse` as default commands. +- Use 4+1 as an internal reasoning lens for goals, boundaries, runtime collaboration, development constraints, and physical constraints. +- Replace the architecture synthesis template with an `Architecture Planning Contract` template for downstream `/plan` guidance. +- Change setup helpers so default bootstrap creates only `.specify/memory/architecture.md`. +- Remove unregistered legacy 4+1 command templates and secondary architecture artifact templates. +- Change readiness validators to emit `planning_gate` with compatibility `ready_gate`. +- Update schema and repository contract tests for the planning contract workflow. + ## v1.2.2 - 2026-06-25 - Use CLI-compatible command names such as `/speckit.arch.scenario-generate` and `/speckit.arch.scenario-reverse`. diff --git a/extensions/arch/README.md b/extensions/arch/README.md index a5e52d252a..79e056fc5b 100644 --- a/extensions/arch/README.md +++ b/extensions/arch/README.md @@ -1,35 +1,35 @@ -# Spec Kit Architecture Workflow Extension +# Spec Kit Architecture Planning Contract Extension -Add a project-level architecture source of truth to Spec Kit. +Guide downstream Spec Kit plans with explicit architecture constraints. -Spec Kit is very good at turning a feature spec into a plan, tasks, and implementation work. In real projects, though, feature specs often do not carry enough stable architecture context: module boundaries, runtime responsibilities, deployment assumptions, cross-team ownership, and the tradeoffs that should not be rediscovered by every agent run. +Spec Kit turns feature specs into plans, tasks, and implementation work. Those plans need stable architecture context: which boundaries cannot be crossed, which capabilities own which responsibilities, which decisions have already been made, and which architecture gaps must block or shape planning. -This extension fills that gap. It creates architecture memory under `.specify/memory/` so architecture decisions can be reviewed from one explicit SSOT instead of guessed from scattered docs, old code, or one feature request. +This extension records that context in `.specify/memory/architecture.md` as a planning contract. The contract is intentionally plan-facing: it tells `/plan` what it must preserve, what it must not invent, where extension is allowed, and when architecture review is required. -## When You Need This +Each rule-bearing row carries `Source / Basis` so the single artifact remains traceable without a secondary evidence file. -Use this extension when you want the AI agent to preserve architecture intent across Spec Kit workflows: +## When You Need This -- You are starting or reshaping a Spec Kit project and want architecture decisions captured before detailed planning. -- You have an existing repository and need architecture memory derived from observable repo facts. -- You want stable boundaries, constraints, tradeoffs, and unresolved gaps captured before downstream work consumes architecture context. -- You need a safe place for architecture-level reasoning without editing source code, feature specs, tasks, deployment files, or runbooks. +Use this extension when you want downstream planning to respect project-level architecture: -The extension is intentionally about architecture SSOT, not implementation design. It records project-level 4+1 architecture views and a synthesis that downstream work can use as grounding. +- You are starting or reshaping a Spec Kit project and want plan guardrails before detailed planning. +- You have an existing repository and need planning constraints derived from observable repository evidence. +- You want stable boundaries, constraints, prohibited directions, and open architecture questions captured in one place. +- You need architecture guidance without producing implementation plans, task lists, API schemas, database schemas, deployment manifests, or runbooks. ## Install -The extension is listed in the Spec Kit community catalog for discovery. You can find or inspect it from a Spec Kit project: +The extension is listed in the Spec Kit community catalog for discovery: ```bash specify extension search arch specify extension info arch ``` -Community catalog entries may be discovery-only. Install the published release directly from GitHub: +Install the published release directly from GitHub: ```bash -specify extension add arch --from https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v1.2.2.zip +specify extension add arch --from https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v2.0.0.zip ``` Install from a local development checkout: @@ -46,156 +46,78 @@ After installation, the extension is copied under: ## Commands -The extension id is `arch`, and each command uses `.arch` as the command namespace. The extension provides twelve commands: one full forward-generation command, one full reverse-generation command, plus one forward-generation command and one reverse-generation command for each 4+1 architecture view. +The extension id is `arch`, and each command uses `.arch` as the command namespace. The extension provides two default commands: ```text -/speckit.arch.full-generate -/speckit.arch.scenario-generate -/speckit.arch.logical-generate -/speckit.arch.process-generate -/speckit.arch.development-generate -/speckit.arch.physical-generate -/speckit.arch.full-reverse -/speckit.arch.scenario-reverse -/speckit.arch.logical-reverse -/speckit.arch.process-reverse -/speckit.arch.development-reverse -/speckit.arch.physical-reverse +/speckit.arch.generate +/speckit.arch.reverse ``` -Choose the direction based on where architecture knowledge should come from, then choose whether to generate the full 4+1 set or update one view. - -| Direction | Use when | Evidence source | Writes | -| --- | --- | --- | --- | -| `full-generate` | You want one command to generate the complete forward 4+1 architecture set | User input, current architecture memory, optional `.specify/memory/uc.md` | All five architecture views, with synthesis refreshed only when the readiness validator returns `ready_gate: PASS` | -| `full-reverse` | You want one command to reconstruct the complete 4+1 architecture set from an existing repository | Observable repository facts recorded in `.specify/memory/architecture-repo-facts.md` | Repo facts plus all five architecture views, with synthesis refreshed only when the readiness validator returns `ready_gate: PASS` | -| `generate` | You are working from intended product/use-case context or existing architecture memory | User input, current architecture views, optional `.specify/memory/uc.md` for scenario only | The selected architecture view, with synthesis refreshed only when the readiness validator returns `ready_gate: PASS` | -| `reverse` | You are onboarding or documenting an existing repository | Observable repository facts recorded in `.specify/memory/architecture-repo-facts.md` | Repo facts plus the selected architecture view, with synthesis refreshed only when the readiness validator returns `ready_gate: PASS` | - -| View | Forward command | Reverse command | Main artifact | +| Command | Use when | Evidence source | Writes | | --- | --- | --- | --- | -| Scenario | `/speckit.arch.scenario-generate` | `/speckit.arch.scenario-reverse` | `.specify/memory/architecture-scenario-view.md` | -| Logical | `/speckit.arch.logical-generate` | `/speckit.arch.logical-reverse` | `.specify/memory/architecture-logical-view.md` | -| Process | `/speckit.arch.process-generate` | `/speckit.arch.process-reverse` | `.specify/memory/architecture-process-view.md` | -| Development | `/speckit.arch.development-generate` | `/speckit.arch.development-reverse` | `.specify/memory/architecture-development-view.md` | -| Physical | `/speckit.arch.physical-generate` | `/speckit.arch.physical-reverse` | `.specify/memory/architecture-physical-view.md` | +| `/speckit.arch.generate` | You know the intended product direction and want architecture planning guardrails | User input, current architecture memory, optional `.specify/memory/uc.md` | `.specify/memory/architecture.md` | +| `/speckit.arch.reverse` | You are onboarding or documenting an existing repository | Observable repository evidence inspected during the command | `.specify/memory/architecture.md` | -### Forward Generation +## Planning Contract -Run `*.generate` commands when you already know what the project is meant to become, or when Spec Kit use-case context exists and you want to make architecture intent explicit before planning. - -Use the full forward command when you want to populate the complete 4+1 set in dependency order: +The primary artifact is: ```text -/speckit.arch.full-generate +.specify/memory/architecture.md ``` -The full command writes the scenario, logical, process, development, and physical views, then refreshes `.specify/memory/architecture.md` only after all five generated views satisfy the working-model contract and the rendered-artifact readiness validator returns `ready_gate: PASS`. It does not read or update `.specify/memory/architecture-repo-facts.md`. - -Recommended order: - -1. `/speckit.arch.scenario-generate` -2. `/speckit.arch.logical-generate` -3. `/speckit.arch.process-generate` -4. `/speckit.arch.development-generate` -5. `/speckit.arch.physical-generate` - -Use it to answer questions like: +It uses this structure: -- What boundaries should later feature plans preserve? -- Which responsibilities must not be merged by future implementation work? -- Which runtime, development, or deployment constraints are already architecture decisions? -- Which architecture gaps must stay explicit until the team supplies more information? +- Architecture Intent +- Planning Scope Rules +- Capability Boundaries +- Required Constraints +- Architecture Decisions Already Made +- Allowed Extension Points +- Prohibited Plan Directions +- Open Architecture Questions +- Plan Review Checklist -Each per-view forward command populates only its selected view. Its setup bootstrap may create missing placeholder files for the architecture memory set, but the command must not populate non-target views or use `.specify/memory/architecture-repo-facts.md` as input. It may refresh `.specify/memory/architecture.md` only after the readiness validator reports `ready_gate: PASS`. +Rule-bearing sections include `Source / Basis`. Open architecture questions also include a planning status: `BLOCKS_PLAN` or `CAN_PROCEED_WITH_GUARDRAIL`. -`speckit.arch.development-generate` must produce the Development View `Dependency Matrix` section from logical/process architecture relationships and stated constraints. - -Each command also loads `.specify/extensions/arch/schemas/architecture-artifacts.schema.json` as the working-model contract and uses `.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh` or `.specify/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1` as the rendered-artifact readiness gate. Commands own evidence extraction, classification, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own only the Markdown rendering layout. - -### Reverse Generation - -Run `*.reverse` commands when the repository already exists but the architecture SSOT does not. - -Use the full reverse command when you want to populate repo facts and the complete 4+1 set in dependency order: +The contract is usable when the planning readiness validator reports: ```text -/speckit.arch.full-reverse +planning_gate: USABLE +ready_gate: PASS ``` -The full reverse command writes `.specify/memory/architecture-repo-facts.md`, the scenario, logical, process, development, and physical views, then refreshes `.specify/memory/architecture.md` only after all five generated views satisfy the working-model contract and the rendered-artifact readiness validator returns `ready_gate: PASS`. - -Recommended order: - -1. `/speckit.arch.scenario-reverse` -2. `/speckit.arch.logical-reverse` -3. `/speckit.arch.process-reverse` -4. `/speckit.arch.development-reverse` -5. `/speckit.arch.physical-reverse` - -Each reverse command inspects repository evidence first, writes or refreshes `.specify/memory/architecture-repo-facts.md`, then derives the selected 4+1 view from those facts. The repo facts file is cumulative: reverse commands preserve existing non-placeholder facts outside their evidence focus unless cited evidence is removed, contradicted, or superseded, and they record the reason for any replacement or downgrade. A reverse command may refresh `.specify/memory/architecture.md` only after the readiness validator reports `ready_gate: PASS`. - -Reverse commands validate both the repo-facts working model and the target-view working model against the same schema contract before rendering Markdown. - -It is useful for: +If readiness is blocked, the validator emits stable blocker codes such as: -- Bringing a non-Spec Kit repository into Spec Kit. -- Reconstructing architecture intent from README files, tests, entry points, package layout, routes, workers, CI/CD, configuration, and deployment clues. -- Making uncertainty visible when the repository does not prove actors, runtime ownership, deployment topology, or business meaning. +- `ARCH_PLACEHOLDER_PRESENT` +- `ARCH_PLANNING_SCOPE_RULES_MISSING` +- `ARCH_CAPABILITY_BOUNDARIES_MISSING` +- `ARCH_CONSTRAINTS_OR_DECISIONS_MISSING` +- `ARCH_PLAN_REVIEW_CHECKLIST_MISSING` +- `ARCH_SOURCE_MISSING` +- `ARCH_UNSUPPORTED_CONCLUSION` +- `ARCH_OPEN_QUESTION_STATUS_INVALID` -If `.specify/memory/repository-first/` exists, reverse commands also treat those files as evidence inputs within each command's view scope. Dependency matrices are primarily owned by the development view: `speckit.arch.development-generate` and `speckit.arch.development-reverse` must produce the Development View `Dependency Matrix` section, and the reverse command summarizes repository-first matrices into architecture-level development constraints, dependency rules, gaps, and review triggers. Other views must not consume dependency matrices directly or treat them as a separate architecture view; they may use development-view dependency conclusions only when the development view is synthesis-ready and relevant to their target view. +Blocked contracts can still expose useful questions, but downstream plans must not treat missing architecture decisions as permission to invent them. -### Synthesis Refresh +## Internal Reasoning Model -Commands refresh `.specify/memory/architecture.md` only when the readiness validator reports `ready_gate: PASS` for the rendered architecture memory set. The validator reports `ready_gate: BLOCKED` with these runtime blocker codes when any rendered-artifact readiness rule fails: +The commands use 4+1 as an internal reasoning lens, not as the default artifact shape: -- `ARCH_ARTIFACT_MISSING`: a required architecture artifact is missing. -- `ARCH_PLACEHOLDER_PRESENT`: a rendered artifact still contains placeholder update markers. -- `ARCH_REQUIRED_SECTION_MISSING`: a required section id is absent from a rendered artifact. -- `ARCH_REQUIRED_SECTION_EMPTY`: a required section has no supported content. -- `ARCH_TRACEABILITY_MISSING`: a view has no supported Source Traceability records. -- `ARCH_DEPENDENCY_MATRIX_MISSING` or `ARCH_DEPENDENCY_MATRIX_EMPTY`: the Development View dependency matrix is absent or empty. +- Scenario lens: goals, actors, main paths, alternate paths, and failure paths. +- Logical lens: capability boundaries, domain concepts, ownership, state responsibility, and invariants. +- Process lens: runtime collaboration, handoffs, approval points, receipts, and failure closure. +- Development lens: module boundaries, dependency direction, package ownership, and code-organization constraints. +- Physical lens: deployment assumptions, external systems, runtime environment, fact sources, and operational constraints. -Commands may also report command-local blocker codes while classifying candidate conclusions: - -- `ARCH_SOURCE_MISSING`: a conclusion or dependency matrix entry lacks an allowed source. -- `ARCH_USER_INPUT_ONLY`: a reverse-generated conclusion is supported only by user input. -- `ARCH_REPO_FIRST_MATRIX_MISUSED`: repository-first dependency matrices are copied into architecture views, treated as an independent view, or used as direct non-development evidence. -- `ARCH_GIT_HISTORY_ONLY`: Git history is used as the sole support for an architecture conclusion. -- `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING`: a boundary has responsibilities but no explicit non-responsibility. -- `ARCH_UNSUPPORTED_CONCLUSION`: unsupported content is promoted into conclusion tables instead of gaps. - -If any blocker is present, commands leave `.specify/memory/architecture.md` unchanged and report the blocker codes, affected artifacts, and affected sections. +These lenses help prevent omissions, but downstream planning consumes the single planning contract. ## Files Written -The architecture SSOT files are: +Both default commands write only: ```text .specify/memory/architecture.md -.specify/memory/architecture-scenario-view.md -.specify/memory/architecture-logical-view.md -.specify/memory/architecture-process-view.md -.specify/memory/architecture-development-view.md -.specify/memory/architecture-physical-view.md -``` - -Reverse commands also write their evidence layer: - -```text -.specify/memory/architecture-repo-facts.md -``` - -The full forward command populates the five 4+1 view files and may refresh `.specify/memory/architecture.md` after all generated views are synthesis-ready. Per-view forward `*.generate` commands populate only the selected view. Their setup may create placeholder architecture memory files, including an empty `.specify/memory/architecture-repo-facts.md` for reverse workflow compatibility, but generate commands do not use that file as input. - -The full reverse command populates `.specify/memory/architecture-repo-facts.md` plus all five 4+1 view files, and may refresh `.specify/memory/architecture.md` after all generated views are synthesis-ready. Per-view reverse `*.reverse` commands populate `.specify/memory/architecture-repo-facts.md` plus the selected view, preserving unrelated existing repo facts unless evidence has changed and the reason is recorded. - -The extension also ships the artifact contract used by the prompts: - -```text -.specify/extensions/arch/schemas/architecture-artifacts.schema.json -.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh -.specify/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1 ``` The commands do not edit: @@ -210,15 +132,12 @@ source code tests root docs/ deployment manifests +package files +infrastructure files runbooks +other `.specify/memory/architecture*.md` files ``` -## What The Extension Is Not - -This extension does not produce implementation plans, task lists, class designs, API schemas, database schemas, framework choices, deployment manifests, or runbooks. - -It also does not replace feature specs. Feature specs describe what a feature should do. The architecture SSOT records the project-level decisions and constraints that future features should respect. - ## Development Validate the extension from a fresh project: @@ -228,6 +147,11 @@ specify init /tmp/spec-kit-arch-test --ai codex --ignore-agent-tools --script sh cd /tmp/spec-kit-arch-test specify extension add --dev /home/administrator/github/spec-kit-arch .specify/extensions/arch/scripts/bash/setup-arch.sh --json +.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json ``` -The extension intentionally does not provide the legacy `/speckit.arch`, `/speckit.arch.generate`, or `/speckit.arch.reverse` commands. +Run the repository contract test after command, template, schema, setup-script, validator, or documentation changes: + +```bash +bash tests/repository-first-contract.sh +``` diff --git a/extensions/arch/commands/speckit.arch.development-generate.md b/extensions/arch/commands/speckit.arch.development-generate.md deleted file mode 100644 index 4364cd775f..0000000000 --- a/extensions/arch/commands/speckit.arch.development-generate.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -description: Generate the 4+1 development view from logical and process architecture views. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Goal - -Generate or refresh the development view: - -- Target view: `.specify/memory/architecture-development-view.md` -- Primary inputs: `.specify/memory/architecture-logical-view.md`, `.specify/memory/architecture-process-view.md` -- Optional synthesis refresh: `.specify/memory/architecture.md` - -The development view derives architecture-level components, package boundary intent, contract/artifact semantics, dependency rules, and the required dependency matrix from logical and process views. - -## Operating Boundaries - -- Write only `DEVELOPMENT_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not read, populate, or update `REPO_FACTS_FILE`. -- Do not modify logical or process views, source code, specs, plans, tasks, docs, tests, package files, deployment files, or runbooks. -- Stay at architecture-level development structure, not concrete implementation design. -- If prerequisite views are insufficient, record development gaps instead of fabricating components, packages, or contracts. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders and `REPO_FACTS_FILE`. Treat that as bootstrap scaffolding only. After setup, this command must populate only `DEVELOPMENT_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -If setup creates `REPO_FACTS_FILE`, leave it as-is. Do not read it as input and do not add facts to it from this generate command. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -For `DEVELOPMENT_VIEW`, the `Dependency Matrix` section is a required output section with section id `dependency-matrix`. Populate it from source-backed logical/process architecture relationships and stated constraints; when evidence is insufficient for a matrix relation, record the missing relation in `Development View Gaps` instead of omitting the section. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-development-template.md`, and `architecture-template.md`. -3. Extract source-backed logical boundaries, process collaborations, contracts, and invariants. -4. Normalize component, package, contract, and dependency terminology. -5. Derive architecture-level development boundaries, dependency rules, and the required dependency matrix. -6. Classify each candidate as a supported development conclusion or a development gap under the schema and quality gates. -7. Render the schema-compliant development working model with `architecture-development-template.md`. -8. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -9. Report updated paths and explicit development gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the development view contains source file paths, concrete package trees, classes, functions, framework wiring, or implementation tasks. -- BLOCKER `ARCH_DEPENDENCY_MATRIX_MISSING` if the development view omits the required `Dependency Matrix` section. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks logical/process architecture or a stated constraint. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Development View Gaps`. -- BLOCKER `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING` if a boundary has responsibilities but no explicit non-responsibility. -- Record gaps instead of inventing development structure. diff --git a/extensions/arch/commands/speckit.arch.development-reverse.md b/extensions/arch/commands/speckit.arch.development-reverse.md deleted file mode 100644 index d6abc398a5..0000000000 --- a/extensions/arch/commands/speckit.arch.development-reverse.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -description: Reverse-generate the 4+1 development view from observable repository facts. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). In reverse workflows, user input may scope evidence collection or state explicit external constraints, but user input alone must not prove a reverse-generated architecture conclusion. - -## Goal - -Reverse-generate or refresh the development view from observable repository evidence: - -- Evidence layer: `.specify/memory/architecture-repo-facts.md` -- Target view: `.specify/memory/architecture-development-view.md` -- Supporting inputs: logical and process views if available under Supporting View Availability -- Optional synthesis refresh: `.specify/memory/architecture.md` - -The development view must include a `Dependency Matrix` section as a required output of this command. - -## Operating Boundaries - -- Write only `REPO_FACTS_FILE` and `DEVELOPMENT_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not modify logical/process views, source code, README files, docs, package files, configuration, tests, deployment files, specs, plans, tasks, or runbooks. -- Stay at architecture-level development structure, not implementation design. -- If repository evidence is insufficient, record a specific evidence gap and development gap instead of inventing components, packages, contracts, or dependency rules. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders. Treat that as bootstrap scaffolding only. After setup, this command must populate only `REPO_FACTS_FILE` and `DEVELOPMENT_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -## Evidence Sources - -Inspect package directories, module boundaries, imports, manifests, build scripts, configuration ownership, test grouping, examples, and CI structure. - -Repository-First Inputs: if `.specify/memory/repository-first/` exists, inspect its markdown artifacts before deriving the view. Treat dependency matrices as development-owned dependency governance evidence, not as an independent architecture view. Summarize build manifest detection, first-party module edges, allowed/forbidden invocation rules, dependency matrix signals, and governance actions in `REPO_FACTS_FILE`, then project only architecture-level constraints into the required `Dependency Matrix` section and related `DEVELOPMENT_VIEW` dependency rules. Other views may consume only derived development-view constraints, never the matrix itself. Repository-first content must not be copied verbatim into architecture views. - -## Supporting View Availability - -`LOGICAL_VIEW` and `PROCESS_VIEW` are available only when the readiness validator reports no blockers for those views such as missing artifact, placeholder marker, required-section, or traceability failures. Placeholder content and view gaps may identify missing context but must not support new development conclusions. - -## Repo Facts Merge Rule - -Treat `REPO_FACTS_FILE` as a cumulative evidence layer. Preserve existing non-placeholder facts from sections outside this command's evidence focus unless the cited evidence no longer exists or is contradicted by stronger evidence. When replacing, removing, or downgrading an existing fact, record the reason in `Evidence Gaps` or a review trigger instead of silently dropping it. - -## Repo Facts Evidence Rules - -- Every non-placeholder fact must name an evidence source such as a file, directory, configuration, test, script, manifest, command output, or commit signal. -- Confidence values are `High`, `Medium`, or `Low`: `High` means multiple independent sources agree; `Medium` means one strong source is present; `Low` means naming, directory structure, isolated code, or Git history suggests a fact but lacks behavior evidence. -- Git history is an auxiliary signal for change axes and boundary risks. It cannot independently prove architecture conclusions. -- Repository-first outputs are fact inputs for development governance. Summarize only architecture constraints, dependency rules, governance signals, gaps, or review triggers; do not copy full dependency inventories into architecture views. -- Concrete classes, functions, fields, endpoints, database tables, and implementation data structures may appear only as evidence sources, not architecture conclusions. -- Architecture conclusions must trace to repo facts, available supporting-view conclusions, or stated external constraints. If a conclusion is supported only by user input, report blocker code `ARCH_USER_INPUT_ONLY` and place it in `Evidence Gaps` or the target view gaps instead of conclusion tables. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -For `DEVELOPMENT_VIEW`, the `Dependency Matrix` section is a required output section with section id `dependency-matrix`. Populate it from source-backed repository facts, repository-first dependency matrix signals, available logical/process architecture relationships, and stated constraints; when evidence is insufficient for a matrix relation, record the missing relation in `Evidence Gaps` or `Development View Gaps` instead of omitting the section. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `REPO_FACTS_FILE`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-repo-facts-template.md`, `architecture-development-template.md`, and `architecture-template.md`. -3. Refresh repo facts for this command's evidence focus and classify unsupported observations as evidence gaps. -4. Populate a schema-compliant development working model from eligible repo facts plus `LOGICAL_VIEW` and `PROCESS_VIEW` when they satisfy Supporting View Availability. -5. Populate the required `Dependency Matrix` section and summarize repository-first dependency matrices only as development-view architecture constraints, dependency rules, gaps, or review triggers. -6. Apply the repo facts merge rule before writing `REPO_FACTS_FILE`. -7. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -8. Report updated paths and explicit unresolved gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the development view promotes concrete source paths, package trees, classes, functions, framework wiring, or implementation tasks into architecture conclusions. -- BLOCKER `ARCH_DEPENDENCY_MATRIX_MISSING` if the development view omits the required `Dependency Matrix` section. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a repo fact, available `LOGICAL_VIEW` or `PROCESS_VIEW` source, or stated constraint. -- BLOCKER `ARCH_REPO_FIRST_MATRIX_MISUSED` if repository-first dependency matrices are copied into architecture views, treated as an independent architecture view, or used as direct non-development evidence. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Evidence Gaps` or `Development View Gaps`. -- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used alone as a development conclusion. -- BLOCKER `ARCH_SOURCE_MISSING` if development ownership or dependency governance cannot be supported by repository evidence; record the unsupported item in evidence gaps and target-view gaps. diff --git a/extensions/arch/commands/speckit.arch.full-generate.md b/extensions/arch/commands/speckit.arch.full-generate.md deleted file mode 100644 index 4b9b657660..0000000000 --- a/extensions/arch/commands/speckit.arch.full-generate.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -description: Generate all 4+1 architecture views and the architecture synthesis from intended project context. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Goal - -Generate or refresh the complete forward 4+1 architecture set: - -- Scenario view: `.specify/memory/architecture-scenario-view.md` -- Logical view: `.specify/memory/architecture-logical-view.md` -- Process view: `.specify/memory/architecture-process-view.md` -- Development view: `.specify/memory/architecture-development-view.md` -- Physical view: `.specify/memory/architecture-physical-view.md` -- Synthesis: `.specify/memory/architecture.md` - -This command is the full forward-generation workflow. It derives the `+1` scenario view first, then derives the four supporting views in dependency order, and refreshes the synthesis only from validated view content. - -## Operating Boundaries - -- Write only `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, and `ARCH_FILE`. -- Do not read, populate, or update `REPO_FACTS_FILE`. -- Read `.specify/memory/uc.md` only as optional scenario background. -- Do not modify `.specify/memory/uc.md`, `.specify/memory/constitution.md`, feature specs, plans, tasks, source code, tests, root `docs/`, deployment manifests, package files, infrastructure files, or runbooks. -- Stay at abstract architecture-design level across all views. -- If context is insufficient for any view, record a specific gap in that view instead of inventing architecture facts. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including `REPO_FACTS_FILE`. Treat that as bootstrap scaffolding only. After setup, this command must populate only the five architecture views and `ARCH_FILE`. - -If setup creates `REPO_FACTS_FILE`, leave it as-is. Do not read it as input and do not add facts to it from this generate command. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -For `DEVELOPMENT_VIEW`, the `Dependency Matrix` section is a required output section. Populate it from source-backed logical/process architecture relationships and stated constraints; when evidence is insufficient for a matrix relation, record the missing relation in `Development View Gaps` instead of omitting the section. - -## Generation Order - -Generate and validate views in this order: - -1. `SCENARIO_VIEW` from user input, optional `.specify/memory/uc.md`, and existing memory context. -2. `LOGICAL_VIEW` from validated scenario architecture semantics. -3. `PROCESS_VIEW` from validated scenario paths and logical boundaries. -4. `DEVELOPMENT_VIEW` from validated logical/process architecture relationships. -5. `PHYSICAL_VIEW` from validated process/development architecture constraints. -6. `ARCH_FILE` from the five validated views, only after synthesis readiness passes. - -Each later view may use earlier views generated in the same command after their working models pass the schema and quality gates. Do not use a placeholder or gap-only view as proof for downstream architecture conclusions. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `ARCH_FILE`, all five view files, `ARCH_SCHEMA_FILE`, all six architecture templates, and `.specify/memory/uc.md` if present. -3. Generate the scenario working model from source-backed user, use-case, and memory context. -4. Generate logical, process, development, and physical working models in dependency order, using only validated upstream architecture conclusions and stated constraints. -5. Populate the required development `Dependency Matrix` section from validated logical/process relationships and stated constraints. -6. Classify every candidate conclusion as supported architecture content or a view-specific gap under the schema and quality gates. -7. Render the five schema-compliant view working models with their corresponding templates. -8. Run the readiness validator. If it returns `ready_gate: PASS`, render `ARCH_FILE` with `architecture-template.md`; otherwise leave synthesis untouched and report validator blocker codes. -9. Report updated paths and explicit gaps by view. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if any generated view contains concrete implementation design, source paths, classes, functions, endpoints, database fields, deployment manifests, infrastructure configuration, scripts, runbooks, plans, tasks, or test strategy. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks user input, optional use-case context, validated upstream architecture, existing memory context, or a stated constraint. -- BLOCKER `ARCH_DEPENDENCY_MATRIX_MISSING` if the development view omits the required `Dependency Matrix` section. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks logical/process architecture or a stated constraint. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported conclusions appear in conclusion tables; place them only in the corresponding view gaps. -- BLOCKER `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING` if a boundary has responsibilities but no explicit non-responsibility. -- Record gaps instead of inventing business facts, authority boundaries, runtime behavior, development structure, topology, or operational constraints. diff --git a/extensions/arch/commands/speckit.arch.full-reverse.md b/extensions/arch/commands/speckit.arch.full-reverse.md deleted file mode 100644 index 4341ee8f7a..0000000000 --- a/extensions/arch/commands/speckit.arch.full-reverse.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -description: Reverse-generate all 4+1 architecture views and the architecture synthesis from observable repository facts. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). In reverse workflows, user input may scope evidence collection or state explicit external constraints, but user input alone must not prove a reverse-generated architecture conclusion. - -## Goal - -Reverse-generate or refresh the complete 4+1 architecture set from observable repository evidence: - -- Evidence layer: `.specify/memory/architecture-repo-facts.md` -- Scenario view: `.specify/memory/architecture-scenario-view.md` -- Logical view: `.specify/memory/architecture-logical-view.md` -- Process view: `.specify/memory/architecture-process-view.md` -- Development view: `.specify/memory/architecture-development-view.md` -- Physical view: `.specify/memory/architecture-physical-view.md` -- Synthesis: `.specify/memory/architecture.md` - -This command is the full reverse-generation workflow. It records repository facts first, derives the `+1` scenario view and four supporting views from those facts, then refreshes synthesis only from validated view content. - -## Operating Boundaries - -- Write only `REPO_FACTS_FILE`, `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, and `ARCH_FILE`. -- Do not modify source code, README files, project documentation, package files, configuration, tests, deployment files, `.specify/memory/uc.md`, `.specify/memory/constitution.md`, feature specs, plans, tasks, root `docs/`, deployment manifests, infrastructure files, or runbooks. -- Stay at abstract architecture-design level across all views. -- If repository evidence is insufficient for any view, record a specific evidence gap and view gap instead of inventing architecture facts. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates. Treat that as bootstrap scaffolding only. After setup, this command must populate only `REPO_FACTS_FILE`, the five architecture views, and `ARCH_FILE`. - -## Evidence Sources - -Inspect README/docs, CLI/API entry points, examples, tests, route declarations, package directories, module boundaries, imports, manifests, build scripts, configuration ownership, CI structure, deployment clues, and user-visible behavior descriptions. Prefer concise inventory over exhaustive source listing. - -Repository-First Inputs: if `.specify/memory/repository-first/` exists, inspect its markdown artifacts before deriving the views. Dependency matrices are owned by the development view: summarize build manifest detection, first-party module edges, allowed/forbidden invocation rules, dependency matrix signals, and governance actions in `REPO_FACTS_FILE`, then project only architecture-level dependency constraints into the required development `Dependency Matrix` section and related development-view rules. A dependency matrix is evidence for development governance, not an independent architecture view or equal input to every 4+1 view. Repository-first content must not be copied verbatim into architecture views. - -## Repo Facts Merge Rule - -Treat `REPO_FACTS_FILE` as a cumulative evidence layer. Preserve existing non-placeholder facts unless the cited evidence no longer exists or is contradicted by stronger evidence. When replacing, removing, or downgrading an existing fact, record the reason in `Evidence Gaps` or a review trigger instead of silently dropping it. - -## Repo Facts Evidence Rules - -- Every non-placeholder fact must name an evidence source such as a file, directory, configuration, test, script, manifest, command output, or commit signal. -- Confidence values are `High`, `Medium`, or `Low`: `High` means multiple independent sources agree; `Medium` means one strong source is present; `Low` means naming, directory structure, isolated code, or Git history suggests a fact but lacks behavior evidence. -- Git history is an auxiliary signal for change axes and boundary risks. It cannot independently prove architecture conclusions. -- Repository-first outputs are fact inputs only when summarized into architecture constraints, dependency rules, governance signals, gaps, or review triggers; do not copy full dependency inventories into architecture views. -- Concrete classes, functions, fields, endpoints, database tables, and implementation data structures may appear only as evidence sources, not architecture conclusions. -- Architecture conclusions must trace to repo facts or stated external constraints. If a conclusion is supported only by user input, report blocker code `ARCH_USER_INPUT_ONLY` and place it in `Evidence Gaps` or the target view gaps instead of conclusion tables. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -For `DEVELOPMENT_VIEW`, the `Dependency Matrix` section is a required output section with section id `dependency-matrix`. Populate it from source-backed repository facts, repository-first dependency matrix signals, available logical/process architecture relationships generated in this command, and stated constraints; when evidence is insufficient for a matrix relation, record the missing relation in `Evidence Gaps` or `Development View Gaps` instead of omitting the section. - -## Reverse Generation Order - -Generate and validate artifacts in this order: - -1. `REPO_FACTS_FILE` from observable repository evidence and optional repository-first evidence. -2. `SCENARIO_VIEW` from high- or medium-confidence facts about user-visible behavior, actors, goals, paths, and acceptance semantics. -3. `LOGICAL_VIEW` from repo facts plus validated scenario architecture semantics. -4. `PROCESS_VIEW` from repo facts plus validated scenario paths and logical boundaries. -5. `DEVELOPMENT_VIEW` from repo facts plus validated logical/process architecture relationships, including the required `Dependency Matrix` section. -6. `PHYSICAL_VIEW` from repo facts plus validated process/development architecture constraints. -7. `ARCH_FILE` from the five validated views, only after synthesis readiness passes. - -Each later view may use earlier views generated in the same command after their working models pass the schema and quality gates. Do not use a placeholder or gap-only view as proof for downstream architecture conclusions. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `REPO_FACTS_FILE`, `ARCH_FILE`, all five view files, `ARCH_SCHEMA_FILE`, all seven architecture templates, and optional `.specify/memory/repository-first/` markdown artifacts. -3. Refresh repo facts across scenario, logical, process, development, and physical evidence focuses; classify unsupported observations as evidence gaps. -4. Generate scenario, logical, process, development, and physical working models in reverse-generation order, using only eligible repo facts, validated upstream architecture conclusions, and stated constraints. -5. Populate the required development `Dependency Matrix` section and summarize repository-first dependency matrices only as development-view architecture constraints, dependency rules, gaps, or review triggers. -6. Apply the repo facts merge rule before writing `REPO_FACTS_FILE`. -7. Classify every candidate conclusion as supported architecture content or a view-specific gap under the schema and quality gates. -8. Render the repo facts file and five schema-compliant view working models with their corresponding templates. -9. Run the readiness validator. If it returns `ready_gate: PASS`, render `ARCH_FILE` with `architecture-template.md`; otherwise leave synthesis untouched and report validator blocker codes. -10. Report updated paths and explicit unresolved gaps by evidence focus and view. - -## Quality Gates - -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a repo fact source or stated external constraint source. -- BLOCKER `ARCH_SOURCE_MISSING` if the repo facts file contains generic claims without file paths, directories, configuration, tests, commands, or commit signals. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if any generated view promotes concrete source paths, package trees, classes, functions, fields, endpoints, database structure, framework wiring, deployment manifests, infrastructure configuration, scripts, runbooks, plans, tasks, or test strategy into architecture conclusions. -- BLOCKER `ARCH_DEPENDENCY_MATRIX_MISSING` if the development view omits the required `Dependency Matrix` section. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a repo fact, generated `LOGICAL_VIEW` or `PROCESS_VIEW` source, repository-first dependency matrix signal, or stated constraint. -- BLOCKER `ARCH_REPO_FIRST_MATRIX_MISUSED` if repository-first dependency matrices are copied into architecture views, treated as an independent architecture view, or used as direct non-development evidence. -- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used alone as an architecture conclusion. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported conclusions appear in conclusion tables; place them only in `Evidence Gaps` or the corresponding view gaps. -- Record gaps instead of inventing actors, business meaning, authority boundaries, runtime behavior, development structure, topology, or operational constraints. diff --git a/extensions/arch/commands/speckit.arch.generate.md b/extensions/arch/commands/speckit.arch.generate.md new file mode 100644 index 0000000000..00ab05e569 --- /dev/null +++ b/extensions/arch/commands/speckit.arch.generate.md @@ -0,0 +1,68 @@ +--- +description: Generate an architecture planning contract for downstream Spec Kit planning. +scripts: + sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json + ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json +--- + +## User Input + +```text +$ARGUMENTS +``` + +You **MUST** consider the user input before proceeding when it is not empty. + +## Goal + +Generate or refresh the planning-facing architecture contract: + +- Target artifact: `.specify/memory/architecture.md` +- Optional input: `.specify/memory/uc.md` +- Optional existing memory: current `.specify/memory/architecture.md` + +This command uses 4+1 as an internal reasoning lens only. Do not create, update, or require separate 4+1 view files. + +## Operating Boundaries + +- Write only `ARCH_FILE`. +- Read `.specify/memory/uc.md` only as optional product/use-case background. +- Do not modify `.specify/memory/uc.md`, `.specify/memory/constitution.md`, feature specs, plans, tasks, source code, tests, root `docs/`, deployment manifests, package files, infrastructure files, or runbooks. +- Stay at architecture planning-contract level. Record implementation design pressure as plan guardrails, prohibited directions, extension points, or open architecture questions. + +## Internal 4+1 Reasoning Lens + +Use these lenses to prevent omissions, but render only the planning contract: + +- Scenario lens: identify goals, actors, main paths, alternate paths, and failure paths that a downstream plan must preserve. +- Logical lens: identify capability boundaries, domain concepts, ownership, state responsibility, and invariants. +- Process lens: identify runtime collaboration, handoffs, approval points, receipts, and failure closure. +- Development lens: identify module boundaries, dependency direction, package ownership, and code-organization constraints. +- Physical lens: identify deployment assumptions, external systems, runtime environment, fact sources, and operational constraints. + +## Structured Contract + +`ARCH_SCHEMA_FILE` is the authoritative working-model contract for the planning contract. Shape a JSON-compatible working model before rendering Markdown with `architecture-template.md`. + +`ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable planning readiness gate. After rendering candidate changes, run the validator and report `planning_gate`, `ready_gate`, blocker codes, affected artifacts, and affected sections. + +Every plan-facing rule row must include `Source / Basis`. Use user input, `.specify/memory/uc.md`, existing architecture memory, or an explicitly stated architecture assumption as the basis. If the basis is missing, record the gap in `Open Architecture Questions` instead of turning it into a rule. + +## Outline + +1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. +2. Load `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `architecture-template.md`, and `.specify/memory/uc.md` if present. +3. Use the internal 4+1 reasoning lens to identify plan-facing architecture rules. +4. Render `ARCH_FILE` with the required planning contract sections. +5. Run the readiness validator. Report `planning_gate`, `ready_gate`, blockers, updated paths, and open architecture questions. + +## Quality Gates + +- BLOCKER `ARCH_PLANNING_SCOPE_RULES_MISSING` if the contract has no supported Planning Scope Rules. +- BLOCKER `ARCH_CAPABILITY_BOUNDARIES_MISSING` if the contract has no supported Capability Boundaries. +- BLOCKER `ARCH_CONSTRAINTS_OR_DECISIONS_MISSING` if both Required Constraints and Architecture Decisions Already Made are empty. +- BLOCKER `ARCH_PLAN_REVIEW_CHECKLIST_MISSING` if the contract has no supported Plan Review Checklist. +- BLOCKER `ARCH_SOURCE_MISSING` if a rule-bearing row has no supported `Source / Basis`. +- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the contract contains implementation tasks, source file edits, class designs, API schemas, database schemas, deployment manifests, runbooks, test strategy, or downstream-owned requirement IDs. +- BLOCKER `ARCH_OPEN_QUESTION_STATUS_INVALID` if an open architecture question does not use `BLOCKS_PLAN` or `CAN_PROCEED_WITH_GUARDRAIL`. +- Record missing architecture evidence in `Open Architecture Questions` instead of inventing planning rules. diff --git a/extensions/arch/commands/speckit.arch.logical-generate.md b/extensions/arch/commands/speckit.arch.logical-generate.md deleted file mode 100644 index 35c1d14c9e..0000000000 --- a/extensions/arch/commands/speckit.arch.logical-generate.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -description: Generate the 4+1 logical view from scenario architecture semantics. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Goal - -Generate or refresh the logical view: - -- Target view: `.specify/memory/architecture-logical-view.md` -- Primary input: `.specify/memory/architecture-scenario-view.md` -- Optional synthesis refresh: `.specify/memory/architecture.md` - -The logical view derives capability boundaries, domain objects, states, relationships, and invariants from scenario semantics. - -## Operating Boundaries - -- Write only `LOGICAL_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not read, populate, or update `REPO_FACTS_FILE`. -- Do not modify scenario view, source code, specs, plans, tasks, docs, tests, deployment files, or runbooks. -- Stay at abstract logical architecture level. -- If the scenario view is placeholder, stale, or insufficient, record logical gaps instead of fabricating capabilities or domain objects. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders and `REPO_FACTS_FILE`. Treat that as bootstrap scaffolding only. After setup, this command must populate only `LOGICAL_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -If setup creates `REPO_FACTS_FILE`, leave it as-is. Do not read it as input and do not add facts to it from this generate command. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `SCENARIO_VIEW`, `LOGICAL_VIEW`, `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `architecture-logical-template.md`, and `architecture-template.md`. -3. Extract source-backed scenario conclusions and scenario terminology. -4. Normalize capability, object, state, and boundary names. -5. Derive logical authority boundaries, domain relationships, and lifecycle constraints. -6. Classify each candidate as a supported logical conclusion or a logical gap under the schema and quality gates. -7. Render the schema-compliant logical working model with `architecture-logical-template.md`. -8. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -9. Report updated paths and explicit logical gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the logical view introduces classes, DTOs, database tables, fields, endpoints, schemas, or implementation data structures. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a scenario, boundary, lifecycle constraint, or stated user constraint. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Logical Gaps`. -- BLOCKER `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING` if a boundary has responsibilities but no explicit non-responsibility. -- Record gaps instead of inventing authority, lifecycle, or object facts. diff --git a/extensions/arch/commands/speckit.arch.logical-reverse.md b/extensions/arch/commands/speckit.arch.logical-reverse.md deleted file mode 100644 index 978b1c9132..0000000000 --- a/extensions/arch/commands/speckit.arch.logical-reverse.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -description: Reverse-generate the 4+1 logical view from observable repository facts. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). In reverse workflows, user input may scope evidence collection or state explicit external constraints, but user input alone must not prove a reverse-generated architecture conclusion. - -## Goal - -Reverse-generate or refresh the logical view from observable repository evidence: - -- Evidence layer: `.specify/memory/architecture-repo-facts.md` -- Target view: `.specify/memory/architecture-logical-view.md` -- Supporting input: `.specify/memory/architecture-scenario-view.md` if available under Supporting View Availability -- Optional synthesis refresh: `.specify/memory/architecture.md` - -## Operating Boundaries - -- Write only `REPO_FACTS_FILE` and `LOGICAL_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not modify scenario view, source code, README files, docs, package files, configuration, tests, deployment files, specs, plans, tasks, or runbooks. -- Stay at abstract logical architecture level. -- If repository evidence is insufficient, record a specific evidence gap and logical gap instead of inventing capabilities, objects, states, or invariants. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders. Treat that as bootstrap scaffolding only. After setup, this command must populate only `REPO_FACTS_FILE` and `LOGICAL_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -## Evidence Sources - -Inspect README/docs, entry points, tests, examples, route declarations, state clues, persistence clues, domain naming, and configuration ownership. - -Repository-First Inputs: if `.specify/memory/repository-first/` exists, inspect only non-matrix markdown evidence that affects logical boundaries, such as domain naming, source-backed module roles, or stated invocation constraints, and summarize those signals in `REPO_FACTS_FILE`. Dependency matrices are owned by the development view; this command must not consume dependency matrices directly or treat them as a separate architecture view. Repository-first content must not be copied verbatim into architecture views. - -## Supporting View Availability - -`SCENARIO_VIEW` is available only when the readiness validator reports no blockers for `SCENARIO_VIEW` such as missing artifact, placeholder marker, required-section, or traceability failures. Placeholder content and scenario gaps may identify missing context but must not support new logical conclusions. - -## Repo Facts Merge Rule - -Treat `REPO_FACTS_FILE` as a cumulative evidence layer. Preserve existing non-placeholder facts from sections outside this command's evidence focus unless the cited evidence no longer exists or is contradicted by stronger evidence. When replacing, removing, or downgrading an existing fact, record the reason in `Evidence Gaps` or a review trigger instead of silently dropping it. - -## Repo Facts Evidence Rules - -- Every non-placeholder fact must name an evidence source such as a file, directory, configuration, test, script, manifest, command output, or commit signal. -- Confidence values are `High`, `Medium`, or `Low`: `High` means multiple independent sources agree; `Medium` means one strong source is present; `Low` means naming, directory structure, isolated code, or Git history suggests a fact but lacks behavior evidence. -- Git history is an auxiliary signal for change axes and boundary risks. It cannot independently prove architecture conclusions. -- Repository-first outputs are fact inputs only when they match this command's logical evidence focus. Do not consume repository-first dependency matrices directly; use development-view dependency conclusions only after `DEVELOPMENT_VIEW` is synthesis-ready and relevant to logical boundaries. -- Concrete classes, functions, fields, endpoints, database tables, and implementation data structures may appear only as evidence sources, not architecture conclusions. -- Architecture conclusions must trace to repo facts, available supporting-view conclusions, or stated external constraints. If a conclusion is supported only by user input, report blocker code `ARCH_USER_INPUT_ONLY` and place it in `Evidence Gaps` or the target view gaps instead of conclusion tables. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `REPO_FACTS_FILE`, `SCENARIO_VIEW`, `LOGICAL_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-repo-facts-template.md`, `architecture-logical-template.md`, and `architecture-template.md`. -3. Refresh repo facts for this command's evidence focus and classify unsupported observations as evidence gaps. -4. Populate a schema-compliant logical working model from eligible repo facts and `SCENARIO_VIEW` when it satisfies Supporting View Availability. -5. Put low-confidence facts in gaps rather than promoting them into architecture conclusions. -6. Apply the repo facts merge rule before writing `REPO_FACTS_FILE`. -7. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -8. Report updated paths and explicit unresolved gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the logical view promotes classes, functions, fields, endpoints, database structures, or implementation data structures into architecture conclusions. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a repo fact, available `SCENARIO_VIEW` source, or stated constraint. -- BLOCKER `ARCH_REPO_FIRST_MATRIX_MISUSED` if repository-first dependency matrices are copied into architecture views, treated as an independent architecture view, or used as direct non-development evidence. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Evidence Gaps` or `Logical Gaps`. -- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used alone as a logical conclusion. -- BLOCKER `ARCH_SOURCE_MISSING` if authority boundaries or domain lifecycle cannot be supported by repository evidence; record the unsupported item in evidence gaps and target-view gaps. diff --git a/extensions/arch/commands/speckit.arch.physical-generate.md b/extensions/arch/commands/speckit.arch.physical-generate.md deleted file mode 100644 index e7716237a9..0000000000 --- a/extensions/arch/commands/speckit.arch.physical-generate.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -description: Generate the 4+1 physical view from process and development architecture views. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Goal - -Generate or refresh the physical view: - -- Target view: `.specify/memory/architecture-physical-view.md` -- Primary inputs: `.specify/memory/architecture-process-view.md`, `.specify/memory/architecture-development-view.md` -- Optional synthesis refresh: `.specify/memory/architecture.md` - -The physical view derives deployment, hosting, external system, fact-source, observability, and operational boundaries from process and development architecture. - -## Operating Boundaries - -- Write only `PHYSICAL_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not read, populate, or update `REPO_FACTS_FILE`. -- Do not modify process or development views, source code, specs, plans, tasks, docs, tests, deployment manifests, infrastructure files, or runbooks. -- Stay at abstract physical architecture level. -- If prerequisite views are insufficient, record physical gaps instead of fabricating deployment units, external systems, or operational constraints. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders and `REPO_FACTS_FILE`. Treat that as bootstrap scaffolding only. After setup, this command must populate only `PHYSICAL_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -If setup creates `REPO_FACTS_FILE`, leave it as-is. Do not read it as input and do not add facts to it from this generate command. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-physical-template.md`, and `architecture-template.md`. -3. Extract source-backed process collaborations, development boundaries, release constraints, and operational constraints. -4. Normalize deployment, external-system, fact-source, observability, and operations terminology. -5. Derive physical architecture boundaries and ownership constraints. -6. Classify each candidate as a supported physical conclusion or a physical gap under the schema and quality gates. -7. Render the schema-compliant physical working model with `architecture-physical-template.md`. -8. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -9. Report updated paths and explicit physical gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the physical view contains Kubernetes YAML, cloud resource manifests, machine sizes, service SKUs, deployment scripts, runbooks, or concrete infrastructure configuration. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, or a stated constraint. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Physical View Gaps`. -- BLOCKER `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING` if a boundary has responsibilities but no explicit non-responsibility. -- Record gaps instead of inventing topology or operations facts. diff --git a/extensions/arch/commands/speckit.arch.physical-reverse.md b/extensions/arch/commands/speckit.arch.physical-reverse.md deleted file mode 100644 index 62e70e2190..0000000000 --- a/extensions/arch/commands/speckit.arch.physical-reverse.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -description: Reverse-generate the 4+1 physical view from observable repository facts. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). In reverse workflows, user input may scope evidence collection or state explicit external constraints, but user input alone must not prove a reverse-generated architecture conclusion. - -## Goal - -Reverse-generate or refresh the physical view from observable repository evidence: - -- Evidence layer: `.specify/memory/architecture-repo-facts.md` -- Target view: `.specify/memory/architecture-physical-view.md` -- Supporting inputs: process and development views if available under Supporting View Availability -- Optional synthesis refresh: `.specify/memory/architecture.md` - -## Operating Boundaries - -- Write only `REPO_FACTS_FILE` and `PHYSICAL_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not modify process/development views, source code, README files, docs, package files, configuration, tests, deployment files, specs, plans, tasks, infrastructure files, or runbooks. -- Stay at abstract physical architecture level. -- If repository evidence is insufficient, record a specific evidence gap and physical gap instead of inventing deployment units, external systems, fact sources, or operational constraints. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders. Treat that as bootstrap scaffolding only. After setup, this command must populate only `REPO_FACTS_FILE` and `PHYSICAL_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -## Evidence Sources - -Inspect Dockerfiles, Compose files, Kubernetes manifests, Terraform, CI/CD, environment examples, service configuration, deployment documentation, scripts, and observable external-system configuration. - -Repository-First Inputs: if `.specify/memory/repository-first/` exists, inspect only non-matrix markdown evidence that affects deployment or external boundaries, such as observable deployment entry points, external-system configuration, or runtime ownership signals, and summarize those signals in `REPO_FACTS_FILE`. Dependency matrices are owned by the development view; this command must not consume dependency matrices directly or treat them as a separate architecture view. Repository-first content must not be copied verbatim into architecture views. - -## Supporting View Availability - -`PROCESS_VIEW` and `DEVELOPMENT_VIEW` are available only when the readiness validator reports no blockers for those views such as missing artifact, placeholder marker, required-section, or traceability failures. Placeholder content and view gaps may identify missing context but must not support new physical conclusions. - -## Repo Facts Merge Rule - -Treat `REPO_FACTS_FILE` as a cumulative evidence layer. Preserve existing non-placeholder facts from sections outside this command's evidence focus unless the cited evidence no longer exists or is contradicted by stronger evidence. When replacing, removing, or downgrading an existing fact, record the reason in `Evidence Gaps` or a review trigger instead of silently dropping it. - -## Repo Facts Evidence Rules - -- Every non-placeholder fact must name an evidence source such as a file, directory, configuration, test, script, manifest, command output, or commit signal. -- Confidence values are `High`, `Medium`, or `Low`: `High` means multiple independent sources agree; `Medium` means one strong source is present; `Low` means naming, directory structure, isolated code, or Git history suggests a fact but lacks behavior evidence. -- Git history is an auxiliary signal for change axes and boundary risks. It cannot independently prove architecture conclusions. -- Repository-first outputs are fact inputs only when they match this command's physical evidence focus. Do not consume repository-first dependency matrices directly; use development-view dependency conclusions only after `DEVELOPMENT_VIEW` is synthesis-ready and relevant to deployment or external boundaries. -- Concrete classes, functions, fields, endpoints, database tables, and implementation data structures may appear only as evidence sources, not architecture conclusions. -- Architecture conclusions must trace to repo facts, available supporting-view conclusions, or stated external constraints. If a conclusion is supported only by user input, report blocker code `ARCH_USER_INPUT_ONLY` and place it in `Evidence Gaps` or the target view gaps instead of conclusion tables. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `REPO_FACTS_FILE`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-repo-facts-template.md`, `architecture-physical-template.md`, and `architecture-template.md`. -3. Refresh repo facts for this command's evidence focus and classify unsupported observations as evidence gaps. -4. Populate a schema-compliant physical working model from eligible repo facts plus `PROCESS_VIEW` and `DEVELOPMENT_VIEW` when they satisfy Supporting View Availability. -5. Put low-confidence facts in gaps rather than promoting them into physical conclusions. -6. Apply the repo facts merge rule before writing `REPO_FACTS_FILE`. -7. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -8. Report updated paths and explicit unresolved gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the physical view promotes Kubernetes YAML, cloud resource manifests, machine sizes, service SKUs, deployment scripts, runbooks, or concrete infrastructure configuration into architecture conclusions. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks repo facts, available `PROCESS_VIEW`, available `DEVELOPMENT_VIEW`, or stated constraints. -- BLOCKER `ARCH_REPO_FIRST_MATRIX_MISUSED` if repository-first dependency matrices are copied into architecture views, treated as an independent architecture view, or used as direct non-development evidence. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Evidence Gaps` or `Physical View Gaps`. -- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used alone as a physical conclusion. -- BLOCKER `ARCH_SOURCE_MISSING` if deployment topology, external ownership, or operations cannot be supported by repository evidence; record the unsupported item in evidence gaps and target-view gaps. diff --git a/extensions/arch/commands/speckit.arch.process-generate.md b/extensions/arch/commands/speckit.arch.process-generate.md deleted file mode 100644 index 7a4472a35c..0000000000 --- a/extensions/arch/commands/speckit.arch.process-generate.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -description: Generate the 4+1 process view from scenario and logical architecture views. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Goal - -Generate or refresh the process view: - -- Target view: `.specify/memory/architecture-process-view.md` -- Primary inputs: `.specify/memory/architecture-scenario-view.md`, `.specify/memory/architecture-logical-view.md` -- Optional synthesis refresh: `.specify/memory/architecture.md` - -The process view derives runtime collaboration, handoffs, approvals, receipts, state advancement, and failure closure from scenario paths and logical boundaries. - -## Operating Boundaries - -- Write only `PROCESS_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not read, populate, or update `REPO_FACTS_FILE`. -- Do not modify scenario or logical views, source code, specs, plans, tasks, docs, tests, deployment files, or runbooks. -- Stay at abstract runtime-collaboration architecture level. -- If prerequisite views are insufficient, record process gaps instead of fabricating runtime links or failure paths. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders and `REPO_FACTS_FILE`. Treat that as bootstrap scaffolding only. After setup, this command must populate only `PROCESS_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -If setup creates `REPO_FACTS_FILE`, leave it as-is. Do not read it as input and do not add facts to it from this generate command. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-process-template.md`, and `architecture-template.md`. -3. Extract source-backed scenario paths, logical boundaries, states, and invariants. -4. Normalize runtime participant, handoff, receipt, and failure-closure terminology. -5. Derive runtime collaboration boundaries and completion conditions. -6. Classify each candidate as a supported process conclusion or a process gap under the schema and quality gates. -7. Render the schema-compliant process working model with `architecture-process-template.md`. -8. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -9. Report updated paths and explicit process gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the process view contains call stacks, queue names, retry counts, endpoint sequences, workflow engine configuration, or orchestration code. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a scenario path, logical boundary, or stated constraint. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Process Gaps`. -- BLOCKER `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING` if a boundary has responsibilities but no explicit non-responsibility. -- Record gaps instead of inventing runtime ownership or operational behavior. diff --git a/extensions/arch/commands/speckit.arch.process-reverse.md b/extensions/arch/commands/speckit.arch.process-reverse.md deleted file mode 100644 index 4b6140aa24..0000000000 --- a/extensions/arch/commands/speckit.arch.process-reverse.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -description: Reverse-generate the 4+1 process view from observable repository facts. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). In reverse workflows, user input may scope evidence collection or state explicit external constraints, but user input alone must not prove a reverse-generated architecture conclusion. - -## Goal - -Reverse-generate or refresh the process view from observable repository evidence: - -- Evidence layer: `.specify/memory/architecture-repo-facts.md` -- Target view: `.specify/memory/architecture-process-view.md` -- Supporting inputs: scenario and logical views if available under Supporting View Availability -- Optional synthesis refresh: `.specify/memory/architecture.md` - -## Operating Boundaries - -- Write only `REPO_FACTS_FILE` and `PROCESS_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not modify scenario/logical views, source code, README files, docs, package files, configuration, tests, deployment files, specs, plans, tasks, or runbooks. -- Stay at abstract runtime-collaboration architecture level. -- If repository evidence is insufficient, record a specific evidence gap and process gap instead of inventing runtime links, handoffs, retries, or failure closure. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders. Treat that as bootstrap scaffolding only. After setup, this command must populate only `REPO_FACTS_FILE` and `PROCESS_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -## Evidence Sources - -Inspect workers, schedulers, middleware, async jobs, event handlers, transactions, retries, locks, route behavior, tests, examples, configuration, and CI/runtime scripts. - -Repository-First Inputs: if `.specify/memory/repository-first/` exists, inspect only non-matrix markdown evidence that affects runtime boundaries, such as observable invocation constraints, worker entry points, or runtime ownership signals, and summarize those signals in `REPO_FACTS_FILE`. Dependency matrices are owned by the development view; this command must not consume dependency matrices directly or treat them as a separate architecture view. Repository-first content must not be copied verbatim into architecture views. - -## Supporting View Availability - -`SCENARIO_VIEW` and `LOGICAL_VIEW` are available only when the readiness validator reports no blockers for those views such as missing artifact, placeholder marker, required-section, or traceability failures. Placeholder content and view gaps may identify missing context but must not support new process conclusions. - -## Repo Facts Merge Rule - -Treat `REPO_FACTS_FILE` as a cumulative evidence layer. Preserve existing non-placeholder facts from sections outside this command's evidence focus unless the cited evidence no longer exists or is contradicted by stronger evidence. When replacing, removing, or downgrading an existing fact, record the reason in `Evidence Gaps` or a review trigger instead of silently dropping it. - -## Repo Facts Evidence Rules - -- Every non-placeholder fact must name an evidence source such as a file, directory, configuration, test, script, manifest, command output, or commit signal. -- Confidence values are `High`, `Medium`, or `Low`: `High` means multiple independent sources agree; `Medium` means one strong source is present; `Low` means naming, directory structure, isolated code, or Git history suggests a fact but lacks behavior evidence. -- Git history is an auxiliary signal for change axes and boundary risks. It cannot independently prove architecture conclusions. -- Repository-first outputs are fact inputs only when they match this command's process evidence focus. Do not consume repository-first dependency matrices directly; use development-view dependency conclusions only after `DEVELOPMENT_VIEW` is synthesis-ready and relevant to runtime boundaries. -- Concrete classes, functions, fields, endpoints, database tables, and implementation data structures may appear only as evidence sources, not architecture conclusions. -- Architecture conclusions must trace to repo facts, available supporting-view conclusions, or stated external constraints. If a conclusion is supported only by user input, report blocker code `ARCH_USER_INPUT_ONLY` and place it in `Evidence Gaps` or the target view gaps instead of conclusion tables. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `REPO_FACTS_FILE`, `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-repo-facts-template.md`, `architecture-process-template.md`, and `architecture-template.md`. -3. Refresh repo facts for this command's evidence focus and classify unsupported observations as evidence gaps. -4. Populate a schema-compliant process working model from eligible repo facts plus `SCENARIO_VIEW` and `LOGICAL_VIEW` when they satisfy Supporting View Availability. -5. Put low-confidence facts in gaps rather than promoting them into process conclusions. -6. Apply the repo facts merge rule before writing `REPO_FACTS_FILE`. -7. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -8. Report updated paths and explicit unresolved gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the process view promotes call stacks, queue names, retry counts, thread/process details, endpoint sequences, workflow engine config, or orchestration code into architecture conclusions. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a repo fact, available `SCENARIO_VIEW` or `LOGICAL_VIEW` source, or stated constraint. -- BLOCKER `ARCH_REPO_FIRST_MATRIX_MISUSED` if repository-first dependency matrices are copied into architecture views, treated as an independent architecture view, or used as direct non-development evidence. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Evidence Gaps` or `Process Gaps`. -- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used alone as a process conclusion. -- BLOCKER `ARCH_SOURCE_MISSING` if runtime ownership, handoffs, or failure closure cannot be supported by repository evidence; record the unsupported item in evidence gaps and target-view gaps. diff --git a/extensions/arch/commands/speckit.arch.reverse.md b/extensions/arch/commands/speckit.arch.reverse.md new file mode 100644 index 0000000000..df1bae6f6c --- /dev/null +++ b/extensions/arch/commands/speckit.arch.reverse.md @@ -0,0 +1,75 @@ +--- +description: Reverse-generate an architecture planning contract from observable repository evidence. +scripts: + sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json + ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json +--- + +## User Input + +```text +$ARGUMENTS +``` + +You **MUST** consider the user input before proceeding when it is not empty. User input may scope repository inspection or state external constraints, but user input alone must not prove a reverse-generated architecture rule. + +## Goal + +Reverse-generate or refresh the only architecture artifact: + +- Planning contract: `.specify/memory/architecture.md` + +The planning contract is the downstream planning surface. Repository evidence may be inspected during the command, but it must be summarized only inside plan-facing contract sections and open architecture questions. + +## Operating Boundaries + +- Write only `ARCH_FILE`. +- Do not create, update, or require separate 4+1 view files. +- Do not create, update, or require `.specify/memory/architecture-repo-facts.md`. +- Do not modify source code, feature specs, plans, tasks, tests, root `docs/`, deployment manifests, package files, infrastructure files, or runbooks. +- Stay at architecture planning-contract level. Do not promote implementation details into planning rules. + +## Evidence Sources + +Inspect observable repository evidence such as README files, entry points, package manifests, routes, workers, tests, configuration, scripts, CI, deployment clues, and existing `.specify/memory/repository-first/` artifacts when present. + +Every reverse-derived planning rule must be supported by observable repository evidence or a stated external constraint. Git history alone must not prove an architecture rule. + +## Internal 4+1 Reasoning Lens + +Use these lenses to classify evidence, but render only the planning contract: + +- Scenario lens: user-visible behaviors, actors, entry points, main paths, and failure paths. +- Logical lens: capability boundaries, domain concepts, ownership, state responsibility, and invariants. +- Process lens: runtime links, handoffs, approvals, receipts, and failure closure. +- Development lens: module boundaries, dependency direction, package ownership, and code-organization constraints. +- Physical lens: deployment assumptions, external systems, runtime environment, fact sources, and operational constraints. + +## Structured Contract + +`ARCH_SCHEMA_FILE` is the authoritative working-model contract for the planning contract. Shape a JSON-compatible working model before rendering Markdown with `architecture-template.md`. + +`ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable planning readiness gate. After rendering candidate changes, run the validator and report `planning_gate`, `ready_gate`, blocker codes, affected artifacts, and affected sections. + +Every reverse-derived rule row must include `Source / Basis` inside `.specify/memory/architecture.md`. Because this command writes only one artifact, repository evidence must be summarized in that column or in `Open Architecture Questions`, not in a secondary evidence file. + +## Outline + +1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. +2. Load `ARCH_FILE`, `ARCH_SCHEMA_FILE`, and `architecture-template.md`. +3. Inspect repository evidence within the user's scope, or the full repository when no scope is provided. +4. Use the internal 4+1 reasoning lens to project eligible evidence into plan-facing architecture rules. +5. Render `ARCH_FILE` with the required planning contract sections. +6. Run the readiness validator. Report `planning_gate`, `ready_gate`, blockers, updated path, evidence gaps, and open architecture questions. + +## Quality Gates + +- BLOCKER `ARCH_SOURCE_MISSING` if a reverse-derived planning rule lacks observable repository evidence or a stated external constraint. +- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used as the sole support for a planning rule. +- BLOCKER `ARCH_PLANNING_SCOPE_RULES_MISSING` if the contract has no supported Planning Scope Rules. +- BLOCKER `ARCH_CAPABILITY_BOUNDARIES_MISSING` if the contract has no supported Capability Boundaries. +- BLOCKER `ARCH_CONSTRAINTS_OR_DECISIONS_MISSING` if both Required Constraints and Architecture Decisions Already Made are empty. +- BLOCKER `ARCH_PLAN_REVIEW_CHECKLIST_MISSING` if the contract has no supported Plan Review Checklist. +- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if concrete package trees, classes, functions, endpoints, database structures, framework wiring, deployment manifests, scripts, runbooks, plans, tasks, or test strategy are promoted into planning rules. +- BLOCKER `ARCH_OPEN_QUESTION_STATUS_INVALID` if an open architecture question does not use `BLOCKS_PLAN` or `CAN_PROCEED_WITH_GUARDRAIL`. +- Place unsupported conclusions in `Open Architecture Questions`, not in planning-rule tables. diff --git a/extensions/arch/commands/speckit.arch.scenario-generate.md b/extensions/arch/commands/speckit.arch.scenario-generate.md deleted file mode 100644 index cfeb341cfd..0000000000 --- a/extensions/arch/commands/speckit.arch.scenario-generate.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -description: Generate the 4+1 scenario view from intended product and use-case context. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Goal - -Generate or refresh the scenario view: - -- Target view: `.specify/memory/architecture-scenario-view.md` -- Optional synthesis refresh: `.specify/memory/architecture.md` - -This is the `+1` view in 4+1 architecture. It produces actor, goal, use-case, path, branch, and acceptance semantics for the other architecture views. - -## Operating Boundaries - -- Write only `SCENARIO_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not read, populate, or update `REPO_FACTS_FILE`. -- Read `.specify/memory/uc.md` only as optional scenario background. -- Do not modify `.specify/memory/uc.md`, `.specify/memory/constitution.md`, feature specs, plans, tasks, source code, tests, root `docs/`, deployment manifests, or runbooks. -- Stay at abstract architecture-design level. -- If context is insufficient, record a specific scenario gap instead of inventing actors, goals, business facts, or acceptance meaning. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders and `REPO_FACTS_FILE`. Treat that as bootstrap scaffolding only. After setup, this command must populate only `SCENARIO_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -If setup creates `REPO_FACTS_FILE`, leave it as-is. Do not read it as input and do not add facts to it from this generate command. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `SCENARIO_VIEW`, `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `architecture-scenario-template.md`, and `architecture-template.md`. -3. Load `.specify/memory/uc.md` if present as supporting context. -4. Extract source-backed actors, goals, triggers, paths, branches, and acceptance semantics. -5. Normalize scenario terminology and derive scenario-level boundaries. -6. Classify each candidate as a supported scenario conclusion or a scenario gap under the schema and quality gates. -7. Render the schema-compliant scenario working model with `architecture-scenario-template.md`. -8. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE` using `architecture-template.md`; otherwise leave synthesis untouched and report validator blocker codes. -9. Report updated paths and explicit scenario gaps. - -## Quality Gates - -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if the scenario view contains implementation details, components, APIs, database tables, deployment scripts, or task plans. -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks stated scenario source, user input source, or existing memory source. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Scenario Gaps`. -- BLOCKER `ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING` if a boundary has responsibilities but no explicit non-responsibility. -- Record gaps instead of inventing business facts. diff --git a/extensions/arch/commands/speckit.arch.scenario-reverse.md b/extensions/arch/commands/speckit.arch.scenario-reverse.md deleted file mode 100644 index 18d316cdbb..0000000000 --- a/extensions/arch/commands/speckit.arch.scenario-reverse.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -description: Reverse-generate the 4+1 scenario view from observable repository facts. -scripts: - sh: .specify/extensions/arch/scripts/bash/setup-arch.sh --json - ps: .specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json ---- - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). In reverse workflows, user input may scope evidence collection or state explicit external constraints, but user input alone must not prove a reverse-generated architecture conclusion. - -## Goal - -Reverse-generate or refresh the scenario view from observable repository evidence: - -- Evidence layer: `.specify/memory/architecture-repo-facts.md` -- Target view: `.specify/memory/architecture-scenario-view.md` -- Optional synthesis refresh: `.specify/memory/architecture.md` - -## Operating Boundaries - -- Write only `REPO_FACTS_FILE` and `SCENARIO_VIEW`; update `ARCH_FILE` only when the architecture readiness validator returns `ready_gate: PASS`. -- Do not modify source code, README files, project documentation, package files, configuration, tests, deployment files, `.specify/memory/uc.md`, `.specify/memory/constitution.md`, feature specs, plans, tasks, root `docs/`, deployment manifests, or runbooks. -- Stay at abstract architecture-design level. -- If repository evidence is insufficient, record a specific evidence gap and scenario gap instead of inventing actors, use cases, business meaning, or acceptance semantics. - -## Setup Bootstrap - -`{SCRIPT}` may create missing architecture memory files from templates, including non-target view placeholders. Treat that as bootstrap scaffolding only. After setup, this command must populate only `REPO_FACTS_FILE` and `SCENARIO_VIEW`, and may refresh `ARCH_FILE` only under the synthesis readiness rule below. - -## Evidence Sources - -Inspect README/docs, CLI/API entry points, examples, tests, route declarations, configuration, package manifests, and user-visible behavior descriptions. Infer target-view conclusions only from user-visible behavior, explicit documentation, or stated external constraints. Prefer concise inventory over exhaustive source listing. - -Repository-First Inputs: if `.specify/memory/repository-first/` exists, inspect only non-matrix markdown evidence that affects scenario meaning, such as user-visible entry points, examples, or stated invocation constraints, and summarize those signals in `REPO_FACTS_FILE`. Dependency matrices are owned by the development view; this command must not consume dependency matrices directly or treat them as a separate architecture view. Repository-first content must not be copied verbatim into architecture views. - -## Repo Facts Merge Rule - -Treat `REPO_FACTS_FILE` as a cumulative evidence layer. Preserve existing non-placeholder facts from sections outside this command's evidence focus unless the cited evidence no longer exists or is contradicted by stronger evidence. When replacing, removing, or downgrading an existing fact, record the reason in `Evidence Gaps` or a review trigger instead of silently dropping it. - -## Repo Facts Evidence Rules - -- Every non-placeholder fact must name an evidence source such as a file, directory, configuration, test, script, manifest, command output, or commit signal. -- Confidence values are `High`, `Medium`, or `Low`: `High` means multiple independent sources agree; `Medium` means one strong source is present; `Low` means naming, directory structure, isolated code, or Git history suggests a fact but lacks behavior evidence. -- Git history is an auxiliary signal for change axes and boundary risks. It cannot independently prove architecture conclusions. -- Repository-first outputs are fact inputs only when they match this command's scenario evidence focus. Do not consume repository-first dependency matrices directly; use development-view dependency conclusions only after `DEVELOPMENT_VIEW` is synthesis-ready and relevant to scenario meaning. -- Concrete classes, functions, fields, endpoints, database tables, and implementation data structures may appear only as evidence sources, not architecture conclusions. -- Architecture conclusions must trace to repo facts or stated external constraints. If a conclusion is supported only by user input, report blocker code `ARCH_USER_INPUT_ONLY` and place it in `Evidence Gaps` or the target view gaps instead of conclusion tables. - -## Structured Contract - -`ARCH_SCHEMA_FILE` is the authoritative working-model contract for architecture artifacts. Use it to shape JSON-compatible working models for every file you update before rendering Markdown with the corresponding templates. `ARCH_VALIDATOR_FILE` and `ARCH_VALIDATOR_PS_FILE` provide the executable readiness gate for rendered artifacts. After rendering candidate changes, run the readiness validator and use its `ready_gate` and blocker codes as the only synthesis refresh decision. The command owns evidence extraction, classification, merge policy when applicable, and write routing; schemas own working-model structure; validators own rendered-artifact readiness; templates own Markdown layout only. - -## Synthesis Readiness - -Parse all five view paths and validator paths from setup JSON: `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, `ARCH_VALIDATOR_FILE`, and `ARCH_VALIDATOR_PS_FILE`. - -Synthesis readiness is validator-owned. Run `ARCH_VALIDATOR_FILE --json` (or `ARCH_VALIDATOR_PS_FILE -Json` in PowerShell-only environments) after rendering candidate view updates. Refresh `ARCH_FILE` only when the validator returns `ready_gate: PASS` with no blockers. If the validator returns `ready_gate: BLOCKED`, leave `ARCH_FILE` unchanged and report the blocker codes, affected artifacts, and affected sections. - -## Outline - -1. Run `{SCRIPT}` from repo root and parse JSON for `ARCH_FILE`, `ARCH_SCHEMA_FILE`, `ARCH_VALIDATOR_FILE`, `ARCH_VALIDATOR_PS_FILE`, `REPO_FACTS_FILE`, and all five view paths. -2. Load `REPO_FACTS_FILE`, `SCENARIO_VIEW`, `ARCH_SCHEMA_FILE`, `architecture-repo-facts-template.md`, `architecture-scenario-template.md`, and `architecture-template.md`. -3. Refresh repo facts for this command's evidence focus and classify unsupported observations as evidence gaps. -4. Populate a schema-compliant scenario working model from high- or medium-confidence facts. -5. Put low-confidence or missing business meaning in evidence gaps and scenario gaps. -6. Apply the repo facts merge rule before writing `REPO_FACTS_FILE`. -7. Run the readiness validator. If it returns `ready_gate: PASS`, refresh `ARCH_FILE`; otherwise leave synthesis untouched and report validator blocker codes. -8. Report updated paths and explicit unresolved gaps. - -## Quality Gates - -- BLOCKER `ARCH_SOURCE_MISSING` if a conclusion or dependency matrix entry lacks a repo fact source or stated external constraint source. -- BLOCKER `ARCH_SOURCE_MISSING` if the repo facts file contains generic claims without file paths, directories, configuration, tests, commands, or commit signals. -- BLOCKER `ARCH_REPO_FIRST_MATRIX_MISUSED` if repository-first dependency matrices are copied into architecture views, treated as an independent architecture view, or used as direct non-development evidence. -- BLOCKER `ARCH_UNSUPPORTED_CONCLUSION` if unsupported target-view conclusions appear in conclusion tables; place them only in `Evidence Gaps` or `Scenario Gaps`. -- BLOCKER `ARCH_GIT_HISTORY_ONLY` if Git history is used alone as a scenario conclusion. -- BLOCKER `ARCH_SOURCE_MISSING` if actors, goals, or business meaning cannot be supported by repository evidence; record the unsupported item in evidence gaps and target-view gaps. diff --git a/extensions/arch/extension.yml b/extensions/arch/extension.yml index 79f4c03cd2..6d3bec1dc7 100644 --- a/extensions/arch/extension.yml +++ b/extensions/arch/extension.yml @@ -2,9 +2,9 @@ schema_version: "1.0" extension: id: arch - name: "Architecture Workflow" - version: "1.2.2" - description: "Generate or reverse project-level 4+1 architecture views with per-view and full-workflow commands" + name: "Architecture Planning Contract" + version: "2.0.0" + description: "Generate or reverse a planning-focused architecture contract that guides downstream Spec Kit plans" author: bigsmartben repository: https://github.com/bigsmartben/spec-kit-arch homepage: https://github.com/bigsmartben/spec-kit-arch @@ -15,45 +15,15 @@ requires: provides: commands: - - name: speckit.arch.scenario-generate - file: commands/speckit.arch.scenario-generate.md - description: "Generate the 4+1 scenario view from intended product and use-case context" - - name: speckit.arch.logical-generate - file: commands/speckit.arch.logical-generate.md - description: "Generate the 4+1 logical view from scenario architecture semantics" - - name: speckit.arch.process-generate - file: commands/speckit.arch.process-generate.md - description: "Generate the 4+1 process view from scenario and logical architecture views" - - name: speckit.arch.development-generate - file: commands/speckit.arch.development-generate.md - description: "Generate the 4+1 development view and required dependency matrix from logical and process architecture views" - - name: speckit.arch.physical-generate - file: commands/speckit.arch.physical-generate.md - description: "Generate the 4+1 physical view from process and development architecture views" - - name: speckit.arch.full-generate - file: commands/speckit.arch.full-generate.md - description: "Generate all 4+1 architecture views and the architecture synthesis from intended project context" - - name: speckit.arch.full-reverse - file: commands/speckit.arch.full-reverse.md - description: "Reverse-generate all 4+1 architecture views and the architecture synthesis from observable repository facts" - - name: speckit.arch.scenario-reverse - file: commands/speckit.arch.scenario-reverse.md - description: "Reverse-generate the 4+1 scenario view from observable repository facts" - - name: speckit.arch.logical-reverse - file: commands/speckit.arch.logical-reverse.md - description: "Reverse-generate the 4+1 logical view from observable repository facts" - - name: speckit.arch.process-reverse - file: commands/speckit.arch.process-reverse.md - description: "Reverse-generate the 4+1 process view from observable repository facts" - - name: speckit.arch.development-reverse - file: commands/speckit.arch.development-reverse.md - description: "Reverse-generate the 4+1 development view and required dependency matrix from observable repository facts" - - name: speckit.arch.physical-reverse - file: commands/speckit.arch.physical-reverse.md - description: "Reverse-generate the 4+1 physical view from observable repository facts" + - name: speckit.arch.generate + file: commands/speckit.arch.generate.md + description: "Generate an architecture planning contract from intended product and use-case context" + - name: speckit.arch.reverse + file: commands/speckit.arch.reverse.md + description: "Reverse-generate an architecture planning contract from observable repository facts" tags: - architecture - - 4plus1 + - planning-contract - workflow - design diff --git a/extensions/arch/schemas/architecture-artifacts.schema.json b/extensions/arch/schemas/architecture-artifacts.schema.json index 92e5fa15d3..39c8bd9afa 100644 --- a/extensions/arch/schemas/architecture-artifacts.schema.json +++ b/extensions/arch/schemas/architecture-artifacts.schema.json @@ -1,383 +1,124 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/bigsmartben/spec-kit-arch/schemas/architecture-artifacts.schema.json", - "title": "Spec Kit Architecture Artifact Contract", + "title": "Spec Kit Architecture Planning Contract", "type": "object", "additionalProperties": false, "required": [ "artifactType", "project", "sections", - "traceability", - "gaps", "readiness" ], "properties": { "artifactType": { "type": "string", "enum": [ - "architecture-synthesis", - "repo-facts", - "scenario-view", - "logical-view", - "process-view", - "development-view", - "physical-view" + "architecture-planning-contract" ] }, "project": { - "type": "string", - "minLength": 1 + "$ref": "#/$defs/nonEmptyText" }, "sourceMode": { "type": "string", "enum": [ "generate", - "reverse", - "synthesis" + "reverse" ] }, "sections": { "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/section" - } - }, - "traceability": { - "type": "array", - "items": { - "$ref": "#/$defs/trace" - } - }, - "gaps": { - "type": "array", + "minItems": 9, "items": { - "$ref": "#/$defs/gap" - } - }, - "readiness": { - "$ref": "#/$defs/readiness" - } - }, - "allOf": [ - { - "if": { - "properties": { - "artifactType": { - "const": "architecture-synthesis" + "oneOf": [ + { + "$ref": "#/$defs/architectureIntentSection" + }, + { + "$ref": "#/$defs/planningScopeRulesSection" + }, + { + "$ref": "#/$defs/capabilityBoundariesSection" + }, + { + "$ref": "#/$defs/requiredConstraintsSection" + }, + { + "$ref": "#/$defs/architectureDecisionsSection" + }, + { + "$ref": "#/$defs/allowedExtensionPointsSection" + }, + { + "$ref": "#/$defs/prohibitedPlanDirectionsSection" + }, + { + "$ref": "#/$defs/openArchitectureQuestionsSection" + }, + { + "$ref": "#/$defs/planReviewChecklistSection" } - }, - "required": [ - "artifactType" ] }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/section-view-index" - }, - { - "$ref": "#/$defs/section-architecture-intent" - }, - { - "$ref": "#/$defs/section-central-design-forces" - }, - { - "$ref": "#/$defs/section-primary-tradeoffs" - }, - { - "$ref": "#/$defs/section-stable-boundaries" - }, - { - "$ref": "#/$defs/section-change-axes" - }, - { - "$ref": "#/$defs/section-anti-patterns" - }, - { - "$ref": "#/$defs/section-cross-view-architecture-model" - }, - { - "$ref": "#/$defs/section-key-architecture-conclusions" - }, - { - "$ref": "#/$defs/section-cross-cutting-constraints" - }, - { - "$ref": "#/$defs/section-open-risks-and-review-triggers" - } - ] - } - } - } - }, - { - "if": { - "properties": { - "artifactType": { - "const": "repo-facts" - } + "allOf": [ + { + "$ref": "#/$defs/section-architecture-intent" }, - "required": [ - "artifactType" - ] - }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/section-repository-identity" - }, - { - "$ref": "#/$defs/section-entry-points" - }, - { - "$ref": "#/$defs/section-user-visible-behaviors" - }, - { - "$ref": "#/$defs/section-system-boundaries" - }, - { - "$ref": "#/$defs/section-data-and-state-clues" - }, - { - "$ref": "#/$defs/section-runtime-and-process-clues" - }, - { - "$ref": "#/$defs/section-development-structure-clues" - }, - { - "$ref": "#/$defs/section-repository-first-projection" - }, - { - "$ref": "#/$defs/section-physical-deployment-clues" - }, - { - "$ref": "#/$defs/section-git-history-signals" - }, - { - "$ref": "#/$defs/section-evidence-gaps" - } - ] - } - } - } - }, - { - "if": { - "properties": { - "artifactType": { - "const": "scenario-view" - } + { + "$ref": "#/$defs/section-planning-scope-rules" }, - "required": [ - "artifactType" - ] - }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/view-common-sections" - }, - { - "$ref": "#/$defs/section-actors-and-participants" - }, - { - "$ref": "#/$defs/section-use-cases" - }, - { - "$ref": "#/$defs/section-scenario-paths" - }, - { - "$ref": "#/$defs/section-acceptance-semantics" - }, - { - "$ref": "#/$defs/section-source-traceability" - }, - { - "$ref": "#/$defs/section-scenario-gaps" - } - ] - } - } - } - }, - { - "if": { - "properties": { - "artifactType": { - "const": "logical-view" - } + { + "$ref": "#/$defs/section-capability-boundaries" }, - "required": [ - "artifactType" - ] - }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/view-common-sections" - }, - { - "$ref": "#/$defs/section-capability-boundaries" - }, - { - "$ref": "#/$defs/section-domain-objects-and-relationships" - }, - { - "$ref": "#/$defs/section-state-and-lifecycle" - }, - { - "$ref": "#/$defs/section-logical-decisions" - }, - { - "$ref": "#/$defs/section-source-traceability" - }, - { - "$ref": "#/$defs/section-logical-gaps" - } - ] - } - } - } - }, - { - "if": { - "properties": { - "artifactType": { - "const": "process-view" - } + { + "$ref": "#/$defs/section-required-constraints" }, - "required": [ - "artifactType" - ] - }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/view-common-sections" - }, - { - "$ref": "#/$defs/section-main-runtime-links" - }, - { - "$ref": "#/$defs/section-handoffs-and-approvals" - }, - { - "$ref": "#/$defs/section-receipts-and-user-participation" - }, - { - "$ref": "#/$defs/section-failure-degradation-and-closure" - }, - { - "$ref": "#/$defs/section-source-traceability" - }, - { - "$ref": "#/$defs/section-process-gaps" - } - ] - } + { + "$ref": "#/$defs/section-architecture-decisions-already-made" + }, + { + "$ref": "#/$defs/section-allowed-extension-points" + }, + { + "$ref": "#/$defs/section-prohibited-plan-directions" + }, + { + "$ref": "#/$defs/section-open-architecture-questions" + }, + { + "$ref": "#/$defs/section-plan-review-checklist" } - } + ] }, - { - "if": { - "properties": { - "artifactType": { - "const": "development-view" - } - }, - "required": [ - "artifactType" + "readiness": { + "$ref": "#/$defs/readiness" + } + }, + "$defs": { + "nonEmptyText": { + "type": "string", + "minLength": 1, + "not": { + "enum": [ + "NEEDS ARCH UPDATE", + "NEEDS REPO FACTS UPDATE", + "TBD", + "N/A", + "none", + "unknown" ] - }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/view-common-sections" - }, - { - "$ref": "#/$defs/section-architecture-level-components" - }, - { - "$ref": "#/$defs/section-package-boundary-intent" - }, - { - "$ref": "#/$defs/section-contracts-and-artifacts" - }, - { - "$ref": "#/$defs/section-dependency-rules" - }, - { - "$ref": "#/$defs/section-dependency-matrix" - }, - { - "$ref": "#/$defs/section-source-traceability" - }, - { - "$ref": "#/$defs/section-development-view-gaps" - } - ] - } - } } }, - { - "if": { - "properties": { - "artifactType": { - "const": "physical-view" - } - }, - "required": [ - "artifactType" - ] - }, - "then": { - "properties": { - "sections": { - "allOf": [ - { - "$ref": "#/$defs/view-common-sections" - }, - { - "$ref": "#/$defs/section-deployment-and-hosting-boundaries" - }, - { - "$ref": "#/$defs/section-external-system-collaboration" - }, - { - "$ref": "#/$defs/section-fact-sources-and-observability" - }, - { - "$ref": "#/$defs/section-operations-and-release-boundaries" - }, - { - "$ref": "#/$defs/section-source-traceability" - }, - { - "$ref": "#/$defs/section-physical-view-gaps" - } - ] - } + "sourceBasis": { + "description": "Source-backed basis for a plan-facing architecture rule.", + "allOf": [ + { + "$ref": "#/$defs/nonEmptyText" } - } - } - ], - "$defs": { - "section": { + ] + }, + "sectionBase": { "type": "object", "additionalProperties": false, "required": [ @@ -391,919 +132,575 @@ "pattern": "^[a-z][a-z0-9-]*$" }, "title": { - "type": "string", - "minLength": 1 + "$ref": "#/$defs/nonEmptyText" }, "records": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "$ref": "#/$defs/recordValue" - } - } + "type": "array" } } }, - "recordValue": { - "type": [ - "string", - "number", - "boolean", - "array", - "object", - "null" + "architectureIntentRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "intent", + "sourceBasis" ], - "not": { - "const": "NEEDS ARCH UPDATE" + "properties": { + "intent": { + "$ref": "#/$defs/nonEmptyText" + }, + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" + } } }, - "trace": { + "planningScopeRuleRecord": { "type": "object", "additionalProperties": false, "required": [ - "conclusion", - "sourceType", - "sourceReference", - "confidence" + "rule", + "appliesWhen", + "planMustDo", + "planMustNotDo", + "sourceBasis" ], "properties": { - "conclusion": { - "type": "string", - "minLength": 1 + "rule": { + "$ref": "#/$defs/nonEmptyText" }, - "sourceType": { - "type": "string", - "minLength": 1 + "appliesWhen": { + "$ref": "#/$defs/nonEmptyText" }, - "sourceReference": { - "type": "string", - "minLength": 1 + "planMustDo": { + "$ref": "#/$defs/nonEmptyText" + }, + "planMustNotDo": { + "$ref": "#/$defs/nonEmptyText" }, - "confidence": { - "$ref": "#/$defs/confidence" + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" } } }, - "gap": { + "capabilityBoundaryRecord": { "type": "object", "additionalProperties": false, "required": [ - "gap", - "affectedArea", - "reason" + "capabilityBoundary", + "owns", + "doesNotOwn", + "planningImplication", + "sourceBasis" ], "properties": { - "gap": { - "type": "string", - "minLength": 1 + "capabilityBoundary": { + "$ref": "#/$defs/nonEmptyText" }, - "affectedArea": { - "type": "string", - "minLength": 1 + "owns": { + "$ref": "#/$defs/nonEmptyText" }, - "reason": { - "type": "string", - "minLength": 1 + "doesNotOwn": { + "$ref": "#/$defs/nonEmptyText" + }, + "planningImplication": { + "$ref": "#/$defs/nonEmptyText" + }, + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" } } }, - "readiness": { + "requiredConstraintRecord": { "type": "object", "additionalProperties": false, "required": [ - "readyGate", - "blockers" + "constraint", + "appliesTo", + "planEnforcement", + "sourceBasis" ], "properties": { - "readyGate": { - "type": "string", - "enum": [ - "PASS", - "BLOCKED" - ] + "constraint": { + "$ref": "#/$defs/nonEmptyText" }, - "blockers": { - "type": "array", - "items": { - "$ref": "#/$defs/blocker" - } - } - }, - "allOf": [ - { - "if": { - "properties": { - "readyGate": { - "const": "PASS" - } - }, - "required": [ - "readyGate" - ] - }, - "then": { - "properties": { - "blockers": { - "maxItems": 0 - } - } - } + "appliesTo": { + "$ref": "#/$defs/nonEmptyText" }, - { - "if": { - "properties": { - "readyGate": { - "const": "BLOCKED" - } - }, - "required": [ - "readyGate" - ] - }, - "then": { - "properties": { - "blockers": { - "minItems": 1 - } - } - } + "planEnforcement": { + "$ref": "#/$defs/nonEmptyText" + }, + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" } - ] + } }, - "blocker": { + "architectureDecisionRecord": { "type": "object", "additionalProperties": false, "required": [ - "code", - "message" + "decision", + "planConsequence", + "revisitTrigger", + "sourceBasis" ], "properties": { - "code": { - "$ref": "#/$defs/blockerCode" + "decision": { + "$ref": "#/$defs/nonEmptyText" }, - "message": { - "type": "string", - "minLength": 1 + "planConsequence": { + "$ref": "#/$defs/nonEmptyText" }, - "artifact": { - "type": "string", - "minLength": 1 + "revisitTrigger": { + "$ref": "#/$defs/nonEmptyText" }, - "sectionId": { - "type": "string", - "pattern": "^[a-z][a-z0-9-]*$" + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" } } }, - "blockerCode": { - "type": "string", - "enum": [ - "ARCH_ARTIFACT_MISSING", - "ARCH_PLACEHOLDER_PRESENT", - "ARCH_REQUIRED_SECTION_MISSING", - "ARCH_REQUIRED_SECTION_EMPTY", - "ARCH_TRACEABILITY_MISSING", - "ARCH_DEPENDENCY_MATRIX_MISSING", - "ARCH_DEPENDENCY_MATRIX_EMPTY", - "ARCH_SOURCE_MISSING", - "ARCH_USER_INPUT_ONLY", - "ARCH_REPO_FIRST_MATRIX_MISUSED", - "ARCH_GIT_HISTORY_ONLY", - "ARCH_BOUNDARY_NONRESPONSIBILITY_MISSING", - "ARCH_UNSUPPORTED_CONCLUSION" - ] - }, - "confidence": { - "type": "string", - "enum": [ - "High", - "Medium", - "Low" - ] - }, - "contains-section": { + "allowedExtensionPointRecord": { "type": "object", + "additionalProperties": false, "required": [ - "id" + "extensionPoint", + "intendedUse", + "requiredReviewIf", + "sourceBasis" ], "properties": { - "id": { - "type": "string" + "extensionPoint": { + "$ref": "#/$defs/nonEmptyText" + }, + "intendedUse": { + "$ref": "#/$defs/nonEmptyText" + }, + "requiredReviewIf": { + "$ref": "#/$defs/nonEmptyText" + }, + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" } } }, - "view-common-sections": { - "allOf": [ - { - "$ref": "#/$defs/section-architecture-intent" + "prohibitedPlanDirectionRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "antiPattern", + "whyForbidden", + "saferDirection", + "sourceBasis" + ], + "properties": { + "antiPattern": { + "$ref": "#/$defs/nonEmptyText" }, - { - "$ref": "#/$defs/section-core-tensions" + "whyForbidden": { + "$ref": "#/$defs/nonEmptyText" }, - { - "$ref": "#/$defs/section-stable-boundaries" + "saferDirection": { + "$ref": "#/$defs/nonEmptyText" }, - { - "$ref": "#/$defs/section-change-axes" + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" + } + } + }, + "openArchitectureQuestionRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "question", + "planImpact", + "requiredClarification", + "planningStatus", + "sourceBasis" + ], + "properties": { + "question": { + "$ref": "#/$defs/nonEmptyText" }, - { - "$ref": "#/$defs/section-invariants" + "planImpact": { + "$ref": "#/$defs/nonEmptyText" }, - { - "$ref": "#/$defs/section-non-goals-anti-patterns" + "requiredClarification": { + "$ref": "#/$defs/nonEmptyText" + }, + "planningStatus": { + "type": "string", + "enum": [ + "BLOCKS_PLAN", + "CAN_PROCEED_WITH_GUARDRAIL" + ] + }, + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" } - ] + } }, - "section-view-index": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "view-index" - } - } - } - ] - } - }, - "section-architecture-intent": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "architecture-intent" - } - } - } - ] - } - }, - "section-central-design-forces": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "central-design-forces" - } - } - } - ] - } - }, - "section-primary-tradeoffs": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "primary-tradeoffs" - } - } - } - ] - } - }, - "section-stable-boundaries": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "stable-boundaries" - } - } - } - ] - } - }, - "section-change-axes": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "change-axes" - } - } - } - ] - } - }, - "section-anti-patterns": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "anti-patterns" - } - } - } - ] - } - }, - "section-core-tensions": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "core-tensions" - } - } - } - ] - } - }, - "section-invariants": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "invariants" - } - } - } - ] - } - }, - "section-non-goals-anti-patterns": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "non-goals-anti-patterns" - } - } - } - ] - } - }, - "section-cross-view-architecture-model": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "cross-view-architecture-model" - } - } - } - ] - } - }, - "section-key-architecture-conclusions": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "key-architecture-conclusions" - } - } - } - ] - } - }, - "section-cross-cutting-constraints": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "cross-cutting-constraints" - } - } - } - ] - } - }, - "section-open-risks-and-review-triggers": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "open-risks-and-review-triggers" - } - } - } - ] - } - }, - "section-source-traceability": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "source-traceability" - } - } - } - ] - } - }, - "section-repository-identity": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "repository-identity" - } - } - } - ] - } - }, - "section-entry-points": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "entry-points" - } - } - } - ] - } - }, - "section-user-visible-behaviors": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "user-visible-behaviors" - } - } - } - ] - } - }, - "section-system-boundaries": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "system-boundaries" - } - } - } - ] - } - }, - "section-data-and-state-clues": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "data-and-state-clues" - } - } - } - ] - } - }, - "section-runtime-and-process-clues": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "runtime-and-process-clues" - } - } - } - ] - } - }, - "section-development-structure-clues": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "development-structure-clues" - } - } - } - ] - } - }, - "section-repository-first-projection": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "repository-first-projection" - } - } - } - ] - } - }, - "section-physical-deployment-clues": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "physical-deployment-clues" - } - } - } - ] - } - }, - "section-git-history-signals": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "git-history-signals" - } - } - } - ] - } - }, - "section-evidence-gaps": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "evidence-gaps" - } - } - } - ] - } - }, - "section-actors-and-participants": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "actors-and-participants" - } - } - } - ] - } - }, - "section-use-cases": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "use-cases" - } - } - } - ] - } - }, - "section-scenario-paths": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "scenario-paths" - } - } - } - ] - } - }, - "section-acceptance-semantics": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "acceptance-semantics" - } - } - } - ] - } - }, - "section-scenario-gaps": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "scenario-gaps" - } - } - } - ] + "planReviewCheckRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "check", + "passCriteria", + "blockingFailure", + "sourceBasis" + ], + "properties": { + "check": { + "$ref": "#/$defs/nonEmptyText" + }, + "passCriteria": { + "$ref": "#/$defs/nonEmptyText" + }, + "blockingFailure": { + "$ref": "#/$defs/nonEmptyText" + }, + "sourceBasis": { + "$ref": "#/$defs/sourceBasis" + } } }, - "section-capability-boundaries": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "capability-boundaries" + "architectureIntentSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "architecture-intent" + }, + "title": { + "const": "Architecture Intent" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/architectureIntentRecord" } } } - ] - } + } + ] }, - "section-domain-objects-and-relationships": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "domain-objects-and-relationships" + "planningScopeRulesSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "planning-scope-rules" + }, + "title": { + "const": "Planning Scope Rules" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/planningScopeRuleRecord" } } } - ] - } + } + ] }, - "section-state-and-lifecycle": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "state-and-lifecycle" + "capabilityBoundariesSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "capability-boundaries" + }, + "title": { + "const": "Capability Boundaries" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/capabilityBoundaryRecord" } } } - ] - } + } + ] }, - "section-logical-decisions": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "logical-decisions" + "requiredConstraintsSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "required-constraints" + }, + "title": { + "const": "Required Constraints" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/requiredConstraintRecord" } } } - ] - } + } + ] }, - "section-logical-gaps": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "logical-gaps" + "architectureDecisionsSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "architecture-decisions-already-made" + }, + "title": { + "const": "Architecture Decisions Already Made" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/architectureDecisionRecord" } } } - ] - } + } + ] }, - "section-main-runtime-links": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "main-runtime-links" + "allowedExtensionPointsSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "allowed-extension-points" + }, + "title": { + "const": "Allowed Extension Points" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/allowedExtensionPointRecord" } } } - ] - } + } + ] }, - "section-handoffs-and-approvals": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "handoffs-and-approvals" + "prohibitedPlanDirectionsSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "prohibited-plan-directions" + }, + "title": { + "const": "Prohibited Plan Directions" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/prohibitedPlanDirectionRecord" } } } - ] - } + } + ] }, - "section-receipts-and-user-participation": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "receipts-and-user-participation" + "openArchitectureQuestionsSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "open-architecture-questions" + }, + "title": { + "const": "Open Architecture Questions" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/openArchitectureQuestionRecord" } } } - ] - } + } + ] }, - "section-failure-degradation-and-closure": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { - "properties": { - "id": { - "const": "failure-degradation-and-closure" + "planReviewChecklistSection": { + "allOf": [ + { + "$ref": "#/$defs/sectionBase" + }, + { + "properties": { + "id": { + "const": "plan-review-checklist" + }, + "title": { + "const": "Plan Review Checklist" + }, + "records": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/planReviewCheckRecord" } } } - ] - } + } + ] }, - "section-process-gaps": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" - }, - { + "readiness": { + "type": "object", + "additionalProperties": false, + "required": [ + "planningGate", + "blockers" + ], + "properties": { + "planningGate": { + "type": "string", + "enum": [ + "USABLE", + "BLOCKED" + ] + }, + "readyGate": { + "type": "string", + "enum": [ + "PASS", + "BLOCKED" + ] + }, + "blockers": { + "type": "array", + "items": { + "$ref": "#/$defs/blocker" + } + } + }, + "allOf": [ + { + "if": { "properties": { - "id": { - "const": "process-gaps" + "planningGate": { + "const": "USABLE" } - } - } - ] - } - }, - "section-architecture-level-components": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" + }, + "required": [ + "planningGate" + ] }, - { + "then": { "properties": { - "id": { - "const": "architecture-level-components" + "blockers": { + "maxItems": 0 } } } - ] - } - }, - "section-package-boundary-intent": { - "contains": { - "allOf": [ - { - "$ref": "#/$defs/contains-section" + }, + { + "if": { + "properties": { + "planningGate": { + "const": "BLOCKED" + } + }, + "required": [ + "planningGate" + ] }, - { + "then": { "properties": { - "id": { - "const": "package-boundary-intent" + "blockers": { + "minItems": 1 } } } - ] + } + ] + }, + "blocker": { + "type": "object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "$ref": "#/$defs/blockerCode" + }, + "message": { + "$ref": "#/$defs/nonEmptyText" + }, + "artifact": { + "$ref": "#/$defs/nonEmptyText" + }, + "sectionId": { + "type": "string", + "pattern": "^[a-z][a-z0-9-]*$" + } + } + }, + "blockerCode": { + "type": "string", + "enum": [ + "ARCH_ARTIFACT_MISSING", + "ARCH_PLACEHOLDER_PRESENT", + "ARCH_REQUIRED_SECTION_MISSING", + "ARCH_REQUIRED_SECTION_EMPTY", + "ARCH_PLANNING_SCOPE_RULES_MISSING", + "ARCH_CAPABILITY_BOUNDARIES_MISSING", + "ARCH_CONSTRAINTS_OR_DECISIONS_MISSING", + "ARCH_PLAN_REVIEW_CHECKLIST_MISSING", + "ARCH_SOURCE_MISSING", + "ARCH_GIT_HISTORY_ONLY", + "ARCH_UNSUPPORTED_CONCLUSION", + "ARCH_OPEN_QUESTION_STATUS_INVALID" + ] + }, + "contains-section": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + } } }, - "section-contracts-and-artifacts": { + "section-architecture-intent": { "contains": { "allOf": [ { @@ -1312,14 +709,14 @@ { "properties": { "id": { - "const": "contracts-and-artifacts" + "const": "architecture-intent" } } } ] } }, - "section-dependency-rules": { + "section-planning-scope-rules": { "contains": { "allOf": [ { @@ -1328,37 +725,30 @@ { "properties": { "id": { - "const": "dependency-rules" + "const": "planning-scope-rules" } } } ] } }, - "section-dependency-matrix": { + "section-capability-boundaries": { "contains": { "allOf": [ { "$ref": "#/$defs/contains-section" }, { - "required": [ - "records" - ], "properties": { "id": { - "const": "dependency-matrix" - }, - "records": { - "type": "array", - "minItems": 1 + "const": "capability-boundaries" } } } ] } }, - "section-development-view-gaps": { + "section-required-constraints": { "contains": { "allOf": [ { @@ -1367,14 +757,14 @@ { "properties": { "id": { - "const": "development-view-gaps" + "const": "required-constraints" } } } ] } }, - "section-deployment-and-hosting-boundaries": { + "section-architecture-decisions-already-made": { "contains": { "allOf": [ { @@ -1383,14 +773,14 @@ { "properties": { "id": { - "const": "deployment-and-hosting-boundaries" + "const": "architecture-decisions-already-made" } } } ] } }, - "section-external-system-collaboration": { + "section-allowed-extension-points": { "contains": { "allOf": [ { @@ -1399,14 +789,14 @@ { "properties": { "id": { - "const": "external-system-collaboration" + "const": "allowed-extension-points" } } } ] } }, - "section-fact-sources-and-observability": { + "section-prohibited-plan-directions": { "contains": { "allOf": [ { @@ -1415,14 +805,14 @@ { "properties": { "id": { - "const": "fact-sources-and-observability" + "const": "prohibited-plan-directions" } } } ] } }, - "section-operations-and-release-boundaries": { + "section-open-architecture-questions": { "contains": { "allOf": [ { @@ -1431,14 +821,14 @@ { "properties": { "id": { - "const": "operations-and-release-boundaries" + "const": "open-architecture-questions" } } } ] } }, - "section-physical-view-gaps": { + "section-plan-review-checklist": { "contains": { "allOf": [ { @@ -1447,7 +837,7 @@ { "properties": { "id": { - "const": "physical-view-gaps" + "const": "plan-review-checklist" } } } diff --git a/extensions/arch/scripts/bash/setup-arch.sh b/extensions/arch/scripts/bash/setup-arch.sh index e5201b73d5..b1586e46ac 100755 --- a/extensions/arch/scripts/bash/setup-arch.sh +++ b/extensions/arch/scripts/bash/setup-arch.sh @@ -2,7 +2,6 @@ set -e -# Parse command line arguments JSON_MODE=false for arg in "$@"; do @@ -67,27 +66,14 @@ json_escape() { s="${s//$'\n'/\\n}" s="${s//$'\t'/\\t}" s="${s//$'\r'/\\r}" - s="${s//$'\b'/\\b}" - s="${s//$'\f'/\\f}" - local LC_ALL=C - local i char code - for (( i=0; i<${#s}; i++ )); do - char="${s:$i:1}" - printf -v code '%d' "'$char" 2>/dev/null || code=256 - if (( code >= 1 && code <= 31 )); then - printf '\\u%04x' "$code" - else - printf '%s' "$char" - fi - done + printf '%s' "$s" } resolve_architecture_template() { local template_name="$1" local repo_root="$2" - local ext_templates="$repo_root/.specify/extensions/arch/templates" local override="$repo_root/.specify/templates/overrides/${template_name}.md" - local candidate="$ext_templates/${template_name}.md" + local candidate="$repo_root/.specify/extensions/arch/templates/${template_name}.md" [ -f "$override" ] && echo "$override" && return 0 [ -f "$candidate" ] && echo "$candidate" && return 0 @@ -102,12 +88,6 @@ ARCH_SCHEMA_FILE="$SCHEMA_DIR/architecture-artifacts.schema.json" ARCH_VALIDATOR_FILE="$SCRIPT_DIR/bash/validate-arch-artifacts.sh" ARCH_VALIDATOR_PS_FILE="$SCRIPT_DIR/powershell/validate-arch-artifacts.ps1" ARCH_FILE="$ARCH_DIR/architecture.md" -REPO_FACTS_FILE="$ARCH_DIR/architecture-repo-facts.md" -SCENARIO_VIEW="$ARCH_DIR/architecture-scenario-view.md" -LOGICAL_VIEW="$ARCH_DIR/architecture-logical-view.md" -PROCESS_VIEW="$ARCH_DIR/architecture-process-view.md" -DEVELOPMENT_VIEW="$ARCH_DIR/architecture-development-view.md" -PHYSICAL_VIEW="$ARCH_DIR/architecture-physical-view.md" mkdir -p "$ARCH_DIR" @@ -134,13 +114,7 @@ copy_template_if_missing() { fi } -copy_template_if_missing "architecture-repo-facts-template" "$REPO_FACTS_FILE" copy_template_if_missing "architecture-template" "$ARCH_FILE" -copy_template_if_missing "architecture-scenario-template" "$SCENARIO_VIEW" -copy_template_if_missing "architecture-logical-template" "$LOGICAL_VIEW" -copy_template_if_missing "architecture-process-template" "$PROCESS_VIEW" -copy_template_if_missing "architecture-development-template" "$DEVELOPMENT_VIEW" -copy_template_if_missing "architecture-physical-template" "$PHYSICAL_VIEW" if $JSON_MODE; then if has_jq; then @@ -151,27 +125,15 @@ if $JSON_MODE; then --arg arch_schema_file "$ARCH_SCHEMA_FILE" \ --arg arch_validator_file "$ARCH_VALIDATOR_FILE" \ --arg arch_validator_ps_file "$ARCH_VALIDATOR_PS_FILE" \ - --arg repo_facts_file "$REPO_FACTS_FILE" \ - --arg scenario_view "$SCENARIO_VIEW" \ - --arg logical_view "$LOGICAL_VIEW" \ - --arg process_view "$PROCESS_VIEW" \ - --arg development_view "$DEVELOPMENT_VIEW" \ - --arg physical_view "$PHYSICAL_VIEW" \ - '{ARCH_FILE:$arch_file,ARCH_DIR:$arch_dir,SCHEMA_DIR:$schema_dir,ARCH_SCHEMA_FILE:$arch_schema_file,ARCH_VALIDATOR_FILE:$arch_validator_file,ARCH_VALIDATOR_PS_FILE:$arch_validator_ps_file,REPO_FACTS_FILE:$repo_facts_file,SCENARIO_VIEW:$scenario_view,LOGICAL_VIEW:$logical_view,PROCESS_VIEW:$process_view,DEVELOPMENT_VIEW:$development_view,PHYSICAL_VIEW:$physical_view}' + '{ARCH_FILE:$arch_file,ARCH_DIR:$arch_dir,SCHEMA_DIR:$schema_dir,ARCH_SCHEMA_FILE:$arch_schema_file,ARCH_VALIDATOR_FILE:$arch_validator_file,ARCH_VALIDATOR_PS_FILE:$arch_validator_ps_file}' else - printf '{"ARCH_FILE":"%s","ARCH_DIR":"%s","SCHEMA_DIR":"%s","ARCH_SCHEMA_FILE":"%s","ARCH_VALIDATOR_FILE":"%s","ARCH_VALIDATOR_PS_FILE":"%s","REPO_FACTS_FILE":"%s","SCENARIO_VIEW":"%s","LOGICAL_VIEW":"%s","PROCESS_VIEW":"%s","DEVELOPMENT_VIEW":"%s","PHYSICAL_VIEW":"%s"}\n' \ + printf '{"ARCH_FILE":"%s","ARCH_DIR":"%s","SCHEMA_DIR":"%s","ARCH_SCHEMA_FILE":"%s","ARCH_VALIDATOR_FILE":"%s","ARCH_VALIDATOR_PS_FILE":"%s"}\n' \ "$(json_escape "$ARCH_FILE")" \ "$(json_escape "$ARCH_DIR")" \ "$(json_escape "$SCHEMA_DIR")" \ "$(json_escape "$ARCH_SCHEMA_FILE")" \ "$(json_escape "$ARCH_VALIDATOR_FILE")" \ - "$(json_escape "$ARCH_VALIDATOR_PS_FILE")" \ - "$(json_escape "$REPO_FACTS_FILE")" \ - "$(json_escape "$SCENARIO_VIEW")" \ - "$(json_escape "$LOGICAL_VIEW")" \ - "$(json_escape "$PROCESS_VIEW")" \ - "$(json_escape "$DEVELOPMENT_VIEW")" \ - "$(json_escape "$PHYSICAL_VIEW")" + "$(json_escape "$ARCH_VALIDATOR_PS_FILE")" fi else echo "ARCH_FILE: $ARCH_FILE" @@ -180,10 +142,4 @@ else echo "ARCH_SCHEMA_FILE: $ARCH_SCHEMA_FILE" echo "ARCH_VALIDATOR_FILE: $ARCH_VALIDATOR_FILE" echo "ARCH_VALIDATOR_PS_FILE: $ARCH_VALIDATOR_PS_FILE" - echo "REPO_FACTS_FILE: $REPO_FACTS_FILE" - echo "SCENARIO_VIEW: $SCENARIO_VIEW" - echo "LOGICAL_VIEW: $LOGICAL_VIEW" - echo "PROCESS_VIEW: $PROCESS_VIEW" - echo "DEVELOPMENT_VIEW: $DEVELOPMENT_VIEW" - echo "PHYSICAL_VIEW: $PHYSICAL_VIEW" fi diff --git a/extensions/arch/scripts/bash/validate-arch-artifacts.sh b/extensions/arch/scripts/bash/validate-arch-artifacts.sh index 8d95a17fb1..8fcb6ad1ec 100755 --- a/extensions/arch/scripts/bash/validate-arch-artifacts.sh +++ b/extensions/arch/scripts/bash/validate-arch-artifacts.sh @@ -11,7 +11,7 @@ for arg in "$@"; do ;; --help|-h) echo "Usage: $0 [--json]" - echo " --json Output readiness result as JSON" + echo " --json Output planning readiness result as JSON" echo " --help Show this help message" exit 0 ;; @@ -80,20 +80,18 @@ add_blocker() { } section_heading() { - local section_id="$1" - case "$section_id" in - non-goals-anti-patterns) echo "Non-goals / Anti-patterns"; return ;; - architecture-level-components) echo "Architecture-Level Components"; return ;; - physical-deployment-clues) echo "Physical / Deployment Clues"; return ;; - development-view-gaps) echo "Development View Gaps"; return ;; - physical-view-gaps) echo "Physical View Gaps"; return ;; + case "$1" in + architecture-intent) echo "Architecture Intent" ;; + planning-scope-rules) echo "Planning Scope Rules" ;; + capability-boundaries) echo "Capability Boundaries" ;; + required-constraints) echo "Required Constraints" ;; + architecture-decisions-already-made) echo "Architecture Decisions Already Made" ;; + allowed-extension-points) echo "Allowed Extension Points" ;; + prohibited-plan-directions) echo "Prohibited Plan Directions" ;; + open-architecture-questions) echo "Open Architecture Questions" ;; + plan-review-checklist) echo "Plan Review Checklist" ;; + *) return 1 ;; esac - printf '%s\n' "$section_id" | sed 's/-/ /g' | awk '{ - for (i = 1; i <= NF; i++) { - $i = toupper(substr($i, 1, 1)) substr($i, 2) - } - print - }' } section_exists() { @@ -132,72 +130,196 @@ section_has_content() { ' "$file" } +invalid_source_value() { + local value="$1" + value="$(printf '%s' "$value" | tr -d '`' | sed -E 's/^[[:space:]]+|[[:space:]]+$//g')" + [ -z "$value" ] && return 0 + printf '%s' "$value" | grep -Eiq '^(tbd|n/a|na|none|unknown|guess|guessed|todo|needs arch update|needs repo facts update)$' +} + +section_has_missing_source() { + local file="$1" + local section_id="$2" + local heading + heading="$(section_heading "$section_id")" + awk -v heading="$heading" ' + function trim(s) { + gsub(/^[[:space:]]+|[[:space:]]+$/, "", s) + return s + } + $0 ~ "^##[[:space:]]+" heading "[[:space:]]*$" { in_section = 1; next } + in_section && /^##[[:space:]]+/ { exit } + in_section && /^\|.*\|[[:space:]]*$/ { + line = $0 + if (line ~ /\|[[:space:]]*[-:]+[[:space:]]*\|/) next + if (line ~ /Source[[:space:]]*\/[[:space:]]*Basis/) next + n = split(line, cells, "|") + source = trim(cells[n - 1]) + lower = tolower(source) + if (source == "" || lower ~ /^(tbd|n\/a|na|none|unknown|guess|guessed|todo|needs arch update|needs repo facts update)$/) { + found = 1 + exit + } + } + END { exit(found ? 0 : 1) } + ' "$file" +} + +intent_has_missing_source() { + local file="$1" + awk ' + function trim(s) { + gsub(/^[[:space:]]+|[[:space:]]+$/, "", s) + return s + } + /^##[[:space:]]+Architecture Intent[[:space:]]*$/ { in_section = 1; next } + in_section && /^##[[:space:]]+/ { exit } + in_section && /^\*\*Source[[:space:]]*\/[[:space:]]*Basis\*\*:/ { + value = $0 + sub(/^\*\*Source[[:space:]]*\/[[:space:]]*Basis\*\*:[[:space:]]*/, "", value) + value = trim(value) + lower = tolower(value) + if (value == "" || lower ~ /^(tbd|n\/a|na|none|unknown|guess|guessed|todo|needs arch update|needs repo facts update)$/) { + found = 1 + } + seen = 1 + exit + } + END { + if (!seen) found = 1 + exit(found ? 0 : 1) + } + ' "$file" +} + +open_questions_have_invalid_status() { + local file="$1" + local heading + heading="$(section_heading "open-architecture-questions")" + awk -v heading="$heading" ' + function trim(s) { + gsub(/^[[:space:]]+|[[:space:]]+$/, "", s) + return s + } + $0 ~ "^##[[:space:]]+" heading "[[:space:]]*$" { in_section = 1; next } + in_section && /^##[[:space:]]+/ { exit } + in_section && /^\|.*\|[[:space:]]*$/ { + line = $0 + if (line ~ /\|[[:space:]]*[-:]+[[:space:]]*\|/) next + if (line ~ /Planning Status/) next + n = split(line, cells, "|") + status = trim(cells[n - 2]) + if (status != "BLOCKS_PLAN" && status != "CAN_PROCEED_WITH_GUARDRAIL") { + found = 1 + exit + } + } + END { exit(found ? 0 : 1) } + ' "$file" +} + +has_unsupported_conclusion() { + local file="$1" + grep -Eiq '(^|[^A-Za-z0-9_])(src|app|lib|packages|cmd|internal)/[A-Za-z0-9_./-]+\.[A-Za-z0-9]+([^A-Za-z0-9_]|$)' "$file" && return 0 + grep -Eiq '\b[A-Za-z_][A-Za-z0-9_]*(Controller|Service|Repository|Manager)\b' "$file" && return 0 + grep -Eiq '\b(add|create|edit|modify|write|implement|generate)\b.*\b(endpoint|endpoints|api schema|openapi|database schema|db table|db tables|migration|migrations|task list|tasks|test strategy|runbook|deployment manifest)\b' "$file" && return 0 + return 1 +} + REPO_ROOT="$(get_repo_root)" -ARCH_DIR="$REPO_ROOT/.specify/memory" - -declare -A FILES=( - [architecture-synthesis]="$ARCH_DIR/architecture.md" - [scenario-view]="$ARCH_DIR/architecture-scenario-view.md" - [logical-view]="$ARCH_DIR/architecture-logical-view.md" - [process-view]="$ARCH_DIR/architecture-process-view.md" - [development-view]="$ARCH_DIR/architecture-development-view.md" - [physical-view]="$ARCH_DIR/architecture-physical-view.md" -) - -declare -A REQUIRED_SECTIONS=( - [architecture-synthesis]="view-index|architecture-intent|central-design-forces|primary-tradeoffs|stable-boundaries|change-axes|anti-patterns|cross-view-architecture-model|key-architecture-conclusions|cross-cutting-constraints|open-risks-and-review-triggers" - [scenario-view]="architecture-intent|core-tensions|stable-boundaries|change-axes|invariants|non-goals-anti-patterns|actors-and-participants|use-cases|scenario-paths|acceptance-semantics|source-traceability|scenario-gaps" - [logical-view]="architecture-intent|core-tensions|stable-boundaries|change-axes|invariants|non-goals-anti-patterns|capability-boundaries|domain-objects-and-relationships|state-and-lifecycle|logical-decisions|source-traceability|logical-gaps" - [process-view]="architecture-intent|core-tensions|stable-boundaries|change-axes|invariants|non-goals-anti-patterns|main-runtime-links|handoffs-and-approvals|receipts-and-user-participation|failure-degradation-and-closure|source-traceability|process-gaps" - [development-view]="architecture-intent|core-tensions|stable-boundaries|change-axes|invariants|non-goals-anti-patterns|architecture-level-components|package-boundary-intent|contracts-and-artifacts|dependency-rules|dependency-matrix|source-traceability|development-view-gaps" - [physical-view]="architecture-intent|core-tensions|stable-boundaries|change-axes|invariants|non-goals-anti-patterns|deployment-and-hosting-boundaries|external-system-collaboration|fact-sources-and-observability|operations-and-release-boundaries|source-traceability|physical-view-gaps" -) - -for artifact in architecture-synthesis scenario-view logical-view process-view development-view physical-view; do - file="${FILES[$artifact]}" - - if [ ! -f "$file" ]; then - add_blocker "ARCH_ARTIFACT_MISSING" "$artifact" "" "Required architecture artifact is missing: $file" - continue +ARCH_FILE="$REPO_ROOT/.specify/memory/architecture.md" +ARTIFACT="architecture-planning-contract" + +if [ ! -f "$ARCH_FILE" ]; then + add_blocker "ARCH_ARTIFACT_MISSING" "$ARTIFACT" "" "Required architecture planning contract is missing: $ARCH_FILE" +else + if grep -Eq "NEEDS ARCH UPDATE|NEEDS REPO FACTS UPDATE" "$ARCH_FILE"; then + add_blocker "ARCH_PLACEHOLDER_PRESENT" "$ARTIFACT" "" "Planning contract still contains placeholder update markers." fi - if grep -Eq "NEEDS ARCH UPDATE|NEEDS REPO FACTS UPDATE" "$file"; then - add_blocker "ARCH_PLACEHOLDER_PRESENT" "$artifact" "" "Artifact still contains placeholder update markers." + if has_unsupported_conclusion "$ARCH_FILE"; then + add_blocker "ARCH_UNSUPPORTED_CONCLUSION" "$ARTIFACT" "" "Planning contract contains implementation-level conclusions that belong to downstream planning or implementation." fi - IFS='|' read -r -a sections <<< "${REQUIRED_SECTIONS[$artifact]}" - for section in "${sections[@]}"; do - if ! section_exists "$file" "$section"; then - if [ "$section" = "dependency-matrix" ]; then - add_blocker "ARCH_DEPENDENCY_MATRIX_MISSING" "$artifact" "$section" "Development View must include Dependency Matrix." - else - add_blocker "ARCH_REQUIRED_SECTION_MISSING" "$artifact" "$section" "Required section is missing." - fi + required_sections=( + architecture-intent + planning-scope-rules + capability-boundaries + required-constraints + architecture-decisions-already-made + allowed-extension-points + prohibited-plan-directions + open-architecture-questions + plan-review-checklist + ) + + for section in "${required_sections[@]}"; do + if ! section_exists "$ARCH_FILE" "$section"; then + add_blocker "ARCH_REQUIRED_SECTION_MISSING" "$ARTIFACT" "$section" "Required planning contract section is missing." continue fi - if ! section_has_content "$file" "$section"; then - if [ "$section" = "dependency-matrix" ]; then - add_blocker "ARCH_DEPENDENCY_MATRIX_EMPTY" "$artifact" "$section" "Dependency Matrix has no supported records." - elif [ "$section" = "source-traceability" ]; then - add_blocker "ARCH_TRACEABILITY_MISSING" "$artifact" "$section" "Source Traceability has no supported records." - else - add_blocker "ARCH_REQUIRED_SECTION_EMPTY" "$artifact" "$section" "Required section has no supported records." - fi + if ! section_has_content "$ARCH_FILE" "$section"; then + case "$section" in + planning-scope-rules) + add_blocker "ARCH_PLANNING_SCOPE_RULES_MISSING" "$ARTIFACT" "$section" "Planning Scope Rules has no supported records." + ;; + capability-boundaries) + add_blocker "ARCH_CAPABILITY_BOUNDARIES_MISSING" "$ARTIFACT" "$section" "Capability Boundaries has no supported records." + ;; + plan-review-checklist) + add_blocker "ARCH_PLAN_REVIEW_CHECKLIST_MISSING" "$ARTIFACT" "$section" "Plan Review Checklist has no supported records." + ;; + *) + add_blocker "ARCH_REQUIRED_SECTION_EMPTY" "$ARTIFACT" "$section" "Required planning contract section has no supported records." + ;; + esac fi done -done + + if section_exists "$ARCH_FILE" "architecture-intent" && intent_has_missing_source "$ARCH_FILE"; then + add_blocker "ARCH_SOURCE_MISSING" "$ARTIFACT" "architecture-intent" "Architecture Intent is missing Source / Basis." + fi + + source_sections=( + planning-scope-rules + capability-boundaries + required-constraints + architecture-decisions-already-made + allowed-extension-points + prohibited-plan-directions + open-architecture-questions + plan-review-checklist + ) + + for section in "${source_sections[@]}"; do + if section_exists "$ARCH_FILE" "$section" && section_has_missing_source "$ARCH_FILE" "$section"; then + add_blocker "ARCH_SOURCE_MISSING" "$ARTIFACT" "$section" "Rule-bearing section has a row without supported Source / Basis." + fi + done + + if section_exists "$ARCH_FILE" "open-architecture-questions" && open_questions_have_invalid_status "$ARCH_FILE"; then + add_blocker "ARCH_OPEN_QUESTION_STATUS_INVALID" "$ARTIFACT" "open-architecture-questions" "Open Architecture Questions must use BLOCKS_PLAN or CAN_PROCEED_WITH_GUARDRAIL." + fi + + if section_exists "$ARCH_FILE" "required-constraints" && section_exists "$ARCH_FILE" "architecture-decisions-already-made"; then + if ! section_has_content "$ARCH_FILE" "required-constraints" && ! section_has_content "$ARCH_FILE" "architecture-decisions-already-made"; then + add_blocker "ARCH_CONSTRAINTS_OR_DECISIONS_MISSING" "$ARTIFACT" "required-constraints" "Required Constraints and Architecture Decisions Already Made are both empty." + fi + fi +fi if [ "${#blockers[@]}" -eq 0 ]; then if $JSON_MODE; then - printf '{"ready_gate":"PASS","blockers":[]}\n' + printf '{"planning_gate":"USABLE","ready_gate":"PASS","blockers":[]}\n' else + echo "planning_gate: USABLE" echo "ready_gate: PASS" fi exit 0 fi if $JSON_MODE; then - printf '{"ready_gate":"BLOCKED","blockers":[' + printf '{"planning_gate":"BLOCKED","ready_gate":"BLOCKED","blockers":[' local_prefix="" for blocker in "${blockers[@]}"; do printf '%s%s' "$local_prefix" "$blocker" @@ -205,6 +327,7 @@ if $JSON_MODE; then done printf ']}\n' else + echo "planning_gate: BLOCKED" echo "ready_gate: BLOCKED" for blocker in "${blockers[@]}"; do echo "$blocker" diff --git a/extensions/arch/scripts/powershell/setup-arch.ps1 b/extensions/arch/scripts/powershell/setup-arch.ps1 index 68816f75dd..c8a4946b84 100644 --- a/extensions/arch/scripts/powershell/setup-arch.ps1 +++ b/extensions/arch/scripts/powershell/setup-arch.ps1 @@ -1,5 +1,5 @@ #!/usr/bin/env pwsh -# Setup project-level 4+1 architecture artifacts +# Setup project-level architecture planning contract artifacts [CmdletBinding()] param( @@ -88,12 +88,6 @@ $archSchemaFile = Join-Path $schemaDir "architecture-artifacts.schema.json" $archValidatorFile = Join-Path $scriptDir "bash/validate-arch-artifacts.sh" $archValidatorPsFile = Join-Path $scriptDir "powershell/validate-arch-artifacts.ps1" $archFile = Join-Path $archDir "architecture.md" -$repoFactsFile = Join-Path $archDir "architecture-repo-facts.md" -$scenarioView = Join-Path $archDir "architecture-scenario-view.md" -$logicalView = Join-Path $archDir "architecture-logical-view.md" -$processView = Join-Path $archDir "architecture-process-view.md" -$developmentView = Join-Path $archDir "architecture-development-view.md" -$physicalView = Join-Path $archDir "architecture-physical-view.md" New-Item -ItemType Directory -Path $archDir -Force | Out-Null @@ -121,13 +115,7 @@ function Copy-TemplateIfMissing { } } -Copy-TemplateIfMissing -TemplateName "architecture-repo-facts-template" -Destination $repoFactsFile Copy-TemplateIfMissing -TemplateName "architecture-template" -Destination $archFile -Copy-TemplateIfMissing -TemplateName "architecture-scenario-template" -Destination $scenarioView -Copy-TemplateIfMissing -TemplateName "architecture-logical-template" -Destination $logicalView -Copy-TemplateIfMissing -TemplateName "architecture-process-template" -Destination $processView -Copy-TemplateIfMissing -TemplateName "architecture-development-template" -Destination $developmentView -Copy-TemplateIfMissing -TemplateName "architecture-physical-template" -Destination $physicalView if ($Json) { [PSCustomObject]@{ @@ -137,12 +125,6 @@ if ($Json) { ARCH_SCHEMA_FILE = $archSchemaFile ARCH_VALIDATOR_FILE = $archValidatorFile ARCH_VALIDATOR_PS_FILE = $archValidatorPsFile - REPO_FACTS_FILE = $repoFactsFile - SCENARIO_VIEW = $scenarioView - LOGICAL_VIEW = $logicalView - PROCESS_VIEW = $processView - DEVELOPMENT_VIEW = $developmentView - PHYSICAL_VIEW = $physicalView } | ConvertTo-Json -Compress } else { Write-Output "ARCH_FILE: $archFile" @@ -151,10 +133,4 @@ if ($Json) { Write-Output "ARCH_SCHEMA_FILE: $archSchemaFile" Write-Output "ARCH_VALIDATOR_FILE: $archValidatorFile" Write-Output "ARCH_VALIDATOR_PS_FILE: $archValidatorPsFile" - Write-Output "REPO_FACTS_FILE: $repoFactsFile" - Write-Output "SCENARIO_VIEW: $scenarioView" - Write-Output "LOGICAL_VIEW: $logicalView" - Write-Output "PROCESS_VIEW: $processView" - Write-Output "DEVELOPMENT_VIEW: $developmentView" - Write-Output "PHYSICAL_VIEW: $physicalView" } diff --git a/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1 b/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1 index 923e45c63f..f1e1d77336 100644 --- a/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1 +++ b/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1 @@ -10,7 +10,7 @@ $ErrorActionPreference = 'Stop' if ($Help) { Write-Output "Usage: ./validate-arch-artifacts.ps1 [-Json] [-Help]" - Write-Output " -Json Output readiness result as JSON" + Write-Output " -Json Output planning readiness result as JSON" Write-Output " -Help Show this help message" exit 0 } @@ -117,109 +117,234 @@ function Test-SectionHasContent { return $false } -$repoRoot = Convert-ToPlainPath (Get-RepoRoot) -$archDir = Join-Path $repoRoot ".specify/memory" -$blockers = @() +function Test-InvalidSourceValue { + param([AllowEmptyString()][string]$Value) + + $normalized = ($Value -replace '`', '').Trim() + return [string]::IsNullOrWhiteSpace($normalized) -or $normalized -match '^(tbd|n/a|na|none|unknown|guess|guessed|todo|needs arch update|needs repo facts update)$' +} + +function Test-SectionHasMissingSource { + param( + [AllowEmptyCollection()][AllowEmptyString()][string[]]$Lines, + [Parameter(Mandatory = $true)][string]$Heading + ) + + $pattern = '^##\s+' + [regex]::Escape($Heading) + '\s*$' + $inSection = $false + foreach ($line in $Lines) { + if ($line -match $pattern) { + $inSection = $true + continue + } + if ($inSection -and $line -match '^##\s+') { + break + } + if (-not $inSection) { + continue + } + + $trimmed = $line.Trim() + if ($trimmed -notmatch '^\|.*\|$') { continue } + if ($trimmed -match '\|\s*[-:]+\s*\|') { continue } + if ($trimmed -match 'Source\s*/\s*Basis') { continue } + + $cells = $trimmed -split '\|' + if ($cells.Count -lt 3) { return $true } + $source = $cells[$cells.Count - 2] + if (Test-InvalidSourceValue -Value $source) { return $true } + } + + return $false +} + +function Test-IntentHasMissingSource { + param([AllowEmptyCollection()][AllowEmptyString()][string[]]$Lines) + + $inSection = $false + foreach ($line in $Lines) { + if ($line -match '^##\s+Architecture Intent\s*$') { + $inSection = $true + continue + } + if ($inSection -and $line -match '^##\s+') { + break + } + if (-not $inSection) { + continue + } + if ($line -match '^\*\*Source\s*/\s*Basis\*\*:') { + $value = $line -replace '^\*\*Source\s*/\s*Basis\*\*:\s*', '' + return (Test-InvalidSourceValue -Value $value) + } + } + + return $true +} + +function Test-OpenQuestionsHaveInvalidStatus { + param( + [AllowEmptyCollection()][AllowEmptyString()][string[]]$Lines, + [Parameter(Mandatory = $true)][string]$Heading + ) + + $pattern = '^##\s+' + [regex]::Escape($Heading) + '\s*$' + $inSection = $false + foreach ($line in $Lines) { + if ($line -match $pattern) { + $inSection = $true + continue + } + if ($inSection -and $line -match '^##\s+') { + break + } + if (-not $inSection) { + continue + } + + $trimmed = $line.Trim() + if ($trimmed -notmatch '^\|.*\|$') { continue } + if ($trimmed -match '\|\s*[-:]+\s*\|') { continue } + if ($trimmed -match 'Planning Status') { continue } + + $cells = $trimmed -split '\|' + if ($cells.Count -lt 4) { return $true } + $status = $cells[$cells.Count - 3].Trim() + if ($status -ne "BLOCKS_PLAN" -and $status -ne "CAN_PROCEED_WITH_GUARDRAIL") { + return $true + } + } + + return $false +} + +function Test-UnsupportedConclusion { + param([Parameter(Mandatory = $true)][string]$Content) + + if ($Content -match '(^|[^A-Za-z0-9_])(src|app|lib|packages|cmd|internal)/[A-Za-z0-9_./-]+\.[A-Za-z0-9]+([^A-Za-z0-9_]|$)') { + return $true + } + if ($Content -match '\b[A-Za-z_][A-Za-z0-9_]*(Controller|Service|Repository|Manager)\b') { + return $true + } + if ($Content -match '\b(add|create|edit|modify|write|implement|generate)\b.*\b(endpoint|endpoints|api schema|openapi|database schema|db table|db tables|migration|migrations|task list|tasks|test strategy|runbook|deployment manifest)\b') { + return $true + } -$files = [ordered]@{ - "architecture-synthesis" = Join-Path $archDir "architecture.md" - "scenario-view" = Join-Path $archDir "architecture-scenario-view.md" - "logical-view" = Join-Path $archDir "architecture-logical-view.md" - "process-view" = Join-Path $archDir "architecture-process-view.md" - "development-view" = Join-Path $archDir "architecture-development-view.md" - "physical-view" = Join-Path $archDir "architecture-physical-view.md" + return $false } +$repoRoot = Convert-ToPlainPath (Get-RepoRoot) +$archFile = Join-Path $repoRoot ".specify/memory/architecture.md" +$artifact = "architecture-planning-contract" +$blockers = @() + $sectionHeadings = @{ - "view-index" = "View Index" "architecture-intent" = "Architecture Intent" - "central-design-forces" = "Central Design Forces" - "primary-tradeoffs" = "Primary Tradeoffs" - "stable-boundaries" = "Stable Boundaries" - "change-axes" = "Change Axes" - "anti-patterns" = "Anti-patterns" - "cross-view-architecture-model" = "Cross-View Architecture Model" - "key-architecture-conclusions" = "Key Architecture Conclusions" - "cross-cutting-constraints" = "Cross-Cutting Constraints" - "open-risks-and-review-triggers" = "Open Risks and Review Triggers" - "core-tensions" = "Core Tensions" - "invariants" = "Invariants" - "non-goals-anti-patterns" = "Non-goals / Anti-patterns" - "actors-and-participants" = "Actors and Participants" - "use-cases" = "Use Cases" - "scenario-paths" = "Scenario Paths" - "acceptance-semantics" = "Acceptance Semantics" - "source-traceability" = "Source Traceability" - "scenario-gaps" = "Scenario Gaps" + "planning-scope-rules" = "Planning Scope Rules" "capability-boundaries" = "Capability Boundaries" - "domain-objects-and-relationships" = "Domain Objects and Relationships" - "state-and-lifecycle" = "State and Lifecycle" - "logical-decisions" = "Logical Decisions" - "logical-gaps" = "Logical Gaps" - "main-runtime-links" = "Main Runtime Links" - "handoffs-and-approvals" = "Handoffs and Approvals" - "receipts-and-user-participation" = "Receipts and User Participation" - "failure-degradation-and-closure" = "Failure, Degradation, and Closure" - "process-gaps" = "Process Gaps" - "architecture-level-components" = "Architecture-Level Components" - "package-boundary-intent" = "Package Boundary Intent" - "contracts-and-artifacts" = "Contracts and Artifacts" - "dependency-rules" = "Dependency Rules" - "dependency-matrix" = "Dependency Matrix" - "development-view-gaps" = "Development View Gaps" - "deployment-and-hosting-boundaries" = "Deployment and Hosting Boundaries" - "external-system-collaboration" = "External System Collaboration" - "fact-sources-and-observability" = "Fact Sources and Observability" - "operations-and-release-boundaries" = "Operations and Release Boundaries" - "physical-view-gaps" = "Physical View Gaps" -} - -$requiredSections = @{ - "architecture-synthesis" = @("view-index", "architecture-intent", "central-design-forces", "primary-tradeoffs", "stable-boundaries", "change-axes", "anti-patterns", "cross-view-architecture-model", "key-architecture-conclusions", "cross-cutting-constraints", "open-risks-and-review-triggers") - "scenario-view" = @("architecture-intent", "core-tensions", "stable-boundaries", "change-axes", "invariants", "non-goals-anti-patterns", "actors-and-participants", "use-cases", "scenario-paths", "acceptance-semantics", "source-traceability", "scenario-gaps") - "logical-view" = @("architecture-intent", "core-tensions", "stable-boundaries", "change-axes", "invariants", "non-goals-anti-patterns", "capability-boundaries", "domain-objects-and-relationships", "state-and-lifecycle", "logical-decisions", "source-traceability", "logical-gaps") - "process-view" = @("architecture-intent", "core-tensions", "stable-boundaries", "change-axes", "invariants", "non-goals-anti-patterns", "main-runtime-links", "handoffs-and-approvals", "receipts-and-user-participation", "failure-degradation-and-closure", "source-traceability", "process-gaps") - "development-view" = @("architecture-intent", "core-tensions", "stable-boundaries", "change-axes", "invariants", "non-goals-anti-patterns", "architecture-level-components", "package-boundary-intent", "contracts-and-artifacts", "dependency-rules", "dependency-matrix", "source-traceability", "development-view-gaps") - "physical-view" = @("architecture-intent", "core-tensions", "stable-boundaries", "change-axes", "invariants", "non-goals-anti-patterns", "deployment-and-hosting-boundaries", "external-system-collaboration", "fact-sources-and-observability", "operations-and-release-boundaries", "source-traceability", "physical-view-gaps") -} - -foreach ($artifact in $files.Keys) { - $file = $files[$artifact] - if (-not (Test-Path -LiteralPath $file -PathType Leaf)) { - Add-Blocker -Code "ARCH_ARTIFACT_MISSING" -Artifact $artifact -Message "Required architecture artifact is missing: $file" - continue - } - - $lines = Get-Content -LiteralPath $file + "required-constraints" = "Required Constraints" + "architecture-decisions-already-made" = "Architecture Decisions Already Made" + "allowed-extension-points" = "Allowed Extension Points" + "prohibited-plan-directions" = "Prohibited Plan Directions" + "open-architecture-questions" = "Open Architecture Questions" + "plan-review-checklist" = "Plan Review Checklist" +} + +$requiredSections = @( + "architecture-intent", + "planning-scope-rules", + "capability-boundaries", + "required-constraints", + "architecture-decisions-already-made", + "allowed-extension-points", + "prohibited-plan-directions", + "open-architecture-questions", + "plan-review-checklist" +) + +if (-not (Test-Path -LiteralPath $archFile -PathType Leaf)) { + Add-Blocker -Code "ARCH_ARTIFACT_MISSING" -Artifact $artifact -Message "Required architecture planning contract is missing: $archFile" +} else { + $lines = Get-Content -LiteralPath $archFile $content = $lines -join "`n" if ($content -match 'NEEDS ARCH UPDATE|NEEDS REPO FACTS UPDATE') { - Add-Blocker -Code "ARCH_PLACEHOLDER_PRESENT" -Artifact $artifact -Message "Artifact still contains placeholder update markers." + Add-Blocker -Code "ARCH_PLACEHOLDER_PRESENT" -Artifact $artifact -Message "Planning contract still contains placeholder update markers." } - foreach ($section in $requiredSections[$artifact]) { + if (Test-UnsupportedConclusion -Content $content) { + Add-Blocker -Code "ARCH_UNSUPPORTED_CONCLUSION" -Artifact $artifact -Message "Planning contract contains implementation-level conclusions that belong to downstream planning or implementation." + } + + foreach ($section in $requiredSections) { $heading = $sectionHeadings[$section] if (-not (Test-SectionExists -Lines $lines -Heading $heading)) { - if ($section -eq "dependency-matrix") { - Add-Blocker -Code "ARCH_DEPENDENCY_MATRIX_MISSING" -Artifact $artifact -SectionId $section -Message "Development View must include Dependency Matrix." - } else { - Add-Blocker -Code "ARCH_REQUIRED_SECTION_MISSING" -Artifact $artifact -SectionId $section -Message "Required section is missing." - } + Add-Blocker -Code "ARCH_REQUIRED_SECTION_MISSING" -Artifact $artifact -SectionId $section -Message "Required planning contract section is missing." continue } + if (-not (Test-SectionHasContent -Lines $lines -Heading $heading)) { - if ($section -eq "dependency-matrix") { - Add-Blocker -Code "ARCH_DEPENDENCY_MATRIX_EMPTY" -Artifact $artifact -SectionId $section -Message "Dependency Matrix has no supported records." - } elseif ($section -eq "source-traceability") { - Add-Blocker -Code "ARCH_TRACEABILITY_MISSING" -Artifact $artifact -SectionId $section -Message "Source Traceability has no supported records." + if ($section -eq "planning-scope-rules") { + Add-Blocker -Code "ARCH_PLANNING_SCOPE_RULES_MISSING" -Artifact $artifact -SectionId $section -Message "Planning Scope Rules has no supported records." + } elseif ($section -eq "capability-boundaries") { + Add-Blocker -Code "ARCH_CAPABILITY_BOUNDARIES_MISSING" -Artifact $artifact -SectionId $section -Message "Capability Boundaries has no supported records." + } elseif ($section -eq "plan-review-checklist") { + Add-Blocker -Code "ARCH_PLAN_REVIEW_CHECKLIST_MISSING" -Artifact $artifact -SectionId $section -Message "Plan Review Checklist has no supported records." } else { - Add-Blocker -Code "ARCH_REQUIRED_SECTION_EMPTY" -Artifact $artifact -SectionId $section -Message "Required section has no supported records." + Add-Blocker -Code "ARCH_REQUIRED_SECTION_EMPTY" -Artifact $artifact -SectionId $section -Message "Required planning contract section has no supported records." } } } + + if ( + (Test-SectionExists -Lines $lines -Heading $sectionHeadings["architecture-intent"]) -and + (Test-IntentHasMissingSource -Lines $lines) + ) { + Add-Blocker -Code "ARCH_SOURCE_MISSING" -Artifact $artifact -SectionId "architecture-intent" -Message "Architecture Intent is missing Source / Basis." + } + + $sourceSections = @( + "planning-scope-rules", + "capability-boundaries", + "required-constraints", + "architecture-decisions-already-made", + "allowed-extension-points", + "prohibited-plan-directions", + "open-architecture-questions", + "plan-review-checklist" + ) + + foreach ($section in $sourceSections) { + $heading = $sectionHeadings[$section] + if ( + (Test-SectionExists -Lines $lines -Heading $heading) -and + (Test-SectionHasMissingSource -Lines $lines -Heading $heading) + ) { + Add-Blocker -Code "ARCH_SOURCE_MISSING" -Artifact $artifact -SectionId $section -Message "Rule-bearing section has a row without supported Source / Basis." + } + } + + if ( + (Test-SectionExists -Lines $lines -Heading $sectionHeadings["open-architecture-questions"]) -and + (Test-OpenQuestionsHaveInvalidStatus -Lines $lines -Heading $sectionHeadings["open-architecture-questions"]) + ) { + Add-Blocker -Code "ARCH_OPEN_QUESTION_STATUS_INVALID" -Artifact $artifact -SectionId "open-architecture-questions" -Message "Open Architecture Questions must use BLOCKS_PLAN or CAN_PROCEED_WITH_GUARDRAIL." + } + + if ( + (Test-SectionExists -Lines $lines -Heading $sectionHeadings["required-constraints"]) -and + (Test-SectionExists -Lines $lines -Heading $sectionHeadings["architecture-decisions-already-made"]) -and + -not (Test-SectionHasContent -Lines $lines -Heading $sectionHeadings["required-constraints"]) -and + -not (Test-SectionHasContent -Lines $lines -Heading $sectionHeadings["architecture-decisions-already-made"]) + ) { + Add-Blocker -Code "ARCH_CONSTRAINTS_OR_DECISIONS_MISSING" -Artifact $artifact -SectionId "required-constraints" -Message "Required Constraints and Architecture Decisions Already Made are both empty." + } } +$planningGate = if ($blockers.Count -eq 0) { "USABLE" } else { "BLOCKED" } $readyGate = if ($blockers.Count -eq 0) { "PASS" } else { "BLOCKED" } $result = [PSCustomObject]@{ + planning_gate = $planningGate ready_gate = $readyGate blockers = $blockers } @@ -227,6 +352,7 @@ $result = [PSCustomObject]@{ if ($Json) { $result | ConvertTo-Json -Compress -Depth 5 } else { + Write-Output "planning_gate: $planningGate" Write-Output "ready_gate: $readyGate" foreach ($blocker in $blockers) { Write-Output ($blocker | ConvertTo-Json -Compress) diff --git a/extensions/arch/templates/architecture-development-template.md b/extensions/arch/templates/architecture-development-template.md deleted file mode 100644 index 4761d77a29..0000000000 --- a/extensions/arch/templates/architecture-development-template.md +++ /dev/null @@ -1,81 +0,0 @@ -# Development View - -**Input**: `.specify/memory/architecture-logical-view.md`, `.specify/memory/architecture-process-view.md`; reverse generation may also use development-owned repository-first dependency matrix summaries - -**Purpose**: Architecture-level components, package boundary intent, contract/artifact semantics, dependency rules, and a required dependency matrix from logical and process views. Dependency matrix signals belong here as development governance evidence; they are not an independent architecture view. - -## Architecture Intent - -[Component, package, contract, or dependency decision and source.] - -## Core Tensions - -| Tension | Chosen Architectural Direction | Development Consequence | -|---------|----------------------------|-------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Stable Boundaries - -| Boundary | Must Remain Stable Because | Excluded Responsibility / Scope | -|----------|----------------------------|-------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Change Axes - -| Expected Change | Isolation Mechanism / Boundary Rule | Development Impact | -|-----------------|-------------|--------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Invariants - -| Invariant | Source Boundary / Contract / Dependency Rule | Risk If Violated | -|-----------|----------------------------------------------|------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Non-goals / Anti-patterns - -| Non-goal / Anti-pattern | Why It Is Out of Scope or Harmful | -|-------------------------|-----------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Architecture-Level Components - -| Component / Capability Package | Responsibility | Input / Output Boundary | Collaborators | Excluded Responsibility / Scope | Source Reference | -|--------------------------------|----------------|-------------------------|---------------|--------------------------|----------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Package Boundary Intent - -| Package / Boundary | Abstraction Level | Owned Concepts | May Depend On | Must Not Depend On | Evolution Rule | -|--------------------|-------------------|----------------|---------------|--------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Contracts and Artifacts - -| Contract / Artifact | Semantics | Producer | Consumer | Lifecycle | Architecture Consequence | -|---------------------|-----------|----------|----------|-----------|--------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Dependency Rules - -| Rule | Allowed Direction | Forbidden Direction | Reason | Risk If Violated | -|------|-------------------|---------------------|--------|------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Dependency Matrix - -| From Boundary / Component | To Boundary / Component | Allowed? | Constraint / Rule Source | Architecture Consequence | -|---------------------------|-------------------------|----------|--------------------------|--------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Source Traceability - -| Architecture Conclusion | Source Type | Source Reference | Confidence | -|-------------------------|-------------|------------------|------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Development View Gaps - -| Gap | Affected Component / Boundary | Why It Matters | -|-----|-------------------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | diff --git a/extensions/arch/templates/architecture-logical-template.md b/extensions/arch/templates/architecture-logical-template.md deleted file mode 100644 index 22d7de1439..0000000000 --- a/extensions/arch/templates/architecture-logical-template.md +++ /dev/null @@ -1,75 +0,0 @@ -# Logical View - -**Input**: `.specify/memory/architecture-scenario-view.md` - -**Purpose**: Capability boundaries, domain objects, states, relationships, and invariants from the scenario view. - -## Architecture Intent - -[Logical authority, boundary, or lifecycle decision and source.] - -## Core Tensions - -| Tension | Chosen Architectural Direction | Logical Consequence | -|---------|----------------------------|---------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Stable Boundaries - -| Boundary | Must Remain Stable Because | Excluded Responsibility / Scope | -|----------|----------------------------|-------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Change Axes - -| Expected Change | Isolation Mechanism / Boundary Rule | Logical Impact | -|-----------------|-------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Invariants - -| Invariant | Source Scenario / Object / State | Risk If Violated | -|-----------|----------------------------------|------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Non-goals / Anti-patterns - -| Non-goal / Anti-pattern | Why It Is Out of Scope or Harmful | -|-------------------------|-----------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Capability Boundaries - -| Capability / Boundary | Responsibility | Input | Output | Excluded Responsibility / Scope | Scenario Source | -|-----------------------|----------------|-------|--------|--------------------------|-----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Domain Objects and Relationships - -| Object | Meaning | Owning Capability | Key Relationships | Fact Source | Invariants | -|--------|---------|-------------------|-------------------|-------------|------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## State and Lifecycle - -| Object / Flow | State | Entered When | Exited When | Forbidden Transition | Responsible Boundary | -|---------------|-------|--------------|-------------|----------------------|----------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Logical Decisions - -| Decision | Scope | Owner / Boundary | Affected Objects or Flows | Consequence | -|----------|-------|------------------|---------------------------|-------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Source Traceability - -| Architecture Conclusion | Source Type | Source Reference | Confidence | -|-------------------------|-------------|------------------|------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Logical Gaps - -| Gap | Affected Capability / Object | Why It Matters | -|-----|------------------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | diff --git a/extensions/arch/templates/architecture-physical-template.md b/extensions/arch/templates/architecture-physical-template.md deleted file mode 100644 index 335cb8dbe0..0000000000 --- a/extensions/arch/templates/architecture-physical-template.md +++ /dev/null @@ -1,75 +0,0 @@ -# Physical View - -**Input**: `.specify/memory/architecture-process-view.md`, `.specify/memory/architecture-development-view.md` - -**Purpose**: Deployment, hosting, external system, fact-source, observability, and operational boundaries from process and development views. - -## Architecture Intent - -[Deployment, fact-source, operational, or external-boundary decision and source.] - -## Core Tensions - -| Tension | Chosen Architectural Direction | Physical Consequence | -|---------|----------------------------|----------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Stable Boundaries - -| Boundary | Must Remain Stable Because | Excluded Responsibility / Scope | -|----------|----------------------------|---------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Change Axes - -| Expected Change | Isolation Mechanism / Boundary Rule | Physical Impact | -|-----------------|-------------|-----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Invariants - -| Invariant | Source Deployment / External / Fact Boundary | Risk If Violated | -|-----------|----------------------------------------------|------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Non-goals / Anti-patterns - -| Non-goal / Anti-pattern | Why It Is Out of Scope or Harmful | -|-------------------------|-----------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Deployment and Hosting Boundaries - -| Runtime / Hosting Unit | Carries | Boundary | Depends On | Release / Migration Impact | -|------------------------|---------|----------|------------|----------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## External System Collaboration - -| External System | Purpose | Exchanged Content | Authoritative Fact | Failure Impact | Isolation / Substitute Boundary | -|-----------------|---------|-------------------|--------------------|----------------|---------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Fact Sources and Observability - -| Fact / Event | Authoritative Source | Observable Location | Consumers | Traceability Requirement | -|--------------|----------------------|---------------------|-----------|--------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Operations and Release Boundaries - -| Operational Concern | Responsible Boundary | Trigger | Affected Views | Review Trigger / Architecture Consequence | -|---------------------|----------------------|---------|----------------|--------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Source Traceability - -| Architecture Conclusion | Source Type | Source Reference | Confidence | -|-------------------------|-------------|------------------|------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Physical View Gaps - -| Gap | Affected Deployment / External Boundary | Why It Matters | -|-----|-----------------------------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | diff --git a/extensions/arch/templates/architecture-process-template.md b/extensions/arch/templates/architecture-process-template.md deleted file mode 100644 index 3de19c8ab8..0000000000 --- a/extensions/arch/templates/architecture-process-template.md +++ /dev/null @@ -1,75 +0,0 @@ -# Process View - -**Input**: `.specify/memory/architecture-scenario-view.md`, `.specify/memory/architecture-logical-view.md` - -**Purpose**: Runtime collaboration, handoffs, approvals, receipts, state advancement, and failure closure from scenario paths and logical boundaries. - -## Architecture Intent - -[Runtime collaboration, handoff, or failure-closure decision and source.] - -## Core Tensions - -| Tension | Chosen Architectural Direction | Process Consequence | -|---------|----------------------------|---------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Stable Boundaries - -| Boundary | Must Remain Stable Because | Excluded Responsibility / Scope | -|----------|----------------------------|-----------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Change Axes - -| Expected Change | Isolation Mechanism / Boundary Rule | Process Impact | -|-----------------|-------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Invariants - -| Invariant | Source Scenario / Runtime Link | Risk If Violated | -|-----------|--------------------------------|------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Non-goals / Anti-patterns - -| Non-goal / Anti-pattern | Why It Is Out of Scope or Harmful | -|-------------------------|-----------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Main Runtime Links - -| Runtime Link | Trigger | Source | Target | Transferred Content / Fact | Completion Condition | -|--------------|---------|--------|--------|----------------------------|----------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Handoffs and Approvals - -| Handoff / Approval | From | To | Meaning | Accepted Path | Rejected / Returned Path | -|--------------------|------|----|---------|---------------|--------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Receipts and User Participation - -| Receipt / Participation Point | Sender | Receiver | Content | User Action | Architecture Consequence | -|-------------------------------|--------|----------|---------|-------------|--------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Failure, Degradation, and Closure - -| Failure / Branch | Detection Boundary | Responsible Boundary | Degradation or Compensation | User-Visible Result | Closure Condition | -|------------------|--------------------|----------------------|-----------------------------|---------------------|-------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Source Traceability - -| Architecture Conclusion | Source Type | Source Reference | Confidence | -|-------------------------|-------------|------------------|------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Process Gaps - -| Gap | Affected Runtime Link / Scenario | Why It Matters | -|-----|----------------------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | diff --git a/extensions/arch/templates/architecture-repo-facts-template.md b/extensions/arch/templates/architecture-repo-facts-template.md deleted file mode 100644 index 03f61df769..0000000000 --- a/extensions/arch/templates/architecture-repo-facts-template.md +++ /dev/null @@ -1,93 +0,0 @@ -# Architecture Repo Facts: [PROJECT] - -**Purpose**: Observable repository facts that support reverse generation of the project-level 4+1 architecture artifacts. - -**Scope**: Observable repository evidence for architecture reasoning, not an implementation audit report. - -## Repository Identity - -| Fact | Evidence Source | Confidence | Architecture Relevance | -|------|-----------------|------------|--------------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Entry Points - -| Entry Point | Type | Evidence Source | Observed Responsibility | Supported Scenario | -|-------------|------|-----------------|--------------------------|--------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## User-Visible Behaviors - -| Behavior | Evidence Source | Actor / Trigger | Observable Outcome | Supported Use Case | -|----------|-----------------|-----------------|--------------------|--------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## System Boundaries - -| Boundary | Evidence Source | Inbound Interaction | Outbound Interaction | Not Proven | -|----------|-----------------|---------------------|----------------------|------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Data and State Clues - -| Fact / Entity | Evidence Source | Observed Lifecycle Clue | Fact Source | Not Proven | -|---------------|-----------------|-------------------------|-------------|------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Runtime and Process Clues - -| Runtime Fact | Evidence Source | Trigger / Handoff | Failure or Retry Clue | Not Proven | -|--------------|-----------------|-------------------|-----------------------|------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Development Structure Clues - -| Module / Package Area | Evidence Source | Observed Responsibility | Dependency Clue | Boundary Risk | -|-----------------------|-----------------|--------------------------|-----------------|---------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Repository-First Projection - -Repository-first signals relevant to architecture evidence. - -### Build Manifest Detection - -| Ecosystem | Manifest Evidence | Detection Status | Runtime Surface Notes | -|-----------|-------------------|------------------|-----------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -### First-Party Module Edges - -| From Module | To Module | Evidence Source | Observed Direction | Architecture Boundary Meaning | -|-------------|-----------|-----------------|--------------------|-------------------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -### Module Invocation Governance - -| Rule Source | Allowed Direction | Forbidden Direction | Architecture Constraint | Risk If Violated | -|-------------|-------------------|---------------------|-------------------------|------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -### Development-Owned Dependency Governance Signals - -| Signal Source | Dependency / Concern | Signal Type | Development Boundary / Architecture Boundary Meaning | Architecture Review Trigger | -|---------------|----------------------|-------------|------------------------------------------------------|-----------------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Physical / Deployment Clues - -| Deployment Fact | Evidence Source | Environment / External System | Operational Constraint | Not Proven | -|-----------------|-----------------|-------------------------------|------------------------|------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Git History Signals - -| Signal | Evidence Source | Architecture Meaning | Confidence | Review Trigger | -|--------|-----------------|----------------------|------------|----------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | - -## Evidence Gaps - -| Gap | Affected View | Why It Blocks Architecture Conclusion | -|-----|---------------|----------------------------------------| -| NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | NEEDS REPO FACTS UPDATE | diff --git a/extensions/arch/templates/architecture-scenario-template.md b/extensions/arch/templates/architecture-scenario-template.md deleted file mode 100644 index 4055221481..0000000000 --- a/extensions/arch/templates/architecture-scenario-template.md +++ /dev/null @@ -1,73 +0,0 @@ -# Scenario View - -**Purpose**: Use-case semantics for the architecture workflow. This view is the source for the logical, process, development, and physical views. - -## Architecture Intent - -[Scenario-level decision, boundary, and source.] - -## Core Tensions - -| Tension | Chosen Architectural Direction | Scenario Consequence | -|---------|----------------------------|----------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Stable Boundaries - -| Boundary | Must Remain Stable Because | Excluded Responsibility / Scope | -|----------|----------------------------|---------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Change Axes - -| Expected Change | Isolation Mechanism / Boundary Rule | Scenario Impact | -|-----------------|-------------|-----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Invariants - -| Invariant | Scenario Evidence | Risk If Violated | -|-----------|-------------------|------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Non-goals / Anti-patterns - -| Non-goal / Anti-pattern | Why It Is Out of Scope or Harmful | -|-------------------------|-----------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Actors and Participants - -| Actor / Participant | Goal | Responsibility | Boundary | -|---------------------|------|----------------|----------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Use Cases - -| Use Case | Actor | Goal | Preconditions | Scope Boundary | -|----------|-------|------|---------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Scenario Paths - -| Scenario | Main Path | Successful Outcome | Alternative / Failure Branches | -|----------|-----------|--------------------|--------------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Acceptance Semantics - -| Acceptance Scenario | Observable Result | Must Hold | Not Covered | -|---------------------|-------------------|-----------|-------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Source Traceability - -| Architecture Conclusion | Source Type | Source Reference | Confidence | -|-------------------------|-------------|------------------|------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | - -## Scenario Gaps - -| Gap | Affected Scenario | Why It Matters | -|-----|-------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | diff --git a/extensions/arch/templates/architecture-template.md b/extensions/arch/templates/architecture-template.md index 048eef30ee..aab4073764 100644 --- a/extensions/arch/templates/architecture-template.md +++ b/extensions/arch/templates/architecture-template.md @@ -1,76 +1,59 @@ -# Architecture Synthesis: [PROJECT] +# Architecture Planning Contract: [PROJECT] -**Input Views**: -- Scenario: `.specify/memory/architecture-scenario-view.md` -- Logical: `.specify/memory/architecture-logical-view.md` -- Process: `.specify/memory/architecture-process-view.md` -- Development: `.specify/memory/architecture-development-view.md` -- Physical: `.specify/memory/architecture-physical-view.md` +**Purpose**: Guide downstream Spec Kit `/plan` work with architecture constraints, boundaries, decisions, and review triggers. -## View Index - -| View | File | Purpose | Current Status | -|------|------|---------|----------------| -| Scenario | `.specify/memory/architecture-scenario-view.md` | Use-case actor, path, branch, and acceptance semantics | NEEDS ARCH UPDATE | -| Logical | `.specify/memory/architecture-logical-view.md` | Capability boundaries, domain objects, states, and invariants | NEEDS ARCH UPDATE | -| Process | `.specify/memory/architecture-process-view.md` | Runtime links, handoffs, approvals, receipts, failure closure | NEEDS ARCH UPDATE | -| Development | `.specify/memory/architecture-development-view.md` | Architecture-level components, package boundaries, contracts, dependencies, dependency matrix | NEEDS ARCH UPDATE | -| Physical | `.specify/memory/architecture-physical-view.md` | Deployment, external systems, fact sources, observability, operations | NEEDS ARCH UPDATE | +**Consumer**: Feature planning agents and human reviewers. ## Architecture Intent -[Cross-view architecture decision, affected boundary, and input views.] - -## Central Design Forces +[Project-level architecture intent that the downstream plan must preserve.] -[Primary scenario flow, authority boundary, fact-source model, collaboration model, deployment constraint, or failure-closure model that connects the five views.] +**Source / Basis**: NEEDS ARCH UPDATE -## Primary Tradeoffs +## Planning Scope Rules -| Tradeoff | Chosen Direction | Consequence | Revisit When | -|----------|------------------|-------------|--------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | +| Rule | Applies When | Plan Must Do | Plan Must Not Do | Source / Basis | +|------|--------------|--------------|------------------|----------------| +| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -## Stable Boundaries +## Capability Boundaries -| Boundary | Affected Views | Must Remain Stable Because | Forbidden Crossing | -|----------|----------------|----------------------------|--------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | +| Capability / Boundary | Owns | Does Not Own | Planning Implication | Source / Basis | +|-----------------------|------|--------------|----------------------|----------------| +| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -## Change Axes +## Required Constraints -| Expected Change | Isolation Mechanism / Boundary Rule | Affected Views | Architecture Consequence | -|-----------------|-------------|----------------|--------------------------| +| Constraint | Applies To | Plan Enforcement | Source / Basis | +|------------|------------|------------------|----------------| | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -## Anti-patterns - -| Anti-pattern | Why It Violates Intent | Affected Views | -|--------------|------------------------|----------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | +## Architecture Decisions Already Made -## Cross-View Architecture Model +| Decision | Plan Consequence | Revisit Trigger | Source / Basis | +|----------|------------------|-----------------|----------------| +| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -Cross-view mappings between view-specific concepts, constraints, dependencies, and guardrails. +## Allowed Extension Points -| Architecture Concept | Scenario Meaning | Logical Interpretation | Runtime Role | Development Boundary | Physical Constraint | Architecture Constraint | -|----------------------|------------------|------------------------|--------------|----------------------|---------------------|---------------------------| -| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | +| Extension Point | Intended Use | Required Review If | Source / Basis | +|-----------------|--------------|--------------------|----------------| +| NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -## Key Architecture Conclusions +## Prohibited Plan Directions -| Conclusion | Affected Views | Boundary/Owner | Consequence | -|------------|----------------|----------------|-------------| +| Anti-pattern | Why Forbidden | Safer Direction | Source / Basis | +|--------------|---------------|-----------------|----------------| | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -## Cross-Cutting Constraints +## Open Architecture Questions -| Constraint | Source | Affected Views | Scope | Architecture Consequence | -|------------|--------|----------------|-------|--------------------------| +| Question | Plan Impact | Required Clarification | Planning Status | Source / Basis | +|----------|-------------|------------------------|-----------------|----------------| | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | -## Open Risks and Review Triggers +## Plan Review Checklist -| Risk or Trigger | Missing Evidence / Change Condition | Affected Views | Required Architecture Review | -|-----------------|-------------------------------------|----------------|------------------------------| +| Check | Pass Criteria | Blocking Failure | Source / Basis | +|-------|---------------|------------------|----------------| | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | NEEDS ARCH UPDATE | diff --git a/extensions/arch/tests/repository-first-contract.sh b/extensions/arch/tests/repository-first-contract.sh index 6a45f06282..43de52110d 100755 --- a/extensions/arch/tests/repository-first-contract.sh +++ b/extensions/arch/tests/repository-first-contract.sh @@ -14,133 +14,95 @@ else } fi -views=(scenario logical process development physical) - -search "name: speckit\\.arch\\.full-generate" extension.yml >/dev/null -search "file: commands/speckit\\.arch\\.full-generate\\.md" extension.yml >/dev/null -test -f "commands/speckit.arch.full-generate.md" -search 'Generate all 4\+1 architecture views|Write only `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, and `ARCH_FILE`|Do not read, populate, or update `REPO_FACTS_FILE`|Generation Order|Synthesis Readiness|all five view paths' "commands/speckit.arch.full-generate.md" >/dev/null -search "Generation Order" "commands/speckit.arch.full-generate.md" >/dev/null -search "Synthesis Readiness" "commands/speckit.arch.full-generate.md" >/dev/null -search "all five view paths" "commands/speckit.arch.full-generate.md" >/dev/null -search "ready_gate: PASS" "commands/speckit.arch.full-generate.md" >/dev/null -search "Structured Contract" "commands/speckit.arch.full-generate.md" >/dev/null -search "ARCH_SCHEMA_FILE" "commands/speckit.arch.full-generate.md" >/dev/null -search 'required `Dependency Matrix` section' "commands/speckit.arch.full-generate.md" >/dev/null - -search "name: speckit\\.arch\\.full-reverse" extension.yml >/dev/null -search "file: commands/speckit\\.arch\\.full-reverse\\.md" extension.yml >/dev/null -test -f "commands/speckit.arch.full-reverse.md" -search 'Reverse-generate all 4\+1 architecture views|Write only `REPO_FACTS_FILE`, `SCENARIO_VIEW`, `LOGICAL_VIEW`, `PROCESS_VIEW`, `DEVELOPMENT_VIEW`, `PHYSICAL_VIEW`, and `ARCH_FILE`|Repository-First Inputs|Repo Facts Merge Rule|Reverse Generation Order|Synthesis Readiness|all five view paths' "commands/speckit.arch.full-reverse.md" >/dev/null -search "Reverse Generation Order" "commands/speckit.arch.full-reverse.md" >/dev/null -search "Repo Facts Merge Rule" "commands/speckit.arch.full-reverse.md" >/dev/null -search "Repo Facts Evidence Rules" "commands/speckit.arch.full-reverse.md" >/dev/null -search "Synthesis Readiness" "commands/speckit.arch.full-reverse.md" >/dev/null -search "all five view paths" "commands/speckit.arch.full-reverse.md" >/dev/null -search "ready_gate: PASS" "commands/speckit.arch.full-reverse.md" >/dev/null -search "Structured Contract" "commands/speckit.arch.full-reverse.md" >/dev/null -search "ARCH_SCHEMA_FILE" "commands/speckit.arch.full-reverse.md" >/dev/null -search 'required `Dependency Matrix` section' "commands/speckit.arch.full-reverse.md" >/dev/null -search "ARCH_GIT_HISTORY_ONLY" "commands/speckit.arch.full-reverse.md" >/dev/null -search "ARCH_UNSUPPORTED_CONCLUSION" "commands/speckit.arch.full-reverse.md" >/dev/null - -for view in "${views[@]}"; do - search "name: speckit\\.arch\\.${view}-generate" extension.yml >/dev/null - search "file: commands/speckit\\.arch\\.${view}-generate\\.md" extension.yml >/dev/null - test -f "commands/speckit.arch.${view}-generate.md" - search 'Target view|Write only|Do not read, populate, or update `REPO_FACTS_FILE`|Setup Bootstrap|Synthesis Readiness|all five view paths' "commands/speckit.arch.${view}-generate.md" >/dev/null - search "Setup Bootstrap" "commands/speckit.arch.${view}-generate.md" >/dev/null - search "Synthesis Readiness" "commands/speckit.arch.${view}-generate.md" >/dev/null - search "all five view paths" "commands/speckit.arch.${view}-generate.md" >/dev/null - search "ready_gate: PASS" "commands/speckit.arch.${view}-generate.md" >/dev/null - search "Structured Contract" "commands/speckit.arch.${view}-generate.md" >/dev/null - search "ARCH_SCHEMA_FILE" "commands/speckit.arch.${view}-generate.md" >/dev/null - - search "name: speckit\\.arch\\.${view}-reverse" extension.yml >/dev/null - search "file: commands/speckit\\.arch\\.${view}-reverse\\.md" extension.yml >/dev/null - test -f "commands/speckit.arch.${view}-reverse.md" - search "Evidence layer|Repository-First Inputs|REPO_FACTS_FILE|Repo Facts Merge Rule|Synthesis Readiness|all five view paths" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "Repo Facts Merge Rule" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "Repo Facts Evidence Rules" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "Synthesis Readiness" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "all five view paths" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "ARCH_GIT_HISTORY_ONLY" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "ARCH_UNSUPPORTED_CONCLUSION" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "Structured Contract" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "ARCH_SCHEMA_FILE" "commands/speckit.arch.${view}-reverse.md" >/dev/null - - if [[ "$view" == "development" ]]; then - search 'required dependency matrix' "commands/speckit.arch.${view}-generate.md" >/dev/null - search 'required `Dependency Matrix` section' "commands/speckit.arch.${view}-generate.md" >/dev/null - search 'section id `dependency-matrix`' "commands/speckit.arch.${view}-generate.md" >/dev/null - search "omits the required .*Dependency Matrix" "commands/speckit.arch.${view}-generate.md" >/dev/null - search "required dependency matrix" extension.yml >/dev/null - search "development-owned dependency governance evidence" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search 'required `Dependency Matrix` section' "commands/speckit.arch.${view}-reverse.md" >/dev/null - search 'section id `dependency-matrix`' "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "architecture-level constraints" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "not as an independent architecture view" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "ARCH_REPO_FIRST_MATRIX_MISUSED" "commands/speckit.arch.${view}-reverse.md" >/dev/null - else - search "must not consume dependency matrices directly" "commands/speckit.arch.${view}-reverse.md" >/dev/null - search 'use development-view dependency conclusions only after `DEVELOPMENT_VIEW` is synthesis-ready' "commands/speckit.arch.${view}-reverse.md" >/dev/null - search "ARCH_REPO_FIRST_MATRIX_MISUSED" "commands/speckit.arch.${view}-reverse.md" >/dev/null - fi +search "name: speckit\\.arch\\.generate" extension.yml >/dev/null +search "file: commands/speckit\\.arch\\.generate\\.md" extension.yml >/dev/null +search "name: speckit\\.arch\\.reverse" extension.yml >/dev/null +search "file: commands/speckit\\.arch\\.reverse\\.md" extension.yml >/dev/null +test -f "commands/speckit.arch.generate.md" +test -f "commands/speckit.arch.reverse.md" + +registered_count=$(search "name: speckit\\.arch\\." extension.yml | wc -l | tr -d '[:space:]') +test "$registered_count" = "2" + +if search "name: speckit\\.arch\\.(full|scenario|logical|process|development|physical)-" extension.yml >/dev/null; then + echo "legacy 4+1 commands must not be registered by default" >&2 + exit 1 +fi - search "Source Traceability" "templates/architecture-${view}-template.md" >/dev/null -done +search "Architecture Planning Contract" README.md >/dev/null +search "Commands count: 2" CATALOG-SUBMISSION.md >/dev/null +search "Internal Reasoning Model" README.md >/dev/null +search "4\\+1 as an internal reasoning lens" README.md >/dev/null +search "speckit\\.arch\\.generate" README.md >/dev/null +search "speckit\\.arch\\.reverse" README.md >/dev/null +search "planning_gate: USABLE" README.md >/dev/null +search "only generated architecture artifact" CATALOG-SUBMISSION.md >/dev/null +search "Architecture Planning Contract" templates/architecture-template.md >/dev/null +search "## Planning Scope Rules" templates/architecture-template.md >/dev/null +search "## Capability Boundaries" templates/architecture-template.md >/dev/null +search "## Required Constraints" templates/architecture-template.md >/dev/null +search "## Architecture Decisions Already Made" templates/architecture-template.md >/dev/null +search "## Allowed Extension Points" templates/architecture-template.md >/dev/null +search "## Prohibited Plan Directions" templates/architecture-template.md >/dev/null +search "## Open Architecture Questions" templates/architecture-template.md >/dev/null +search "## Plan Review Checklist" templates/architecture-template.md >/dev/null +source_basis_count=$(search "Source / Basis" templates/architecture-template.md | wc -l | tr -d '[:space:]') +test "$source_basis_count" = "9" +search "Planning Status" templates/architecture-template.md >/dev/null -if search "name: speckit\\.arch\\.(generate|reverse)$|name: speckit\\.arch\\.[a-z]+\\.(generate|reverse)$" extension.yml >/dev/null; then - echo "legacy broad arch commands must not be registered" >&2 +search '"architecture-planning-contract"' schemas/architecture-artifacts.schema.json >/dev/null +if search '"repo-facts"' schemas/architecture-artifacts.schema.json >/dev/null; then + echo "schema must not expose secondary repo-facts artifacts" >&2 exit 1 fi +search '"planningGate"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_PLANNING_SCOPE_RULES_MISSING"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_CAPABILITY_BOUNDARIES_MISSING"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_CONSTRAINTS_OR_DECISIONS_MISSING"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_PLAN_REVIEW_CHECKLIST_MISSING"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_UNSUPPORTED_CONCLUSION"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_SOURCE_MISSING"' schemas/architecture-artifacts.schema.json >/dev/null +search '"ARCH_OPEN_QUESTION_STATUS_INVALID"' schemas/architecture-artifacts.schema.json >/dev/null -search "Commands count: 12" CATALOG-SUBMISSION.md >/dev/null -search "speckit.arch.full-generate" README.md >/dev/null -search "speckit.arch.full-reverse" README.md >/dev/null -search "speckit.arch.scenario-generate" README.md >/dev/null -search "speckit.arch.physical-reverse" README.md >/dev/null -search "legacy .*speckit\\.arch\\.generate.*speckit\\.arch\\.reverse" README.md >/dev/null -search "Dependency matrices are primarily owned by the development view" README.md >/dev/null -search 'development-generate.*development-reverse.*Dependency Matrix' README.md >/dev/null -search "must not consume dependency matrices directly" README.md >/dev/null -search "dependency matrix interpretation owned by development-view governance" CHANGELOG.md >/dev/null -search "full-reverse" CHANGELOG.md >/dev/null -search 'Require the Development View commands to produce a `Dependency Matrix` section' CHANGELOG.md >/dev/null -search "dependency matrix interpretation owned by the development view" CATALOG-SUBMISSION.md >/dev/null -search "full-reverse" CATALOG-SUBMISSION.md >/dev/null -search 'Requires the Development View commands to produce a `Dependency Matrix` section' CATALOG-SUBMISSION.md >/dev/null -search "Repository-First Projection" templates/architecture-repo-facts-template.md >/dev/null -search "Module Invocation Governance" templates/architecture-repo-facts-template.md >/dev/null -search "Development-Owned Dependency Governance Signals" templates/architecture-repo-facts-template.md >/dev/null -search "Development Boundary / Architecture Boundary Meaning" templates/architecture-repo-facts-template.md >/dev/null -search "## Dependency Matrix" templates/architecture-development-template.md >/dev/null -search "From Boundary / Component" templates/architecture-development-template.md >/dev/null -test -f schemas/architecture-artifacts.schema.json -search '"artifactType"' schemas/architecture-artifacts.schema.json >/dev/null -search '"traceability"' schemas/architecture-artifacts.schema.json >/dev/null -search '"readiness"' schemas/architecture-artifacts.schema.json >/dev/null -search '"readyGate"' schemas/architecture-artifacts.schema.json >/dev/null -search '"blockers"' schemas/architecture-artifacts.schema.json >/dev/null -search '"ARCH_REQUIRED_SECTION_MISSING"' schemas/architecture-artifacts.schema.json >/dev/null -search '"ARCH_PLACEHOLDER_PRESENT"' schemas/architecture-artifacts.schema.json >/dev/null -search '"confidence"' schemas/architecture-artifacts.schema.json >/dev/null -search '"High"|\"Medium\"|\"Low\"' schemas/architecture-artifacts.schema.json >/dev/null -search '"const": "development-view"' schemas/architecture-artifacts.schema.json >/dev/null -search '"const": "dependency-matrix"' schemas/architecture-artifacts.schema.json >/dev/null -search '"minItems": 1' schemas/architecture-artifacts.schema.json >/dev/null +test -f scripts/bash/setup-arch.sh +test -x scripts/bash/setup-arch.sh test -f scripts/bash/validate-arch-artifacts.sh test -x scripts/bash/validate-arch-artifacts.sh +test -f scripts/powershell/setup-arch.ps1 test -f scripts/powershell/validate-arch-artifacts.ps1 -search "Preserve existing non-placeholder facts" commands/speckit.arch.development-reverse.md >/dev/null -search "must not be copied verbatim into 4\\+1 views|must not be copied verbatim into architecture views" commands/speckit.arch.development-reverse.md >/dev/null -search "ARCH_GIT_HISTORY_ONLY" commands/speckit.arch.development-reverse.md >/dev/null +search "SCENARIO_VIEW|LOGICAL_VIEW|PROCESS_VIEW|DEVELOPMENT_VIEW|PHYSICAL_VIEW|REPO_FACTS_FILE" scripts/bash/setup-arch.sh && { + echo "setup output must not require secondary artifact paths" >&2 + exit 1 +} +search "planning_gate" scripts/bash/validate-arch-artifacts.sh >/dev/null +search "ready_gate" scripts/bash/validate-arch-artifacts.sh >/dev/null +search "ARCH_UNSUPPORTED_CONCLUSION" scripts/bash/validate-arch-artifacts.sh >/dev/null +search "ARCH_SOURCE_MISSING" scripts/bash/validate-arch-artifacts.sh >/dev/null +search "ARCH_OPEN_QUESTION_STATUS_INVALID" scripts/bash/validate-arch-artifacts.sh >/dev/null +search "planning_gate" scripts/powershell/validate-arch-artifacts.ps1 >/dev/null +search "ready_gate" scripts/powershell/validate-arch-artifacts.ps1 >/dev/null +search "ARCH_UNSUPPORTED_CONCLUSION" scripts/powershell/validate-arch-artifacts.ps1 >/dev/null +search "ARCH_SOURCE_MISSING" scripts/powershell/validate-arch-artifacts.ps1 >/dev/null +search "ARCH_OPEN_QUESTION_STATUS_INVALID" scripts/powershell/validate-arch-artifacts.ps1 >/dev/null + +search 'Write only `ARCH_FILE`' commands/speckit.arch.generate.md >/dev/null +search 'Write only `ARCH_FILE`' commands/speckit.arch.reverse.md >/dev/null +search 'Do not create, update, or require `.specify/memory/architecture-repo-facts.md`' commands/speckit.arch.reverse.md >/dev/null +search "Do not create, update, or require separate 4\\+1 view files" commands/speckit.arch.generate.md >/dev/null +search "Do not create, update, or require separate 4\\+1 view files" commands/speckit.arch.reverse.md >/dev/null +search "plan-facing architecture rules" commands/speckit.arch.generate.md >/dev/null +search "plan-facing architecture rules" commands/speckit.arch.reverse.md >/dev/null if search "Evidence Rules|Prohibited Content|Move unsupported|One sentence|Identify the|List the|Record how|Do not treat|Record observable|projected into" templates >/dev/null; then echo "templates must not carry command execution rules" >&2 exit 1 fi +command_count=$(find commands -maxdepth 1 -type f -name 'speckit.arch.*.md' | wc -l | tr -d '[:space:]') +test "$command_count" = "2" +template_count=$(find templates -maxdepth 1 -type f -name 'architecture-*.md' | wc -l | tr -d '[:space:]') +test "$template_count" = "1" + tmpdir=$(mktemp -d) trap 'rm -rf "$tmpdir"' EXIT git -C "$tmpdir" init >/dev/null @@ -149,32 +111,143 @@ cp -R commands scripts templates schemas "$tmpdir/.specify/extensions/arch/" ( cd "$tmpdir" setup_json=$(.specify/extensions/arch/scripts/bash/setup-arch.sh --json) + printf '%s\n' "$setup_json" | search '"ARCH_FILE"' - >/dev/null printf '%s\n' "$setup_json" | search '"ARCH_SCHEMA_FILE"' - >/dev/null printf '%s\n' "$setup_json" | search '"ARCH_VALIDATOR_FILE"' - >/dev/null printf '%s\n' "$setup_json" | search '"ARCH_VALIDATOR_PS_FILE"' - >/dev/null + if printf '%s\n' "$setup_json" | search 'SCENARIO_VIEW|LOGICAL_VIEW|PROCESS_VIEW|DEVELOPMENT_VIEW|PHYSICAL_VIEW|REPO_FACTS_FILE' - >/dev/null; then + echo "setup JSON must not include secondary artifact paths" >&2 + exit 1 + fi + test -f .specify/memory/architecture.md - test -f .specify/memory/architecture-repo-facts.md - test -f .specify/memory/architecture-scenario-view.md - test -f .specify/memory/architecture-logical-view.md - test -f .specify/memory/architecture-process-view.md - test -f .specify/memory/architecture-development-view.md - search "## Dependency Matrix" .specify/memory/architecture-development-view.md >/dev/null - test -f .specify/memory/architecture-physical-view.md test -f .specify/extensions/arch/schemas/architecture-artifacts.schema.json test -f .specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh test -x .specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh test -f .specify/extensions/arch/scripts/powershell/validate-arch-artifacts.ps1 + find .specify/memory -maxdepth 1 -type f | wc -l | search '^[[:space:]]*1[[:space:]]*$' - >/dev/null + search "## Planning Scope Rules" .specify/memory/architecture.md >/dev/null + if validator_json=$(.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json); then - echo "placeholder architecture memory must block synthesis readiness" >&2 + echo "placeholder planning contract must block planning readiness" >&2 exit 1 fi + printf '%s\n' "$validator_json" | search '"planning_gate":"BLOCKED"' - >/dev/null printf '%s\n' "$validator_json" | search '"ready_gate":"BLOCKED"' - >/dev/null printf '%s\n' "$validator_json" | search '"ARCH_PLACEHOLDER_PRESENT"' - >/dev/null - printf 'custom sentinel\n' > .specify/memory/architecture-scenario-view.md - .specify/extensions/arch/scripts/bash/setup-arch.sh --json >/dev/null - search "custom sentinel" .specify/memory/architecture-scenario-view.md >/dev/null + write_contract() { + local intent="$1" + local scope_do="$2" + local scope_source="$3" + local question_status="$4" + + cat > .specify/memory/architecture.md </dev/null +| Constraint | Applies To | Plan Enforcement | Source / Basis | +|------------|------------|------------------|----------------| +| Single architecture artifact | Architecture memory | Plans consume architecture.md only | README.md Files Written | + +## Architecture Decisions Already Made + +| Decision | Plan Consequence | Revisit Trigger | Source / Basis | +|----------|------------------|-----------------|----------------| +| Use a plan-facing contract | Plans check guardrails before design | Contract no longer guides planning | README.md Planning Contract | + +## Allowed Extension Points + +| Extension Point | Intended Use | Required Review If | Source / Basis | +|-----------------|--------------|--------------------|----------------| +| Open questions | Capture unsupported architecture gaps | A gap blocks planning | Template section list | + +## Prohibited Plan Directions + +| Anti-pattern | Why Forbidden | Safer Direction | Source / Basis | +|--------------|---------------|-----------------|----------------| +| Treat missing architecture as permission | It hides decision gaps | Record a blocking question | README.md readiness notes | + +## Open Architecture Questions + +| Question | Plan Impact | Required Clarification | Planning Status | Source / Basis | +|----------|-------------|------------------------|-----------------|----------------| +| Which boundary owns future integrations? | Plan may need review before expansion | Identify owning boundary | $question_status | README.md When You Need This | + +## Plan Review Checklist + +| Check | Pass Criteria | Blocking Failure | Source / Basis | +|-------|---------------|------------------|----------------| +| Boundary cited | Plan names the affected boundary | Plan changes behavior without boundary review | README.md Planning Contract | +EOF + } + + write_contract \ + "Keep feature planning aligned to the existing product boundary." \ + "State which existing boundary is affected" \ + "README.md project description" \ + "CAN_PROCEED_WITH_GUARDRAIL" + usable_json=$(.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json) + printf '%s\n' "$usable_json" | search '"planning_gate":"USABLE"' - >/dev/null + + write_contract \ + "Create API schemas and edit src/controllers/UserController.ts." \ + "Add endpoints and DB tables" \ + "README.md project description" \ + "CAN_PROCEED_WITH_GUARDRAIL" + if implementation_json=$(.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json); then + echo "implementation-level contract must block planning readiness" >&2 + exit 1 + fi + printf '%s\n' "$implementation_json" | search '"ARCH_UNSUPPORTED_CONCLUSION"' - >/dev/null + + write_contract \ + "Keep feature planning aligned to the existing product boundary." \ + "State which existing boundary is affected" \ + "unknown" \ + "CAN_PROCEED_WITH_GUARDRAIL" + if missing_source_json=$(.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json); then + echo "contract with unsupported Source / Basis must block planning readiness" >&2 + exit 1 + fi + printf '%s\n' "$missing_source_json" | search '"ARCH_SOURCE_MISSING"' - >/dev/null + + write_contract \ + "Keep feature planning aligned to the existing product boundary." \ + "State which existing boundary is affected" \ + "README.md project description" \ + "MAYBE" + if invalid_status_json=$(.specify/extensions/arch/scripts/bash/validate-arch-artifacts.sh --json); then + echo "contract with invalid open question status must block planning readiness" >&2 + exit 1 + fi + printf '%s\n' "$invalid_status_json" | search '"ARCH_OPEN_QUESTION_STATUS_INVALID"' - >/dev/null + + printf 'custom sentinel\n' > .specify/memory/architecture.md + .specify/extensions/arch/scripts/bash/setup-arch.sh --json >/dev/null + search "custom sentinel" .specify/memory/architecture.md >/dev/null ) diff --git a/extensions/catalog.community.json b/extensions/catalog.community.json index 25e6fd4ee5..867b6c6c63 100644 --- a/extensions/catalog.community.json +++ b/extensions/catalog.community.json @@ -219,12 +219,12 @@ "updated_at": "2026-05-07T00:00:00Z" }, "arch": { - "name": "Architecture Workflow", + "name": "Architecture Planning Contract", "id": "arch", - "description": "Generate or reverse project-level 4+1 architecture views with per-view and full-workflow commands", + "description": "Generate or reverse a planning-focused architecture contract that guides downstream Spec Kit plans", "author": "bigsmartben", - "version": "1.2.2", - "download_url": "https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v1.2.2.zip", + "version": "2.0.0", + "download_url": "https://github.com/bigsmartben/spec-kit-arch/archive/refs/tags/v2.0.0.zip", "repository": "https://github.com/bigsmartben/spec-kit-arch", "homepage": "https://github.com/bigsmartben/spec-kit-arch", "documentation": "https://github.com/bigsmartben/spec-kit-arch/blob/main/README.md", @@ -236,12 +236,12 @@ "speckit_version": ">=0.8.10.dev0" }, "provides": { - "commands": 12, + "commands": 2, "hooks": 0 }, "tags": [ "architecture", - "4plus1", + "planning-contract", "workflow", "design" ], @@ -249,7 +249,7 @@ "downloads": 0, "stars": 0, "created_at": "2026-05-14T00:00:00Z", - "updated_at": "2026-06-25T00:00:00Z" + "updated_at": "2026-07-06T00:00:00Z" }, "architect-preview": { "name": "Architect Impact Previewer", diff --git a/extensions/catalog.json b/extensions/catalog.json index 494dd64f35..5674648166 100644 --- a/extensions/catalog.json +++ b/extensions/catalog.json @@ -18,10 +18,10 @@ ] }, "arch": { - "name": "Architecture Workflow", + "name": "Architecture Planning Contract", "id": "arch", - "version": "1.2.2", - "description": "Generate or reverse project-level 4+1 architecture views with per-view and full-workflow commands", + "version": "2.0.0", + "description": "Generate or reverse a planning-focused architecture contract that guides downstream Spec Kit plans", "author": "bigsmartben", "repository": "https://github.com/bigsmartben/spec-kit-arch", "license": "MIT", @@ -30,11 +30,11 @@ "speckit_version": ">=0.8.10.dev0" }, "provides": { - "commands": 12 + "commands": 2 }, "tags": [ "architecture", - "4plus1", + "planning-contract", "workflow", "design" ] diff --git a/src/specify_cli/commands/init.py b/src/specify_cli/commands/init.py index ddf0cb86bd..b652fac498 100644 --- a/src/specify_cli/commands/init.py +++ b/src/specify_cli/commands/init.py @@ -80,49 +80,6 @@ def ensure_constitution_from_template( ) -def _update_agent_context_config_file( - project_path: Path, - context_file: str, - *, - preserve_markers: bool = True, -) -> None: - """Write the active integration context file into agent-context config.""" - import yaml - - config_path = ( - project_path - / ".specify" - / "extensions" - / "agent-context" - / "agent-context-config.yml" - ) - data: dict[str, Any] = {} - if config_path.exists(): - loaded = yaml.safe_load(config_path.read_text(encoding="utf-8")) - if isinstance(loaded, dict): - data = loaded - - markers = data.get("context_markers") if preserve_markers else None - data["context_file"] = context_file - data.setdefault("context_files", []) - if preserve_markers and isinstance(markers, dict): - data["context_markers"] = markers - else: - data.setdefault( - "context_markers", - { - "start": "", - "end": "", - }, - ) - - config_path.parent.mkdir(parents=True, exist_ok=True) - config_path.write_text( - yaml.safe_dump(data, sort_keys=False, allow_unicode=True), - encoding="utf-8", - ) - - def register(app: typer.Typer) -> None: @app.command() def init( @@ -428,7 +385,6 @@ def init( ("chmod", "Ensure scripts executable"), ("constitution", "Constitution setup"), ("workflow", "Install bundled workflow"), - ("agent-context", "Install agent-context extension"), ("default-extensions", "Install default extensions"), ("default-presets", "Install default presets"), ("final", "Finalize"), @@ -561,47 +517,6 @@ def init( init_opts["ai_skills"] = True save_init_options(project_path, init_opts) - # --- agent-context extension (bundled, auto-installed) --- - # Installed after init-options.json is written so that skill - # registration can read ai_skills + integration key. - try: - from ..extensions import ExtensionManager as _ExtMgr - - bundled_ac = _locate_bundled_extension("agent-context") - if bundled_ac: - ac_mgr = _ExtMgr(project_path) - if ac_mgr.registry.is_installed("agent-context"): - tracker.complete("agent-context", "already installed") - else: - ac_mgr.install_from_directory( - bundled_ac, get_speckit_version() - ) - tracker.complete("agent-context", "extension installed") - else: - from ..extensions import REINSTALL_COMMAND as _ac_reinstall - - tracker.error( - "agent-context", - f"bundled extension not found — installation may be " - f"incomplete. Run: {_ac_reinstall}", - ) - except Exception as ac_err: - sanitized_ac = str(ac_err).replace("\n", " ").strip() - tracker.error( - "agent-context", - f"extension install failed: {sanitized_ac[:120]}", - ) - - # Write context_file to the agent-context extension config - # AFTER the extension install (which copies the template config - # with an empty context_file). - if resolved_integration.context_file: - _update_agent_context_config_file( - project_path, - resolved_integration.context_file, - preserve_markers=True, - ) - try: from ..extensions import ExtensionManager as _ExtMgr diff --git a/src/specify_cli/integrations/base.py b/src/specify_cli/integrations/base.py index 5e31baa605..fb52fcaf60 100644 --- a/src/specify_cli/integrations/base.py +++ b/src/specify_cli/integrations/base.py @@ -124,10 +124,7 @@ class IntegrationBase(ABC): """ context_file: str | None = None - """Agent context/instructions file managed by the agent-context extension.""" - - CONTEXT_MARKER_START = "" - CONTEXT_MARKER_END = "" + """Legacy metadata retained for compatibility; unused by setup logic.""" # -- Public API ------------------------------------------------------- @@ -596,79 +593,12 @@ def resolve_python_interpreter(project_root: Path | None = None) -> str: return name return sys.executable or "python3" - def _context_file_display(self, project_root: Path) -> str: - """Return the context file target to render in command templates.""" - return self.context_file or "" - - def _resolve_context_markers(self, project_root: Path) -> tuple[str, str]: - """Return configured agent-context markers, falling back to defaults.""" - config_path = ( - project_root - / ".specify" - / "extensions" - / "agent-context" - / "agent-context-config.yml" - ) - try: - cfg = yaml.safe_load(config_path.read_text(encoding="utf-8")) - except (OSError, UnicodeError, ValueError, yaml.YAMLError): - cfg = None - markers = cfg.get("context_markers") if isinstance(cfg, dict) else None - if isinstance(markers, dict): - start = markers.get("start") - end = markers.get("end") - if isinstance(start, str) and start and isinstance(end, str) and end: - return start, end - return self.CONTEXT_MARKER_START, self.CONTEXT_MARKER_END - - @staticmethod - def _upsert_context_file( - ctx_path: Path, - section: str, - marker_start: str, - marker_end: str, - ) -> None: - """Create or replace the managed Spec Kit section in *ctx_path*.""" - ctx_path.parent.mkdir(parents=True, exist_ok=True) - if ctx_path.exists(): - content = ctx_path.read_text(encoding="utf-8-sig") - else: - content = "" - - start_idx = content.find(marker_start) - end_idx = content.find(marker_end) - if start_idx != -1 and end_idx != -1 and end_idx > start_idx: - end_idx += len(marker_end) - new_content = content[:start_idx].rstrip() + "\n\n" + section + content[end_idx:] - elif content.strip(): - new_content = content.rstrip() + "\n\n" + section - else: - new_content = section - ctx_path.write_text(new_content.replace("\r\n", "\n").replace("\r", "\n"), encoding="utf-8") - - def upsert_context_section(self, project_root: Path, plan_path: str = "") -> Path | None: - """Create or update the managed section in this integration's context file.""" - if not self.context_file: - return None - lines = [ - "For additional context about technologies to be used, project structure,", - "shell commands, and other important information, read the current plan", - ] - if plan_path: - lines.append(f"at {plan_path}") - marker_start, marker_end = self._resolve_context_markers(project_root) - section = f"{marker_start}\n" + "\n".join(lines) + f"\n{marker_end}\n" - ctx_path = project_root / self.context_file - self._upsert_context_file(ctx_path, section, marker_start, marker_end) - return ctx_path - @staticmethod def process_template( content: str, agent_name: str, script_type: str, arg_placeholder: str = "$ARGUMENTS", - context_file: str = "", invoke_separator: str = ".", project_root: Path | None = None, ) -> str: @@ -752,18 +682,7 @@ def process_template( # 5. Replace __AGENT__ content = content.replace("__AGENT__", agent_name) - # 6. Replace context placeholders - content = content.replace("__CONTEXT_FILE__", context_file) - if context_file: - marker_start = IntegrationBase.CONTEXT_MARKER_START - marker_end = IntegrationBase.CONTEXT_MARKER_END - else: - marker_start = "the Spec Kit managed section start" - marker_end = "the Spec Kit managed section end" - content = content.replace("__CONTEXT_MARKER_START__", marker_start) - content = content.replace("__CONTEXT_MARKER_END__", marker_end) - - # 7. Rewrite paths — delegate to the shared implementation in + # 6. Rewrite paths — delegate to the shared implementation in # CommandRegistrar so extension-local paths are preserved and # boundary rules stay consistent across the codebase. from specify_cli.agents import CommandRegistrar @@ -928,13 +847,11 @@ def setup( else "$ARGUMENTS" ) created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") processed = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, project_root=project_root, ) dst_name = self.command_filename(src_file.stem) @@ -943,8 +860,6 @@ def setup( ) created.append(dst_file) - self.upsert_context_section(project_root) - return created @@ -1133,14 +1048,12 @@ def setup( else "{{args}}" ) created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") description = self._extract_description(raw) processed = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, project_root=project_root, ) _, body = self._split_frontmatter(processed) @@ -1151,8 +1064,6 @@ def setup( ) created.append(dst_file) - self.upsert_context_section(project_root) - return created @@ -1328,7 +1239,6 @@ def setup( else "{{args}}" ) created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") @@ -1344,7 +1254,6 @@ def setup( processed = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, project_root=project_root, ) _, body = self._split_frontmatter(processed) @@ -1357,8 +1266,6 @@ def setup( ) created.append(dst_file) - self.upsert_context_section(project_root) - return created @@ -1519,7 +1426,6 @@ def setup( else "$ARGUMENTS" ) created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") @@ -1543,7 +1449,6 @@ def setup( # Process body through the standard template pipeline processed_body = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, project_root=project_root, invoke_separator=self.invoke_separator, ) @@ -1585,6 +1490,4 @@ def setup( ) created.append(dst) - self.upsert_context_section(project_root) - return created diff --git a/src/specify_cli/integrations/copilot/__init__.py b/src/specify_cli/integrations/copilot/__init__.py index ef08143346..30b8df08bd 100644 --- a/src/specify_cli/integrations/copilot/__init__.py +++ b/src/specify_cli/integrations/copilot/__init__.py @@ -366,14 +366,12 @@ def _setup_default( script_type = opts.get("script_type", "sh") arg_placeholder = self.registrar_config.get("args", "$ARGUMENTS") - context_file_display = self._context_file_display(project_root) # 1. Process and write command files as .agent.md for src_file in templates: raw = src_file.read_text(encoding="utf-8") processed = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, project_root=project_root, ) dst_name = self.command_filename(src_file.stem) @@ -409,8 +407,6 @@ def _setup_default( self.record_file_in_manifest(dst_settings, project_root, manifest) created.append(dst_settings) - self.upsert_context_section(project_root) - return created def _setup_skills( diff --git a/src/specify_cli/integrations/forge/__init__.py b/src/specify_cli/integrations/forge/__init__.py index 1e4f586935..1f0d1ed8a8 100644 --- a/src/specify_cli/integrations/forge/__init__.py +++ b/src/specify_cli/integrations/forge/__init__.py @@ -127,14 +127,12 @@ def setup( script_type = opts.get("script_type", "sh") arg_placeholder = self.registrar_config.get("args", "{{parameters}}") created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") # Process template with standard MarkdownIntegration logic processed = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, invoke_separator=self.invoke_separator, project_root=project_root, ) @@ -152,8 +150,6 @@ def setup( ) created.append(dst_file) - self.upsert_context_section(project_root) - return created def _apply_forge_transformations(self, content: str, template_name: str) -> str: diff --git a/src/specify_cli/integrations/generic/__init__.py b/src/specify_cli/integrations/generic/__init__.py index b524033e31..340949185f 100644 --- a/src/specify_cli/integrations/generic/__init__.py +++ b/src/specify_cli/integrations/generic/__init__.py @@ -119,13 +119,11 @@ def setup( script_type = opts.get("script_type", "sh") arg_placeholder = "$ARGUMENTS" created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") processed = self.process_template( raw, self.key, script_type, arg_placeholder, - context_file=context_file_display, project_root=project_root, ) dst_name = self.command_filename(src_file.stem) @@ -134,6 +132,4 @@ def setup( ) created.append(dst_file) - self.upsert_context_section(project_root) - return created diff --git a/src/specify_cli/integrations/hermes/__init__.py b/src/specify_cli/integrations/hermes/__init__.py index 82444bf423..c223d2a793 100644 --- a/src/specify_cli/integrations/hermes/__init__.py +++ b/src/specify_cli/integrations/hermes/__init__.py @@ -113,7 +113,6 @@ def setup( global_skills_dir.mkdir(parents=True, exist_ok=True) created: list[Path] = [] - context_file_display = self._context_file_display(project_root) for src_file in templates: raw = src_file.read_text(encoding="utf-8") @@ -140,7 +139,6 @@ def setup( self.key, script_type, arg_placeholder, - context_file=context_file_display, invoke_separator=self.invoke_separator, project_root=project_root, ) @@ -188,8 +186,6 @@ def _quote(v: str) -> str: # (e.g. git) can detect Hermes as an active integration. # Hermes itself ignores this directory — skills live globally. (project_root / ".hermes" / "skills").mkdir(parents=True, exist_ok=True) - self.upsert_context_section(project_root) - return created # -- Uninstall --------------------------------------------------------- diff --git a/templates/commands/plan.md b/templates/commands/plan.md index b5a8c88f01..e82bd4b303 100644 --- a/templates/commands/plan.md +++ b/templates/commands/plan.md @@ -156,14 +156,11 @@ Command ends after Phase 2 planning. Report branch, IMPL_PLAN path, and generate - Do not include full implementation code, model/service/controller bodies, migrations, or complete test suites - Keep this artifact as a validation/run guide; implementation details belong in `tasks.md` and the implementation phase -4. **Agent context update**: - - Update the plan reference between the `__CONTEXT_MARKER_START__` and `__CONTEXT_MARKER_END__` markers in `__CONTEXT_FILE__` to point to the plan file created in step 1 (the IMPL_PLAN path) - -**Output**: data-model.md, /contracts/*, quickstart.md, updated agent context file +**Output**: data-model.md, /contracts/*, quickstart.md ## Key rules -- Use absolute paths for filesystem operations; use project-relative paths for references in documentation and agent context files +- Use absolute paths for filesystem operations; use project-relative paths for references in documentation - ERROR on gate failures or unresolved clarifications ## Done When diff --git a/tests/integrations/community_defaults.py b/tests/integrations/community_defaults.py index 6b0d1d4596..c0885e7150 100644 --- a/tests/integrations/community_defaults.py +++ b/tests/integrations/community_defaults.py @@ -11,18 +11,8 @@ REPO_ROOT = Path(__file__).resolve().parents[2] DEFAULT_EXTENSION_IDS = ("arch", "discovery", "intake", "preview", "repository-governance") DEFAULT_EXTENSION_COMMANDS = ( - "speckit.arch.scenario-generate", - "speckit.arch.logical-generate", - "speckit.arch.process-generate", - "speckit.arch.development-generate", - "speckit.arch.physical-generate", - "speckit.arch.full-generate", - "speckit.arch.full-reverse", - "speckit.arch.scenario-reverse", - "speckit.arch.logical-reverse", - "speckit.arch.process-reverse", - "speckit.arch.development-reverse", - "speckit.arch.physical-reverse", + "speckit.arch.generate", + "speckit.arch.reverse", "speckit.discovery.contract", "speckit.intake.visual-design", "speckit.intake.prd", diff --git a/tests/integrations/test_cli.py b/tests/integrations/test_cli.py index e3927755a0..2f9956eada 100644 --- a/tests/integrations/test_cli.py +++ b/tests/integrations/test_cli.py @@ -995,7 +995,7 @@ def test_git_extension_commands_not_registered_by_default(self, tmp_path): assert len(git_skills) == 0, "git extension commands should not be registered by default" def test_community_extensions_and_workflow_preset_auto_installed(self, tmp_path): - """specify init installs bundled community extensions and the workflow preset.""" + """specify init installs default community extensions and the workflow preset.""" from typer.testing import CliRunner from specify_cli import app @@ -1021,7 +1021,6 @@ def test_community_extensions_and_workflow_preset_auto_installed(self, tmp_path) extensions_yml = project / ".specify" / "extensions.yml" hooks_data = yaml.safe_load(extensions_yml.read_text(encoding="utf-8")) assert hooks_data["installed"] == [ - "agent-context", "arch", "discovery", "intake", diff --git a/tests/integrations/test_integration_base_skills.py b/tests/integrations/test_integration_base_skills.py index 957d02695a..492892d37f 100644 --- a/tests/integrations/test_integration_base_skills.py +++ b/tests/integrations/test_integration_base_skills.py @@ -1,8 +1,9 @@ """Reusable test mixin for standard SkillsIntegration subclasses. Each per-agent test file sets ``KEY``, ``FOLDER``, ``COMMANDS_SUBDIR``, -``REGISTRAR_DIR``, and ``CONTEXT_FILE``, then inherits all verification -logic from ``SkillsIntegrationTests``. +and ``REGISTRAR_DIR``, then inherits all verification logic from +``SkillsIntegrationTests``. ``CONTEXT_FILE`` is optional for legacy +integrations that still own a context file directly. Mirrors ``MarkdownIntegrationTests`` / ``TomlIntegrationTests`` closely, adapted for the ``speckit-/SKILL.md`` skills layout. @@ -27,14 +28,14 @@ class SkillsIntegrationTests: FOLDER: str — e.g. ".agents/" COMMANDS_SUBDIR: str — e.g. "skills" REGISTRAR_DIR: str — e.g. ".agents/skills" - CONTEXT_FILE: str — e.g. "AGENTS.md" + CONTEXT_FILE: str — optional legacy context file, e.g. "AGENTS.md" """ KEY: str FOLDER: str COMMANDS_SUBDIR: str REGISTRAR_DIR: str - CONTEXT_FILE: str + CONTEXT_FILE: str | None = None # -- Registration ----------------------------------------------------- @@ -358,8 +359,7 @@ def test_integration_flag_creates_files(self, tmp_path): assert skills_dir.is_dir(), f"Skills directory {skills_dir} not created" def test_init_options_includes_context_file(self, tmp_path): - """agent-context extension config must include context_file for the active integration.""" - import yaml + """specify init must not install or configure agent-context implicitly.""" from typer.testing import CliRunner from specify_cli import app @@ -376,11 +376,7 @@ def test_init_options_includes_context_file(self, tmp_path): os.chdir(old_cwd) assert result.exit_code == 0 ext_cfg_path = project / ".specify" / "extensions" / "agent-context" / "agent-context-config.yml" - ext_cfg = yaml.safe_load(ext_cfg_path.read_text(encoding="utf-8")) if ext_cfg_path.exists() else {} - i = get_integration(self.KEY) - assert ext_cfg.get("context_file") == i.context_file, ( - f"Expected context_file={i.context_file!r}, got {ext_cfg.get('context_file')!r}" - ) + assert not ext_cfg_path.exists() # -- IntegrationOption ------------------------------------------------ @@ -407,8 +403,6 @@ def _expected_files(self, script_variant: str) -> list[str]: # Skill files (core commands) for cmd in self._SKILL_COMMANDS: files.append(f"{skills_prefix}/speckit-{cmd}/SKILL.md") - # Extension-installed skill (agent-context) - files.append(f"{skills_prefix}/speckit-agent-context-update/SKILL.md") # Integration metadata files += [ ".specify/init-options.json", @@ -447,16 +441,8 @@ def _expected_files(self, script_variant: str) -> list[str]: ".specify/workflows/speckit/workflow.yml", ".specify/workflows/workflow-registry.json", ] - # Bundled agent-context extension files.append(".specify/extensions.yml") files.append(".specify/extensions/.registry") - files.append(".specify/extensions/agent-context/README.md") - files.append(".specify/extensions/agent-context/agent-context-defaults.json") - files.append(".specify/extensions/agent-context/agent-context-config.yml") - files.append(".specify/extensions/agent-context/commands/speckit.agent-context.update.md") - files.append(".specify/extensions/agent-context/extension.yml") - files.append(".specify/extensions/agent-context/scripts/bash/update-agent-context.sh") - files.append(".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1") # Agent context file (if set) if i.context_file: files.append(i.context_file) diff --git a/tests/integrations/test_integration_cline.py b/tests/integrations/test_integration_cline.py index 3f5e705914..e0b9233ff9 100644 --- a/tests/integrations/test_integration_cline.py +++ b/tests/integrations/test_integration_cline.py @@ -167,7 +167,6 @@ def _expected_files(self, script_variant: str) -> list[str]: else self.COMMAND_STEMS ): files.append(f"{cmd_dir}/speckit-{stem.replace('.', '-')}.md") - files.append(f"{cmd_dir}/speckit-agent-context-update.md") # Framework files files.append(".specify/integration.json") @@ -208,20 +207,8 @@ def _expected_files(self, script_variant: str) -> list[str]: files.append(".specify/workflows/speckit/workflow.yml") files.append(".specify/workflows/workflow-registry.json") - # Bundled agent-context extension files.append(".specify/extensions.yml") files.append(".specify/extensions/.registry") - files.append(".specify/extensions/agent-context/README.md") - files.append(".specify/extensions/agent-context/agent-context-defaults.json") - files.append(".specify/extensions/agent-context/agent-context-config.yml") - files.append(".specify/extensions/agent-context/commands/speckit.agent-context.update.md") - files.append(".specify/extensions/agent-context/extension.yml") - files.append(".specify/extensions/agent-context/scripts/bash/update-agent-context.sh") - files.append(".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1") - - # Agent context file (if set) - if i.context_file: - files.append(i.context_file) files.extend(bundled_community_default_files(self.KEY)) diff --git a/tests/integrations/test_integration_copilot.py b/tests/integrations/test_integration_copilot.py index 74ac4aa468..3c475bf239 100644 --- a/tests/integrations/test_integration_copilot.py +++ b/tests/integrations/test_integration_copilot.py @@ -164,8 +164,8 @@ def test_specify_agent_resolves_active_spec_template(self, tmp_path): assert "Copy `.specify/templates/spec-template.md`" not in content assert "Load `.specify/templates/spec-template.md`" not in content - def test_plan_references_correct_context_file(self, tmp_path): - """The generated plan command must reference copilot's context file.""" + def test_plan_does_not_reference_context_file(self, tmp_path): + """The generated plan command must not reference a context file.""" from specify_cli.integrations.copilot import CopilotIntegration copilot = CopilotIntegration() m = IntegrationManifest("copilot", tmp_path) @@ -173,10 +173,8 @@ def test_plan_references_correct_context_file(self, tmp_path): plan_file = tmp_path / ".github" / "agents" / "speckit.plan.agent.md" assert plan_file.exists() content = plan_file.read_text(encoding="utf-8") - assert copilot.context_file in content, ( - f"Plan command should reference {copilot.context_file!r}" - ) assert "__CONTEXT_FILE__" not in content + assert ".github/copilot-instructions.md" not in content def test_complete_file_inventory_sh(self, tmp_path): """Every file produced by specify init --integration copilot --script sh.""" @@ -195,7 +193,6 @@ def test_complete_file_inventory_sh(self, tmp_path): assert result.exit_code == 0 actual = sorted(p.relative_to(project).as_posix() for p in project.rglob("*") if p.is_file() and ".git" not in p.parts) expected = [ - ".github/agents/speckit.agent-context.update.agent.md", ".github/agents/speckit.analyze.agent.md", ".github/agents/speckit.checklist.agent.md", ".github/agents/speckit.clarify.agent.md", @@ -206,7 +203,6 @@ def test_complete_file_inventory_sh(self, tmp_path): ".github/agents/speckit.specify.agent.md", ".github/agents/speckit.tasks.agent.md", ".github/agents/speckit.taskstoissues.agent.md", - ".github/prompts/speckit.agent-context.update.prompt.md", ".github/prompts/speckit.analyze.prompt.md", ".github/prompts/speckit.checklist.prompt.md", ".github/prompts/speckit.clarify.prompt.md", @@ -218,16 +214,8 @@ def test_complete_file_inventory_sh(self, tmp_path): ".github/prompts/speckit.tasks.prompt.md", ".github/prompts/speckit.taskstoissues.prompt.md", ".vscode/settings.json", - ".github/copilot-instructions.md", ".specify/extensions.yml", ".specify/extensions/.registry", - ".specify/extensions/agent-context/README.md", - ".specify/extensions/agent-context/agent-context-defaults.json", - ".specify/extensions/agent-context/agent-context-config.yml", - ".specify/extensions/agent-context/commands/speckit.agent-context.update.md", - ".specify/extensions/agent-context/extension.yml", - ".specify/extensions/agent-context/scripts/bash/update-agent-context.sh", - ".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1", ".specify/integration.json", ".specify/init-options.json", ".specify/integrations/copilot.manifest.json", @@ -271,7 +259,6 @@ def test_complete_file_inventory_ps(self, tmp_path): assert result.exit_code == 0 actual = sorted(p.relative_to(project).as_posix() for p in project.rglob("*") if p.is_file() and ".git" not in p.parts) expected = [ - ".github/agents/speckit.agent-context.update.agent.md", ".github/agents/speckit.analyze.agent.md", ".github/agents/speckit.checklist.agent.md", ".github/agents/speckit.clarify.agent.md", @@ -282,7 +269,6 @@ def test_complete_file_inventory_ps(self, tmp_path): ".github/agents/speckit.specify.agent.md", ".github/agents/speckit.tasks.agent.md", ".github/agents/speckit.taskstoissues.agent.md", - ".github/prompts/speckit.agent-context.update.prompt.md", ".github/prompts/speckit.analyze.prompt.md", ".github/prompts/speckit.checklist.prompt.md", ".github/prompts/speckit.clarify.prompt.md", @@ -294,16 +280,8 @@ def test_complete_file_inventory_ps(self, tmp_path): ".github/prompts/speckit.tasks.prompt.md", ".github/prompts/speckit.taskstoissues.prompt.md", ".vscode/settings.json", - ".github/copilot-instructions.md", ".specify/extensions.yml", ".specify/extensions/.registry", - ".specify/extensions/agent-context/README.md", - ".specify/extensions/agent-context/agent-context-defaults.json", - ".specify/extensions/agent-context/agent-context-config.yml", - ".specify/extensions/agent-context/commands/speckit.agent-context.update.md", - ".specify/extensions/agent-context/extension.yml", - ".specify/extensions/agent-context/scripts/bash/update-agent-context.sh", - ".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1", ".specify/integration.json", ".specify/init-options.json", ".specify/integrations/copilot.manifest.json", @@ -547,15 +525,15 @@ def test_skill_body_has_content(self, tmp_path): body = parts[2].strip() if len(parts) >= 3 else "" assert len(body) > 0, f"{f} has empty body" - def test_plan_references_correct_context_file(self, tmp_path): - """The generated plan skill must reference copilot's context file.""" + def test_plan_does_not_reference_context_file(self, tmp_path): + """The generated plan skill must not reference a context file.""" copilot = self._make_copilot() self._setup_skills(copilot, tmp_path) plan_file = tmp_path / ".github" / "skills" / "speckit-plan" / "SKILL.md" assert plan_file.exists() content = plan_file.read_text(encoding="utf-8") - assert copilot.context_file in content assert "__CONTEXT_FILE__" not in content + assert ".github/copilot-instructions.md" not in content # -- Manifest tracking ------------------------------------------------ @@ -611,16 +589,13 @@ def test_build_command_invocation_default_mode(self): assert copilot.build_command_invocation("plan", "my args") == "my args" assert copilot.build_command_invocation("plan") == "" - # -- Context section --------------------------------------------------- + # -- Context ownership ------------------------------------------------- - def test_skills_setup_upserts_context_section(self, tmp_path): + def test_skills_setup_does_not_create_context_file(self, tmp_path): copilot = self._make_copilot() self._setup_skills(copilot, tmp_path) ctx_path = tmp_path / copilot.context_file - assert ctx_path.exists() - content = ctx_path.read_text(encoding="utf-8") - assert "" in content - assert "" in content + assert not ctx_path.exists() # -- CLI integration test --------------------------------------------- @@ -669,21 +644,10 @@ def test_complete_file_inventory_skills_sh(self, tmp_path): assert result.exit_code == 0, f"init failed: {result.output}" actual = sorted(p.relative_to(project).as_posix() for p in project.rglob("*") if p.is_file() and ".git" not in p.parts) expected = [ - # Skill files (core + extension-installed agent-context command) + # Skill files (core commands) *[f".github/skills/speckit-{cmd}/SKILL.md" for cmd in self._SKILL_COMMANDS], - ".github/skills/speckit-agent-context-update/SKILL.md", - # Context file - ".github/copilot-instructions.md", - # Bundled agent-context extension ".specify/extensions.yml", ".specify/extensions/.registry", - ".specify/extensions/agent-context/README.md", - ".specify/extensions/agent-context/agent-context-defaults.json", - ".specify/extensions/agent-context/agent-context-config.yml", - ".specify/extensions/agent-context/commands/speckit.agent-context.update.md", - ".specify/extensions/agent-context/extension.yml", - ".specify/extensions/agent-context/scripts/bash/update-agent-context.sh", - ".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1", # Integration metadata ".specify/init-options.json", ".specify/integration.json", diff --git a/tests/integrations/test_integration_generic.py b/tests/integrations/test_integration_generic.py index 051cd81e60..7cb70b213e 100644 --- a/tests/integrations/test_integration_generic.py +++ b/tests/integrations/test_integration_generic.py @@ -160,31 +160,24 @@ def test_different_commands_dirs(self, tmp_path): cmd_files = [f for f in created if "scripts" not in f.parts] assert len(cmd_files) > 0 - # -- Context section --------------------------------------------------- + # -- Context ownership ------------------------------------------------- - def test_setup_upserts_context_section(self, tmp_path): + def test_setup_does_not_create_context_file(self, tmp_path): i = get_integration("generic") m = IntegrationManifest("generic", tmp_path) i.setup(tmp_path, m, parsed_options={"commands_dir": ".custom/cmds"}) - if i.context_file: - ctx_path = tmp_path / i.context_file - assert ctx_path.exists() - content = ctx_path.read_text(encoding="utf-8") - assert "" in content - assert "" in content - - def test_plan_references_correct_context_file(self, tmp_path): - """The generated plan command must reference generic's context file.""" + assert not (tmp_path / "AGENTS.md").exists() + + def test_plan_does_not_reference_context_file(self, tmp_path): + """The generated plan command must not reference a context file.""" i = get_integration("generic") m = IntegrationManifest("generic", tmp_path) i.setup(tmp_path, m, parsed_options={"commands_dir": ".custom/cmds"}) plan_file = tmp_path / ".custom" / "cmds" / "speckit.plan.md" assert plan_file.exists() content = plan_file.read_text(encoding="utf-8") - assert i.context_file in content, ( - f"Plan command should reference {i.context_file!r}" - ) assert "__CONTEXT_FILE__" not in content + assert "AGENTS.md" not in content def test_plan_defines_quickstart_as_validation_guide(self, tmp_path): """The generated plan command should keep quickstart.md out of implementation scope.""" @@ -257,9 +250,8 @@ def test_cli_generic_without_commands_dir_fails(self, tmp_path): # Generic requires --commands-dir via --integration-options assert result.exit_code != 0 - def test_init_options_includes_context_file(self, tmp_path): - """agent-context extension config must include context_file for the generic integration.""" - import yaml + def test_init_options_do_not_include_context_file(self, tmp_path): + """init must not install or configure agent-context for generic.""" from typer.testing import CliRunner from specify_cli import app @@ -277,8 +269,7 @@ def test_init_options_includes_context_file(self, tmp_path): os.chdir(old_cwd) assert result.exit_code == 0 ext_cfg_path = project / ".specify" / "extensions" / "agent-context" / "agent-context-config.yml" - ext_cfg = yaml.safe_load(ext_cfg_path.read_text(encoding="utf-8")) if ext_cfg_path.exists() else {} - assert ext_cfg.get("context_file") == "AGENTS.md" + assert not ext_cfg_path.exists() def test_complete_file_inventory_sh(self, tmp_path): """Every file produced by specify init --integration generic --integration-options=--commands-dir ... --script sh.""" @@ -303,7 +294,6 @@ def test_complete_file_inventory_sh(self, tmp_path): for p in project.rglob("*") if p.is_file() and ".git" not in p.parts ) expected = [ - "AGENTS.md", ".myagent/commands/speckit.analyze.md", ".myagent/commands/speckit.checklist.md", ".myagent/commands/speckit.clarify.md", @@ -316,13 +306,6 @@ def test_complete_file_inventory_sh(self, tmp_path): ".myagent/commands/speckit.taskstoissues.md", ".specify/extensions.yml", ".specify/extensions/.registry", - ".specify/extensions/agent-context/README.md", - ".specify/extensions/agent-context/agent-context-defaults.json", - ".specify/extensions/agent-context/agent-context-config.yml", - ".specify/extensions/agent-context/commands/speckit.agent-context.update.md", - ".specify/extensions/agent-context/extension.yml", - ".specify/extensions/agent-context/scripts/bash/update-agent-context.sh", - ".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1", ".specify/init-options.json", ".specify/integration.json", ".specify/integrations/generic.manifest.json", @@ -377,7 +360,6 @@ def test_complete_file_inventory_ps(self, tmp_path): for p in project.rglob("*") if p.is_file() and ".git" not in p.parts ) expected = [ - "AGENTS.md", ".myagent/commands/speckit.analyze.md", ".myagent/commands/speckit.checklist.md", ".myagent/commands/speckit.clarify.md", @@ -390,13 +372,6 @@ def test_complete_file_inventory_ps(self, tmp_path): ".myagent/commands/speckit.taskstoissues.md", ".specify/extensions.yml", ".specify/extensions/.registry", - ".specify/extensions/agent-context/README.md", - ".specify/extensions/agent-context/agent-context-defaults.json", - ".specify/extensions/agent-context/agent-context-config.yml", - ".specify/extensions/agent-context/commands/speckit.agent-context.update.md", - ".specify/extensions/agent-context/extension.yml", - ".specify/extensions/agent-context/scripts/bash/update-agent-context.sh", - ".specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1", ".specify/init-options.json", ".specify/integration.json", ".specify/integrations/generic.manifest.json", diff --git a/tests/integrations/test_integration_rovodev.py b/tests/integrations/test_integration_rovodev.py index 45e337e06a..f1a7eb831a 100644 --- a/tests/integrations/test_integration_rovodev.py +++ b/tests/integrations/test_integration_rovodev.py @@ -13,6 +13,7 @@ from specify_cli import app from specify_cli.integrations import get_integration from specify_cli.integrations.manifest import IntegrationManifest +from tests.integrations.community_defaults import DEFAULT_EXTENSION_COMMANDS def _run_init(project, *flags: str) -> Result: @@ -218,8 +219,13 @@ def test_init_inventory(self, rovodev_init_project): # Prompts: exactly the core template set. assert prompt_stems == core_skill_names - # Skills: exactly the core template set (no extension auto-install). - assert skill_names == core_skill_names + extension_skill_names = { + command.replace(".", "-") + for command in DEFAULT_EXTENSION_COMMANDS + } + + # Skills: core templates plus default bundled extension commands. + assert skill_names == core_skill_names | extension_skill_names # prompts.yml mirrors the prompt files exactly. prompts_manifest = project / ".rovodev" / "prompts.yml" diff --git a/tests/test_arch_templates.py b/tests/test_arch_templates.py index 76d95d6676..32a209a3b5 100644 --- a/tests/test_arch_templates.py +++ b/tests/test_arch_templates.py @@ -1,4 +1,5 @@ -"""Quality guards for 4+1 architecture templates and command.""" +"""Quality guards for the bundled architecture planning contract extension.""" + from pathlib import Path @@ -12,22 +13,12 @@ def _read_template(name: str) -> str: return (TEMPLATES / name).read_text(encoding="utf-8") -def test_arch_commands_are_split_by_view_and_bootstrap_setup(): +def test_arch_commands_are_single_planning_contract_surface(): command_files = sorted(COMMANDS.glob("speckit.arch.*.md")) assert [path.name for path in command_files] == [ - "speckit.arch.development-generate.md", - "speckit.arch.development-reverse.md", - "speckit.arch.full-generate.md", - "speckit.arch.full-reverse.md", - "speckit.arch.logical-generate.md", - "speckit.arch.logical-reverse.md", - "speckit.arch.physical-generate.md", - "speckit.arch.physical-reverse.md", - "speckit.arch.process-generate.md", - "speckit.arch.process-reverse.md", - "speckit.arch.scenario-generate.md", - "speckit.arch.scenario-reverse.md", + "speckit.arch.generate.md", + "speckit.arch.reverse.md", ] for command_file in command_files: @@ -37,51 +28,49 @@ def test_arch_commands_are_split_by_view_and_bootstrap_setup(): assert ".specify/extensions/arch/scripts/powershell/setup-arch.ps1 -Json" in content assert "ARCH_SCHEMA_FILE" in content assert "ARCH_VALIDATOR_FILE" in content - assert "Synthesis Readiness" in content + assert "planning_gate" in content assert "ready_gate" in content assert "BLOCKER" in content + assert "Write only `ARCH_FILE`" in content + assert "Do not create, update, or require separate 4+1 view files" in content assert ".specify/memory/architecture/" not in content assert "__SPECKIT_COMMAND_UC__" not in content -def test_arch_generate_and_reverse_commands_keep_distinct_evidence_boundaries(): - for command_file in COMMANDS.glob("speckit.arch.*-generate.md"): - content = command_file.read_text(encoding="utf-8") - assert "Do not read, populate, or update `REPO_FACTS_FILE`" in content - assert "record" in content - assert "instead of inventing" in content +def test_arch_generate_and_reverse_keep_evidence_inside_single_artifact(): + generate = (COMMANDS / "speckit.arch.generate.md").read_text(encoding="utf-8") + reverse = (COMMANDS / "speckit.arch.reverse.md").read_text(encoding="utf-8") - for command_file in COMMANDS.glob("speckit.arch.*-reverse.md"): - content = command_file.read_text(encoding="utf-8") - assert "observable repository" in content - assert "REPO_FACTS_FILE" in content - assert "Every non-placeholder fact must name an evidence source" in content - assert "Architecture conclusions must trace to repo facts" in content + assert "Source / Basis" in generate + assert "Open Architecture Questions" in generate + assert "instead of inventing planning rules" in generate + assert "observable repository evidence" in reverse + assert "Source / Basis" in reverse + assert "not in a secondary evidence file" in reverse + assert "Do not create, update, or require `.specify/memory/architecture-repo-facts.md`" in reverse -def test_architecture_synthesis_references_five_view_files(): + +def test_architecture_template_defines_planning_contract_sections(): content = _read_template("architecture-template.md") - for filename in [ - "architecture-scenario-view.md", - "architecture-logical-view.md", - "architecture-process-view.md", - "architecture-development-view.md", - "architecture-physical-view.md", - ]: - assert f".specify/memory/{filename}" in content - assert "Cross-View Architecture Model" in content - assert "Cross-view mappings between view-specific concepts" in content - assert "Key Architecture Conclusions" in content for section in [ "Architecture Intent", - "Central Design Forces", - "Primary Tradeoffs", - "Stable Boundaries", - "Change Axes", - "Anti-patterns", + "Planning Scope Rules", + "Capability Boundaries", + "Required Constraints", + "Architecture Decisions Already Made", + "Allowed Extension Points", + "Prohibited Plan Directions", + "Open Architecture Questions", + "Plan Review Checklist", ]: - assert section in content + assert f"## {section}" in content + + assert content.count("Source / Basis") == 9 + assert "Planning Status" in content + assert ".specify/memory/architecture-scenario-view.md" not in content + assert ".specify/memory/architecture-repo-facts.md" not in content assert ".specify/memory/architecture/" not in content @@ -95,51 +84,27 @@ def test_init_next_steps_do_not_list_arch_as_core_workflow(): assert "specify extension add arch" not in init_source -def test_view_templates_define_inputs_and_reject_implementation_detail(): - scenario = _read_template("architecture-scenario-template.md") - logical = _read_template("architecture-logical-template.md") - process = _read_template("architecture-process-template.md") - development = _read_template("architecture-development-template.md") - physical = _read_template("architecture-physical-template.md") - - assert "Use-case semantics for the architecture workflow" in scenario - assert "Actors and Participants" in scenario - assert "Acceptance Semantics" in scenario - assert "**Input**: `.specify/memory/architecture-scenario-view.md`" in logical - assert "Capability Boundaries" in logical - assert "Domain Objects and Relationships" in logical - assert "**Input**: `.specify/memory/architecture-scenario-view.md`, `.specify/memory/architecture-logical-view.md`" in process - assert "Main Runtime Links" in process - assert "Failure, Degradation, and Closure" in process - assert "**Input**: `.specify/memory/architecture-logical-view.md`, `.specify/memory/architecture-process-view.md`" in development - assert "Architecture-Level Components" in development - assert "Dependency Rules" in development - assert "**Input**: `.specify/memory/architecture-process-view.md`, `.specify/memory/architecture-development-view.md`" in physical - assert "Deployment and Hosting Boundaries" in physical - assert "Operations and Release Boundaries" in physical - - for content in [scenario, logical, process, development, physical]: - for section in [ - "Architecture Intent", - "Core Tensions", - "Stable Boundaries", - "Change Axes", - "Invariants", - "Non-goals / Anti-patterns", - ]: - assert section in content - - -def test_view_templates_keep_notations_out_of_reasoning_contracts(): - view_contents = [ - _read_template("architecture-scenario-template.md"), - _read_template("architecture-logical-template.md"), - _read_template("architecture-process-template.md"), - _read_template("architecture-development-template.md"), - _read_template("architecture-physical-template.md"), +def test_removed_legacy_view_templates_are_not_bundled(): + assert sorted(path.name for path in TEMPLATES.glob("architecture-*.md")) == [ + "architecture-template.md" ] - notation_terms = ["C4", "UML", "Mermaid", "PlantUML", "notation-specific"] - for content in view_contents: - for term in notation_terms: - assert term not in content + +def test_schema_and_validator_enforce_planning_quality_gate(): + schema = (ARCHITECTURE_EXTENSION / "schemas" / "architecture-artifacts.schema.json").read_text( + encoding="utf-8" + ) + bash_validator = ( + ARCHITECTURE_EXTENSION / "scripts" / "bash" / "validate-arch-artifacts.sh" + ).read_text(encoding="utf-8") + ps_validator = ( + ARCHITECTURE_EXTENSION / "scripts" / "powershell" / "validate-arch-artifacts.ps1" + ).read_text(encoding="utf-8") + + for content in [schema, bash_validator, ps_validator]: + assert "ARCH_SOURCE_MISSING" in content + assert "ARCH_UNSUPPORTED_CONCLUSION" in content + assert "ARCH_OPEN_QUESTION_STATUS_INVALID" in content + + assert "planningScopeRuleRecord" in schema + assert "openArchitectureQuestionRecord" in schema diff --git a/tests/test_presets.py b/tests/test_presets.py index 73be077bb7..985aac9fa9 100644 --- a/tests/test_presets.py +++ b/tests/test_presets.py @@ -4785,7 +4785,11 @@ def test_community_smoke_checks_wheel_assets_and_extension_dev_reinstall(self): in verify_run ) assert ( - 'test -f .claude/skills/speckit-arch-scenario-generate/SKILL.md' + 'test -f .claude/skills/speckit-arch-generate/SKILL.md' + in verify_run + ) + assert ( + 'test -f .claude/skills/speckit-arch-reverse/SKILL.md' in verify_run ) assert ( diff --git a/tests/test_setup_arch.py b/tests/test_setup_arch.py index bbd7b93284..897f783151 100644 --- a/tests/test_setup_arch.py +++ b/tests/test_setup_arch.py @@ -20,12 +20,6 @@ VALIDATE_ARCH_PS = ARCHITECTURE_EXTENSION / "scripts" / "powershell" / "validate-arch-artifacts.ps1" ARCH_TEMPLATES = [ "architecture-template.md", - "architecture-repo-facts-template.md", - "architecture-scenario-template.md", - "architecture-logical-template.md", - "architecture-process-template.md", - "architecture-development-template.md", - "architecture-physical-template.md", ] ARCH_SCHEMAS = [ "architecture-artifacts.schema.json", @@ -129,12 +123,6 @@ def _assert_arch_json(repo: Path, data: dict[str, str], *, exact_paths: bool = T "ARCH_SCHEMA_FILE": repo / ".specify" / "extensions" / "arch" / "schemas" / "architecture-artifacts.schema.json", "ARCH_VALIDATOR_FILE": repo / ".specify" / "extensions" / "arch" / "scripts" / "bash" / "validate-arch-artifacts.sh", "ARCH_VALIDATOR_PS_FILE": repo / ".specify" / "extensions" / "arch" / "scripts" / "powershell" / "validate-arch-artifacts.ps1", - "REPO_FACTS_FILE": repo / ".specify" / "memory" / "architecture-repo-facts.md", - "SCENARIO_VIEW": repo / ".specify" / "memory" / "architecture-scenario-view.md", - "LOGICAL_VIEW": repo / ".specify" / "memory" / "architecture-logical-view.md", - "PROCESS_VIEW": repo / ".specify" / "memory" / "architecture-process-view.md", - "DEVELOPMENT_VIEW": repo / ".specify" / "memory" / "architecture-development-view.md", - "PHYSICAL_VIEW": repo / ".specify" / "memory" / "architecture-physical-view.md", } assert set(data) == set(expected) for key, path in expected.items(): @@ -147,7 +135,7 @@ def _assert_arch_json(repo: Path, data: dict[str, str], *, exact_paths: bool = T @requires_bash -def test_setup_arch_bash_creates_all_artifacts_and_json(arch_repo: Path) -> None: +def test_setup_arch_bash_creates_single_artifact_and_json(arch_repo: Path) -> None: script = arch_repo / ".specify" / "extensions" / "arch" / "scripts" / "bash" / "setup-arch.sh" result = subprocess.run( ["bash", str(script), "--json"], @@ -161,14 +149,16 @@ def test_setup_arch_bash_creates_all_artifacts_and_json(arch_repo: Path) -> None assert result.returncode == 0, result.stderr + result.stdout data = _json_from_output(result.stdout) _assert_arch_json(arch_repo, data) - assert "Scenario View" in (arch_repo / ".specify" / "memory" / "architecture-scenario-view.md").read_text(encoding="utf-8") + memory_files = sorted(path.name for path in (arch_repo / ".specify" / "memory").glob("*.md")) + assert memory_files == ["architecture.md"] + assert "Architecture Planning Contract" in (arch_repo / ".specify" / "memory" / "architecture.md").read_text(encoding="utf-8") @requires_bash def test_setup_arch_bash_preserves_existing_files(arch_repo: Path) -> None: - existing = arch_repo / ".specify" / "memory" / "architecture-scenario-view.md" + existing = arch_repo / ".specify" / "memory" / "architecture.md" existing.parent.mkdir(parents=True) - existing.write_text("# Custom Scenario\n", encoding="utf-8") + existing.write_text("# Custom Architecture\n", encoding="utf-8") script = arch_repo / ".specify" / "extensions" / "arch" / "scripts" / "bash" / "setup-arch.sh" result = subprocess.run( @@ -181,11 +171,11 @@ def test_setup_arch_bash_preserves_existing_files(arch_repo: Path) -> None: ) assert result.returncode == 0, result.stderr + result.stdout - assert existing.read_text(encoding="utf-8") == "# Custom Scenario\n" + assert existing.read_text(encoding="utf-8") == "# Custom Architecture\n" @pytest.mark.skipif(not (HAS_PWSH or _POWERSHELL), reason="no PowerShell available") -def test_setup_arch_powershell_creates_all_artifacts_and_json(arch_repo: Path) -> None: +def test_setup_arch_powershell_creates_single_artifact_and_json(arch_repo: Path) -> None: script = arch_repo / ".specify" / "extensions" / "arch" / "scripts" / "powershell" / "setup-arch.ps1" exe = "pwsh" if HAS_PWSH else _POWERSHELL result = _run_powershell( @@ -196,3 +186,5 @@ def test_setup_arch_powershell_creates_all_artifacts_and_json(arch_repo: Path) - assert result.returncode == 0, result.stderr + result.stdout data = _json_from_output(result.stdout) _assert_arch_json(arch_repo, data, exact_paths=False) + memory_files = sorted(path.name for path in (arch_repo / ".specify" / "memory").glob("*.md")) + assert memory_files == ["architecture.md"]