20 KiB
description, handoffs
| description | handoffs | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Execute the implementation planning workflow for ss-tools (Python backend + Svelte frontend) and generate research, design, contracts, and quickstart artifacts. |
|
User Input
$ARGUMENTS
You MUST consider the user input before proceeding (if not empty).
Outline
-
Setup: Run
.specify/scripts/bash/setup-plan.sh --jsonfrom repo root and parseFEATURE_SPEC,IMPL_PLAN,SPECS_DIR, andBRANCH.IMPL_PLANis the authoritative path forplan.mdinsidespecs/<feature>/.- Derive
FEATURE_DIRfromIMPL_PLANand write every planning artifact there. - Never treat
.kilo/plans/*as workflow output for/speckit.plan.
-
Load canonical planning context:
README.mdrequirements.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.mdFEATURE_DIR/contracts/ux/screen-models.md(if/speckit.uxwas run)FEATURE_DIR/contracts/ux/api-ux.md(if/speckit.uxwas run)FEATURE_DIR/contracts/ux/*-ux.md(per-screen UX contracts)- relevant
docs/adr/*.md
-
Execute the planning workflow using the template structure:
- Fill
Technical Contextfor the current repository reality: Python 3.9+/FastAPI backend, SvelteKit 5/Tailwind frontend, PostgreSQL, Docker, semantic contracts, belief runtime. - Fill
Constitution Checkusing the local constitution. - ERROR if a blocking constitutional or semantic conflict is discovered and cannot be justified.
- Phase 0: generate
research.mdinFEATURE_DIR, resolving all material unknowns. - Phase 1: generate
data-model.md,contracts/modules.md, optional machine-readable contract artifacts, andquickstart.mdinFEATURE_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 kilocodeafter planning artifacts are written.
- Fill
-
Stop and report after planning artifacts are complete. Report branch,
plan.mdpath, 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/orfrontend/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.mddefines Model inventory → use directly, don't re-discoverapi-ux.mddefines API shapes → use as @DATA_CONTRACT source for backend Pydantic schemas<screen>-ux.mddefines UX contracts → use as @UX_STATE/@UX_FEEDBACK source for component contracts- Generated
.svelte.tsmodel files infrontend/src/lib/models/→ DO NOT regenerate; reference them via@RELATION BINDS_TOfrom 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.tsextension,[TYPE Model]contract,@STATE/@ACTION/@INVARIANTtags
Step 2: Component scan (priority order):
Scan targets (priority order):
frontend/src/lib/ui/— design-system atoms:Button.svelte,Select.svelte,Input.svelte,Card.sveltefrontend/src/lib/components/ui/— composite UI widgets:SearchableMultiSelect.svelte,MultiSelect.sveltefrontend/src/lib/components/— feature components that may be adaptable- 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>whenconfirm()suffices - Building a custom
<Select>when$lib/ui/Select.svelteexists - Inventing a
<Toast>system whenaddToast()from$lib/toasts.jsis 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
@RELATIONedges crossing the stack boundary. - Both MUST share at least one
@SEMANTICSkeyword 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.tsmodels
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.tsmodels, 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 likelogin_handlerorUserListModel. - classify each planned module/component/model with
[C:N]complexity in the#regionanchor (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
@RATIONALEand@REJECTEDwhere 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_EDGEdeclarations enable qa-tester to write tests BEFORE implementation (true TDD).@DATA_CONTRACTon API endpoints enables fullstack-coder to align frontend TypeScript DTOs.@SIDE_EFFECTwith belief runtime markers ensures molecular CoT logging is wired from day one.- Cross-stack functions MUST have matching
@DATA_CONTRACTon 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
@REJECTEDpaths: 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 fromscreen-models.md - API column: endpoint from
api-ux.mdorcontracts/modules.md - Task columns: task IDs from
tasks.md(to be filled after/speckit.tasks— leave asT???if tasks not yet generated) - Test column: test contract ID pattern
Test.<Domain>.<Name> - Impact table: derived from
@RELATIONedges 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.mdreplacesimpact_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.tasksuntil blocking ADR continuity and rejected-path guardrails are explicit.