Files
ss-tools/.opencode/command/speckit.plan.md
2026-06-09 09:43:34 +03:00

20 KiB
Raw Blame History

description, handoffs
description handoffs
Execute the implementation planning workflow for ss-tools (Python backend + Svelte frontend) and generate research, design, contracts, and quickstart artifacts.
label agent prompt send
Create Tasks speckit.tasks Break the plan into executable tasks for Python/Svelte implementation true
label agent prompt
Create Checklist speckit.checklist Create a requirements-quality checklist for the active feature

User Input

$ARGUMENTS

You MUST consider the user input before proceeding (if not empty).

Outline

  1. Setup: Run .specify/scripts/bash/setup-plan.sh --json from repo root and parse FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, and BRANCH.

    • IMPL_PLAN is the authoritative path for plan.md inside specs/<feature>/.
    • Derive FEATURE_DIR from IMPL_PLAN and write every planning artifact there.
    • Never treat .kilo/plans/* as workflow output for /speckit.plan.
  2. Load canonical planning context:

    • README.md
    • requirements.txt (backend dependencies)
    • frontend/package.json (frontend dependencies)
    • .specify/memory/constitution.md
    • .opencode/skills/semantics-core/SKILL.md
    • .opencode/skills/semantics-contracts/SKILL.md
    • .opencode/skills/semantics-python/SKILL.md
    • .opencode/skills/semantics-svelte/SKILL.md
    • .opencode/skills/semantics-testing/SKILL.md
    • .specify/templates/plan-template.md
    • FEATURE_DIR/contracts/ux/screen-models.md (if /speckit.ux was run)
    • FEATURE_DIR/contracts/ux/api-ux.md (if /speckit.ux was run)
    • FEATURE_DIR/contracts/ux/*-ux.md (per-screen UX contracts)
    • relevant docs/adr/*.md
  3. Execute the planning workflow using the template structure:

    • Fill Technical Context for the current repository reality: Python 3.9+/FastAPI backend, SvelteKit 5/Tailwind frontend, PostgreSQL, Docker, semantic contracts, belief runtime.
    • Fill Constitution Check using the local constitution.
    • ERROR if a blocking constitutional or semantic conflict is discovered and cannot be justified.
    • Phase 0: generate research.md in FEATURE_DIR, resolving all material unknowns.
    • Phase 1: generate data-model.md, contracts/modules.md, optional machine-readable contract artifacts, and quickstart.md in FEATURE_DIR.
    • Phase 1: if UX contracts exist, generate traceability.md — a requirements traceability matrix mapping Story → Model → API → Task → Test.
    • Materialize blocking ADR references and planning decisions inside the plan and downstream contracts.
    • Run .specify/scripts/bash/update-agent-context.sh kilocode after planning artifacts are written.
  4. Stop and report after planning artifacts are complete. Report branch, plan.md path, generated artifacts, and blocking ADR/decision-memory outcomes.

Phase 0: Research

Research must resolve only implementation-shaping unknowns that matter for this repository, such as:

  • module placement under backend/src/ or frontend/src/
  • Screen Model topology: which screens need a [TYPE Model] (.svelte.ts), which atoms each model declares, which invariants cross widget boundaries
  • API endpoint design (REST routes, WebSocket channels)
  • database schema changes (SQLAlchemy models, migrations)
  • Svelte component hierarchy and store topology
  • async task orchestration patterns
  • TypeScript DTO alignment: frontend types/ matching backend Pydantic schemas
  • test strategy (pytest + vitest; L1 model invariants without render + L2 UX contracts with render)
  • belief runtime instrumentation for C4/C5 flows
  • semantic validation boundaries and static verification workflow

If /speckit.ux was run before plan:

  • screen-models.md defines Model inventory → use directly, don't re-discover
  • api-ux.md defines API shapes → use as @DATA_CONTRACT source for backend Pydantic schemas
  • <screen>-ux.md defines UX contracts → use as @UX_STATE/@UX_FEEDBACK source for component contracts
  • Generated .svelte.ts model files in frontend/src/lib/models/ → DO NOT regenerate; reference them via @RELATION BINDS_TO from component contracts

Write research.md with concise sections:

  • Decision
  • Rationale
  • Alternatives Considered
  • Impact On Contracts / Tasks

Use [NEED_CONTEXT: target] instead of inventing relation targets, DTO names, or module boundaries that cannot be grounded in repo context.

Phase 1: Design, ADR Continuity, and Contracts

Frontend Model & Component Reuse Scan (MANDATORY — before contract generation)

Before designing any new screen, execute a model-first inventory scan followed by a component inventory scan of the existing codebase to maximise reuse and prevent duplicate primitives.

Step 1: Screen Model scan (use a subagent with subagent_type: "explore"):

  • Search frontend/src/lib/models/ for existing [TYPE Model] contracts
  • Use axiom_semantic_discovery search_contracts type="Model" query="<domain>" for structured search
  • Check model atoms, actions, and invariants — reuse if the screen state maps to an existing model
  • New models use .svelte.ts extension, [TYPE Model] contract, @STATE/@ACTION/@INVARIANT tags

Step 2: Component scan (priority order):

Scan targets (priority order):

  1. frontend/src/lib/ui/ — design-system atoms: Button.svelte, Select.svelte, Input.svelte, Card.svelte
  2. frontend/src/lib/components/ui/ — composite UI widgets: SearchableMultiSelect.svelte, MultiSelect.svelte
  3. frontend/src/lib/components/ — feature components that may be adaptable
  4. Inline patterns in existing pages (frontend/src/routes/) — badges, skeletons, empty states, collapsibles

For each found component, the scan MUST return:

  • Exact file path
  • Props interface (what it accepts)
  • Whether it's a direct fit, adaptable, or pattern-only

Reuse decision tree:

Situation Action
Component exists and fits @RELATION DEPENDS_ON -> [ExistingComponent] — zero new code
Pattern exists (badge, skeleton, tooltip) Document the Tailwind classes to replicate; no component extraction
No reusable asset exists Create new component only then

Output: The contracts/modules.md for every frontend contract MUST include @RELATION edges to reused components/models and a @RATIONALE noting WHY the asset is reused rather than rebuilt. For pattern-only reuse, the contract MUST reference the source page/file where the pattern was observed. Components that bind to a Screen Model declare @RELATION BINDS_TO -> [ModelId].

Forbidden patterns:

  • Creating a new <Modal> when confirm() suffices
  • Building a custom <Select> when $lib/ui/Select.svelte exists
  • Inventing a <Toast> system when addToast() from $lib/toasts.js is already wired

UX / Interaction Validation

Validate the proposed design against ux_reference.md as an interaction reference for operators, API callers, CLI/operator flows, result envelopes, warnings, recovery guidance, and (when applicable) browser-based UI flows.

If the planned architecture degrades the promised interaction model, deterministic recovery path, or context-budget behavior, stop and warn the user.

Attention Compliance Gate (MANDATORY — before generating contracts)

Every contract in contracts/modules.md MUST pass these checks. Contracts that fail are invisible to the model after context compression (per semantics-core §VIII):

Rule Check Failure Consequence
ATTN_1 First anchor line: #region Domain.Sub.Name [C:N] [TYPE Type] [SEMANTICS tag1,tag2] — all on ONE line CSA 4× pooling loses detail from multi-line anchors
ATTN_2 IDs are hierarchical: Core.Auth.Login, not login_handler HCA 128× makes flat IDs indistinguishable from noise
ATTN_3 All contracts in a domain share primary @SEMANTICS keyword (e.g., all auth contracts use [SEMANTICS auth, ...]) DSA Lightning Indexer fails to group domain contracts
ATTN_4 Contract ≤150 lines, module ≤400 lines Contracts exceeding the sliding window are partially invisible

Cross-stack compliance (fullstack features only):

  • Backend Pydantic schema contract and frontend TypeScript DTO contract MUST have matching @RELATION edges crossing the stack boundary.
  • Both MUST share at least one @SEMANTICS keyword so the DSA Indexer can link them.

Data Model Output

Generate data-model.md for ss-tools domain entities such as:

  • Pydantic request/response schemas
  • SQLAlchemy models and relationships
  • WebSocket message formats
  • Task state transitions
  • Git operation entities
  • Plugin configuration schemas
  • Frontend TypeScript DTOs in frontend/src/types/ — MUST match backend Pydantic schemas across the stack boundary
  • Screen Model interfaces — typed atoms, FSM state unions, action payloads for .svelte.ts models

Global ADR Continuity

Before task decomposition, planning must identify any repo-shaping decisions this feature depends on or extends:

  • Python module layout and decomposition
  • FastAPI route organization
  • SvelteKit routing and component hierarchy
  • Screen Model topology: which screens need a model, model-atom boundaries, invariant scope
  • belief-state runtime behavior (JSON structured logging / console markers)
  • semantic comment-anchor rules
  • TypeScript-first frontend architecture (.svelte.ts models, typed props, typed API boundaries)
  • payload/schema stability decisions

Contract Design Output

Generate contracts/modules.md as the primary design contract for implementation. Contracts must:

  • use short hierarchical semantic IDs with 2-3 levels: Domain.Name (e.g., Core.Auth.Login, Api.Dashboards, Users.ListModel, Test.Migration.RunTask). NOT flat IDs like login_handler or UserListModel.
  • classify each planned module/component/model with [C:N] complexity in the #region anchor (NOT @COMPLEXITY N)
  • use canonical anchor syntax: #region Id [C:N] [TYPE TypeName] [SEMANTICS tags] / #endregion Id
  • use canonical relation syntax @RELATION PREDICATE -> TARGET_ID
  • preserve accepted-path and rejected-path memory via @RATIONALE and @REJECTED where needed
  • describe Python modules, FastAPI routes, Svelte components, Screen Models (.svelte.ts), stores, and services instead of inventing MCP/backend layers

Complexity guidance for this repository:

  • C1: anchors only (DTOs, simple Pydantic schemas, pure constants)
  • C2: typically adds @BRIEF (pure functions, utility helpers)
  • C3: typically adds @RELATION (service modules, route handlers); Svelte components also @UX_STATE
  • C4: typically adds @PRE, @POST, @SIDE_EFFECT; Screen Models also @STATE, @ACTION, @INVARIANT; orchestration paths should account for belief runtime markers
  • C5: C4 + @DATA_CONTRACT, @INVARIANT, and explicit decision-memory continuity (@RATIONALE/@REJECTED)

Function-Level Contracts for C3+ (MANDATORY for cross-stack and orchestration)

For every C3+ function, method, or Screen Model action that is:

  • An API endpoint (FastAPI route handler)
  • A Screen Model action with @SIDE_EFFECT
  • A C4/C5 orchestration function (migration runner, task executor, auth flow)

Generate its full #region header in contracts/modules.md under its parent module. This header becomes the implementation contract that the coding agent MUST satisfy.

Minimal header for C3 API endpoints:

#region Domain.Resource.Action [C:3] [TYPE Function] [SEMANTICS domain,action]
# @ingroup Domain
# @BRIEF One-line purpose.
# @RELATION DEPENDS_ON -> [DependencyService]
# @RELATION DEPENDS_ON -> [DTO:RequestSchema]

Full header for C4/C5 orchestration & cross-stack functions:

#region Domain.Resource.Action [C:4] [TYPE Function] [SEMANTICS domain,action]
# @ingroup Domain
# @BRIEF One-line purpose.
# @PRE Precondition 1 (verifiable by guard clause).
# @POST Output guarantee 1 (testable assertion).
# @SIDE_EFFECT State mutation, I/O, or external call.
# @SIDE_EFFECT Logging (REASON/REFLECT/EXPLORE markers required).
# @RELATION DEPENDS_ON -> [ServiceDependency]
# @RELATION DEPENDS_ON -> [DTO:InputSchema]
# @DATA_CONTRACT InputDTO -> OutputDTO
# @RATIONALE Why this implementation approach.
# @REJECTED What alternative was considered and forbidden.
# @TEST_EDGE: scenario_name -> Expected failure behavior.

Screen Model actions (Svelte .svelte.ts):

// #region ScreenModel.actionName [C:4] [TYPE Function] [SEMANTICS domain,action]
// @BRIEF What this action does.
// @ACTION Public action — callable from components.
// @PRE Guards before execution.
// @POST State guarantees after completion.
// @SIDE_EFFECT API call, store mutation, model state update.
// @RELATION CALLS -> [apiClient]
// @TEST_EDGE: network_failure -> ScreenState = "error"

Rules:

  • Function contract headers are NOT implementation — they are design contracts. The coding agent implements the body.
  • C1/C2 functions do NOT need pre-generated contracts — only C3+.
  • @TEST_EDGE declarations enable qa-tester to write tests BEFORE implementation (true TDD).
  • @DATA_CONTRACT on API endpoints enables fullstack-coder to align frontend TypeScript DTOs.
  • @SIDE_EFFECT with belief runtime markers ensures molecular CoT logging is wired from day one.
  • Cross-stack functions MUST have matching @DATA_CONTRACT on both backend and frontend sides.
  • All contracts MUST pass the Attention Compliance Gate (ATTN_1-4) above.

If a planned contract depends on unknown schema, relation target, or ADR identity, emit [NEED_CONTEXT: target] instead of fabricating placeholders.

Fixture Generation (MANDATORY for C3+ contracts with @TEST_EDGE)

For every C3+ contract that declares @TEST_EDGE, @POST, or @REJECTED guardrails, generate canonical test fixtures in FEATURE_DIR/fixtures/. Canonical fixtures live beside the spec — they are the design-time source of truth. Executable fixtures are materialized into tests/ later by /speckit.tasks.

Output structure:

specs/<feature>/fixtures/
├── manifest.md              # Fixture index with GRACE contracts
├── api/
│   ├── <contract>_valid.json
│   ├── <contract>_missing_field.json
│   ├── <contract>_invalid_type.json
│   ├── <contract>_external_fail.json
│   └── <contract>_rejected_path.json
└── model/
    ├── <model>_valid.json
    ├── <model>_edge_case.json
    └── <model>_invariant.json

manifest.md — fixture index with GRACE contracts:

#region FixtureManifest [C:3] [TYPE ADR] [SEMANTICS test,fixture,[DOMAIN]]
@defgroup Fixtures Canonical test fixtures for [FEATURE].

## @{ Fixture FX_Auth.Login.Valid [C:2] [TYPE Block] [SEMANTICS test,auth,fixture]
@BRIEF Valid login request/response pair.
@RELATION VERIFIES -> [Api.Auth.Login]
@TEST_FIXTURE: valid_login -> fixtures/api/auth_login_valid.json
@TEST_INVARIANT: TokenIssued -> VERIFIED_BY: [Test.Api.Auth]
## @} Fixture FX_Auth.Login.Valid

## @{ Fixture FX_Auth.Login.MissingPassword [C:2] [TYPE Block] [SEMANTICS test,auth,fixture]
@BRIEF Missing password field — @TEST_EDGE: missing_field.
@RELATION VERIFIES -> [Api.Auth.Login]
@TEST_EDGE: missing_field -> 422 VALIDATION_ERROR
@TEST_FIXTURE: missing_password -> fixtures/api/auth_login_missing_field.json
## @} Fixture FX_Auth.Login.MissingPassword

## @{ Fixture FX_Migration.EnvReset [C:2] [TYPE Block] [SEMANTICS test,migration,fixture]
@BRIEF Model invariant: changing source env resets selection.
@RELATION VERIFIES -> [Migration.Model]
@TEST_INVARIANT: env_reset_selection -> VERIFIED_BY: [Test.Migration.Model]
@TEST_FIXTURE: env_reset -> fixtures/model/migration_env_reset.json
## @} Fixture FX_Migration.EnvReset

JSON fixture format:

{
  "fixture_id": "FX_Auth.Login.MissingPassword",
  "verifies": "Api.Auth.Login",
  "edge": "missing_field",
  "input": {
    "username": "admin"
  },
  "expected": {
    "status": 422,
    "error_code": "VALIDATION_ERROR",
    "error_detail": "Field 'password' is required"
  }
}

Generation rules:

  • One JSON file per fixture — named <contract_snake>_<edge>.json
  • Minimum 5 per C3+ contract: valid, missing_field, invalid_type, external_fail, rejected_path
  • Expected values ALWAYS hardcoded — never derived from implementation (anti-tautology)
  • Input values are concrete — real strings, numbers, objects, not pseudocode
  • Fixture ID format: FX_<Domain>.<Name> — hierarchical, matches contract hierarchy
  • @TEST_FIXTURE in manifest points to the JSON file path
  • @RELATION VERIFIES links fixture to production contract
  • For @REJECTED paths: expected MUST include error/failure, proving the path is unreachable
  • For model invariants: input = state before action, expected = state after action
  • Do NOT generate executable test files here — only canonical JSON fixtures

Fixture Traceability

Extend traceability.md with a Fixture column:

Story Model Fixture Task Test
US1 Api.Auth.Login FX_Auth.Login.Valid T017 Test.Api.Auth

Quickstart Output

Generate quickstart.md using real repository verification paths:

  • Backend: cd backend && source .venv/bin/activate && python -m pytest -v
  • Frontend: cd frontend && npm run test
  • Lint: cd backend && python -m ruff check .
  • Frontend lint: cd frontend && npm run lint
  • Docker: docker compose up --build

Traceability Matrix Output

If UX contracts exist (contracts/ux/ was generated by /speckit.ux), generate traceability.md — a requirements traceability matrix (RTM) mapping every user story through its implementation chain:

#region Traceability [C:3] [TYPE ADR] [SEMANTICS traceability,rtm,[DOMAIN]]
@defgroup Trace Matrix Requirements → Model → API → Task → Test for [FEATURE].

## Traceability Matrix

| Story | Screen | Model | Fixture | API Endpoint | Backend Task | Frontend Task | Test |
|-------|--------|-------|---------|-------------|-------------|--------------|------|
| US1: [Title] | /route | Domain.Model | FX_Domain.Valid | GET /api/... | T017 | T015 | Test.Domain |
| US1: [Title] | /route | Domain.Model | FX_Domain.MissingField | POST /api/... | T018 | T019 | Test.Domain.Edge |

## Impact Analysis Quick Reference

| If you change... | These fixtures verify it | These tests verify it | These screens depend |
|-----------------|------------------------|----------------------|---------------------|
| `GET /api/dashboards` | FX_Dashboards.Hub.* | Test.Dashboards.Hub | /dashboards, /migration |
| `Dashboards.Hub` model | FX_Dashboards.EnvReset | Test.Dashboards.Hub | /dashboards |

#endregion Traceability

Generation rules:

  • One row per unique (Story, API Endpoint, Screen) tuple
  • Model column: [TYPE Model] contract ID from screen-models.md
  • API column: endpoint from api-ux.md or contracts/modules.md
  • Task columns: task IDs from tasks.md (to be filled after /speckit.tasks — leave as T??? if tasks not yet generated)
  • Test column: test contract ID pattern Test.<Domain>.<Name>
  • Impact table: derived from @RELATION edges in contracts — invert the dependency graph
  • Grep-friendly: grep "Dashboards.Hub" traceability.md → all rows for that model
  • Agent zombie mode: without MCP tools, grep "<contract>" traceability.md replaces impact_analysis

Key Rules

  • Use absolute paths in workflow execution.
  • Planning must reflect the current repository structure (backend/src/**/*.py, frontend/src/**/*.svelte, backend/tests/, docs/adr/*).
  • Do not reference .ai/* or .kilocode/* paths (use .opencode/ for skills).
  • Do not write any feature planning artifact outside specs/<feature>/....
  • Do not hand off to speckit.tasks until blocking ADR continuity and rejected-path guardrails are explicit.