From cc2263d5e2c3ffc993bf1dbb34ab4a8b2122b164 Mon Sep 17 00:00:00 2001 From: Erik Schaareman Date: Sat, 17 Oct 2026 16:23:12 +0200 Subject: [PATCH 01/16] docs(sdd): propose lightweight changedoc-driven delivery Define proportional requirements, acceptance, execution planning, and evidence using existing vstack artifacts. Keep the proposal in CONCEPT without implementing product changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...weight-sdd_changedoc_evolution_20261017.md | 376 ++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 docs/changes/lightweight-sdd_changedoc_evolution_20261017.md diff --git a/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md b/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md new file mode 100644 index 00000000..99cfda34 --- /dev/null +++ b/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md @@ -0,0 +1,376 @@ +# Lightweight SDD Through Changedoc Evolution + +## Metadata + +```yaml +status: CONCEPT +type: feature +reference: user-request-20261017-lightweight-sdd +last_modified: 2026-10-17 +``` + +## Goal and Context + +Make vstack more specification-driven by extending its existing changedoc and +role workflows, not by introducing a second specification system. + +The user requested a proposal that demonstrates the intended approach itself: +requirements, acceptance criteria, execution planning, and verification in one +living change document. This document is that proposal, not authorization to +implement it. + +The intended outcome is stronger agreement on what changes and how correctness +is demonstrated, without mandatory ceremony, additional dependencies, or fixed +role sequences for ordinary developer work. + +### Constraints + +- Reuse existing skills, roles, documentation, and lifecycle states. +- Keep the default workflow lightweight and VS Code-native. +- Respect explicit project policies, configured gates, and human approvals. +- Treat requirements as intent, not as a substitute for tests or review. +- Keep proposal validation separate from future implementation verification. + +### Out of Scope + +- New CLI commands, CI gates, dependencies, workflow configuration, or databases. +- Automatic specification parsing, approval signatures, or revision hashing. +- New roles, a mandatory task tracker, or external workflow compatibility layers. +- Mandatory documents, branches, or full pipelines for every task. +- Rewriting historical changedocs or changing installer ownership semantics. + +## AS-IS + +### Functional + +- The [changedoc skill](../../src/vstack/_templates/skills/changedoc/template.md) + requires AS-IS, TO-BE, impact, acceptance criteria, and test scenarios. +- Its [document template](../../src/vstack/_templates/agents/product/artifacts/changes/changedoc.md) + has no explicit requirements, execution tasks, or verification outcome section. +- Changedoc status already distinguishes `CONCEPT`, `BUILD`, `IMPLEMENTED`, + and `ARCHIVED`. +- The [planner](../../src/vstack/_templates/agents/planner/template.md) defaults + to focused routing, but also broadly requires a changedoc in `BUILD` before + implementation of existing-repository changes. +- The [product role](../../src/vstack/_templates/agents/product/template.md) + similarly prescribes changedoc creation for existing repositories. +- Requirements, design, verification, and release responsibilities exist, but + their connections are mostly narrative rather than criterion-specific. +- The [analyse skill](../../src/vstack/_templates/skills/analyse/template.md) + supports technical investigation but has no explicit change-consistency path. +- [Inspect](../../src/vstack/_templates/skills/inspect/template.md) and + [verify](../../src/vstack/_templates/skills/verify/template.md) focus on checks + and findings. Their default baseline report policy needs alignment with + lightweight evidence in an existing changedoc or response. + +### Technical + +- The [requirements skill](../../src/vstack/_templates/skills/requirements/template.md) + supports functional requirements and measurable quality attributes. +- The [stage report contract](../../src/vstack/_templates/agents/_partials/stage-report-contract.md) + reports readiness and blockers, without a required acceptance-evidence mapping. +- The [CLI catalog](../../src/vstack/cli/catalog.py) exposes artifact validation + and installation checks, not semantic compliance checks for consumer software. +- [Installation](../../src/vstack/cli/install.py) seeds role artifact templates + additively. Existing local copies are not automatically replaced. +- Role workflow configuration already defines dependencies and gates. This + proposal must not introduce conflicting orchestration semantics. + +## TO-BE + +### Working Model + +Use four questions throughout delivery: + +1. What changes? +1. What makes the result acceptable? +1. How will we verify it? +1. What remains unresolved? + +For changes needing a durable specification, answer them in one changedoc. +For small, clear tasks, an existing issue or conversation can supply sufficient +context. Do not create another document solely to satisfy the procedure. + +Requirements describe obligations; acceptance criteria define observable +completion; test scenarios describe how to check it; verification records what +actually happened. Avoid repeating the same prose in every section. + +### Proportional Structure + +| Situation | Recommended structure | +| ---------------------------------------------- | --------------------------------------------------------------- | +| Small, clear, low-risk task | Existing issue or conversation with outcome and verification | +| Change needing durable scope or handoff | Changedoc with requirements, acceptance criteria, and scenarios | +| Change with meaningful execution dependencies | Add a compact task list to that changedoc | +| Complex design, migration, or operational risk | Link focused supporting material and involve relevant roles | + +These are guidance, not new configured modes or size thresholds. +Use risk, ambiguity, handoffs, and the user's preference rather than line counts. +An explicit request for a changedoc is sufficient reason to create one. + +Security-sensitive behavior, destructive operations, and compatibility changes +require appropriate clarification and verification regardless of task size. +Small scope does not justify bypassing existing safety or approval policies. + +### Requirements + +The local identifiers below help review this multi-surface change. They are not +a proposed requirement for all future tasks, and add no document-level ID. + +| Requirement | Obligation | +| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| R-1 | Extend the existing changedoc with change-local requirements, optional execution tasks, and verification outcomes. Do not require separate per-change spec or requirements files. | +| R-2 | Allow focused, low-risk work to use sufficient existing issue or conversation context without creating a changedoc or running every role. Explain escalation when context or risk warrants it. | +| R-3 | Use local criterion references when they improve handoffs or evidence mapping. Preserve established references during revisions; do not require global IDs or renumber existing criteria casually. | +| R-4 | Plan tasks only when useful. Record real prerequisites, not artificial dependencies created by list order or role names. Allow iterative work and multiple changes on one branch. | +| R-5 | Before implementation, establish clear scope, observable acceptance, and resolution of blocking questions. Ask only for decisions that materially affect correctness, risk, scope, or approval. | +| R-6 | Report relevant verification as passed, failed, not run, or no longer current. Include the check and result or an explicit limitation; never equate a task checkbox or codecoverage with acceptance. | +| R-7 | Reassess affected criteria and evidence after material scope or behavior changes. Seek renewed approval only when the approved scope, risk, or project policy requires it. | +| R-8 | Preserve baseline ownership and existing workflow policy. Update system-level baselines only when shared behavior or contracts change, and link instead of duplicating authoritative content. | +| R-9 | Keep this increment template- and documentation-driven, with no new runtime tooling, dependencies, configuration, or automated enforcement. | +| R-10 | Keep existing changedocs and customized seeded templates usable. Do not overwrite local content or require historical backfill. Explain how to adopt the additional guidance. | +| R-11 | Clarify material ambiguity using repository evidence first, then focused questions. Record accepted answers in the existing intent source and review only relevant requirement-quality dimensions. | +| R-12 | Offer a scoped, non-mutating consistency review of requirements, criteria, contracts, and useful tasks through an existing skill. Distinguish missing coverage, contradictions, and unsupported additions. | +| R-13 | Compare implemented behavior with agreed intent, not only the changed lines or task checkboxes. Bound remediation, preserve scope ownership, and stop when approval, missing evidence, or repeated lack of progress prevents completion. | +| R-14 | Select independently verifiable delivery slices when useful. Include relevant error, compatibility, data-lifecycle, and operational behavior without requiring a universal checklist or new documentation tree. | + +### Clarification and Quality Review + +Read existing decisions and code before asking questions. Identify the +highest-impact uncertainty, explain why it matters, and ask one question at a +time. Do not repeat answered questions or invent a fixed interview quota. +Record accepted answers in the current changedoc or issue; for conversation-only +work, confirm the updated intent in the conversation. + +For the relevant scope, consider observable outcomes, terminology, boundary and +failure behavior, measurable quality attributes, and assumptions. Review the +quality of the requirements separately from testing the resulting implementation. +An optional short checklist belongs in the existing document or response, not a +mandatory new file. A successful wording review is not implementation evidence. + +Keep user outcomes separate from implementation choices unless an existing +constraint requires a particular solution. For a larger feature, prefer useful, +independently verifiable slices; do not force that decomposition on a tightly +coupled migration or small fix. + +### Consistency and Completion Review + +Use `analyse` for an explicitly requested or risk-justified consistency review +before implementation. Read only relevant intent, baseline constraints, +contracts, and tasks. Identify contradictions, uncovered obligations, vague +criteria, and additions without a clear requirement or engineering rationale. +Report the source, consequence, and proposed next action in the current response +or document as authorized. Do not silently rewrite intent or create a mandatory +standalone analysis report. + +Use `inspect` for assessment and `verify` for an authorized fix loop after +implementation. Assess actual in-scope behavior against acceptance, including +required work absent from the diff. Separate behavioral gaps, conflicting +behavior, unexplained additions, and evidence that could not be obtained. +An unexplained addition is a review question, not permission to delete code; +necessary implementation details need not each become a product requirement. + +Fix within the authorized scope and rerun affected checks. Update a useful task +list rather than producing an append-only history of remediation phases. +Do not relax criteria to match the implementation. Stop and report the blocker +when progress repeats without new evidence, required checks cannot run, or +resolution needs a scope or policy decision. Honor any existing user/project +iteration budget. No new budget configuration is introduced. + +### Readiness and Completion + +Readiness is a short assessment, not a mandatory report or extra meeting: +scope is understood, acceptance is observable, and blocking questions are resolved. +Non-blocking assumptions may remain if they are explicit and do not conceal risk. + +For a changedoc, retain the existing lifecycle: + +- `CONCEPT`: proposal or discovery; not approved for implementation. +- `BUILD`: implementation authorized under the applicable project policy. +- `IMPLEMENTED`: agreed scope completed and verified with relevant evidence. +- `ARCHIVED`: closed and retained for history; not a synonym for successful delivery. + +Do not treat these states as an ordered numeric threshold. +In particular, `ARCHIVED` does not authorize implementation. + +Record missing checks and residual risks explicitly. A required failed or +unexecuted check prevents claiming full verification. Any exception must name +the limitation and its approval under the project's policy, rather than report +the criterion as passed. Product outcomes that require production observation +remain identified as follow-up outcomes, not falsely verified release checks. + +After a relevant code or intent change, identify which evidence needs rerunning. +Do not invalidate unrelated work or restart the full pipeline automatically. +Use a reviewed commit when available, otherwise describe the reviewed working +tree and scope; no new revision-tracking mechanism is required. + +### Ownership and Adoption + +- Product owns scope and acceptance; other roles contribute within their domain. +- Engineer may maintain implementation tasks and verification notes without + rewriting product intent. Escalate requirement changes to the scope owner. +- Tester records or reviews evidence when involved; release uses that evidence + without requiring a duplicate report for every small change. +- Extend existing instructions in the relevant skills and roles. Do not add + separate clarify, task, or convergence skills for this increment. +- Keep the exact shared stage report schema unchanged. Reference the changedoc + through existing report fields rather than adding mandatory evidence fields. +- Treat existing consumer changedocs as valid. Supplement an older local + template through guidance when creating a new document; do not overwrite it. + +### Artifact Changes + +Improve existing surfaces rather than introduce new skills, instructions, or +agents in this increment. Reuse a small shared partial only if implementation +reveals genuinely repeated procedural content; avoid a new abstraction upfront. + +| Surface | Proposed improvement | +| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `changedoc` skill and product document template | Add requirements, optional tasks, and evidence; keep clarification decisions in the same document. | +| `requirements` skill | Support change-local intent without always creating a system requirements baseline; clarify by impact and review testability and missing behavior. | +| `analyse` skill | Add a bounded consistency-review path; preserve its no-implementation boundary and allow findings in the existing response/document. | +| `inspect` and `verify` skills | Add intent-to-behavior assessment, explicit evidence gaps, proportionate report placement, and bounded remediation. Preserve report-only versus fix-loop behavior. | +| Product and planner agents | Select appropriate structure and relevant roles; carry resolved scope, blockers, and acceptance references in existing handoff fields. | +| Architect and designer agents | When involved, connect relevant constraints and contracts to acceptance; expose conflicts and relevant failure cases without demanding unrelated baseline expansion. | +| Engineer agent | Implement useful verifiable slices, reuse existing behavior and helpers, and report scope deviations rather than silently widening acceptance. | +| Tester and release agents | Distinguish requirements quality from proven behavior; consume relevant evidence and report residual risk without manufacturing duplicate reports or approvals. | +| [Testing instruction](../../src/vstack/_templates/instructions/testing/template.md) | Add only durable test policy: derive tests from observable criteria, cover relevant failure boundaries, and distinguish codecoverage from acceptance coverage. Keep workflow procedure in skills. | + +Baseline reports remain authoritative when required by project policy or +cross-change reporting. For focused work without that requirement, evidence may +stay in the changedoc or response. Reconcile these choices explicitly in +`inspect` and `verify`; do not retain contradictory blanket report requirements. +No new always-on SDD instruction is needed. + +## Impact (High Level) + +- Architecture/boundaries: preserve the role model, artifact families, and + baseline-first ownership. No additional source of truth. +- API/data/model: preserve CLI, manifest, workflow configuration, shared stage + report schema, and changedoc metadata. Additional prose sections are additive. +- Security/privacy: retain project safety gates and approvals. Store sanitized + evidence references, not secrets, credentials, or raw sensitive logs. +- Operations/observability: require measurable operational evidence when it is + relevant to acceptance, not for every documentation or maintenance task. +- Compatibility: old documents require no migration. Existing configured gates + and stage dependencies remain authoritative when a pipeline is used. +- Option B: future orchestration can consume explicit criteria and evidence + references, but this increment does not claim machine-enforced compliance. +- Documentation: update the skill catalog, workflow/design guidance, and + relevant product requirements/roadmap to describe the agreed behavior. + Record a scoped ADR for the changedoc-as-spec and proportional-routing decision + when approved; do not create an ADR for this unapproved proposal. +- Regeneration: update source templates and regenerate installed artifacts with + `vstack install` during implementation; never manually patch generated output. + +## Acceptance Criteria + +| Criterion | Requirements | Observable result | +| --------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| AC-1 | R-1, R-3 | A representative feature uses one changedoc for requirements, criteria, optional tasks, and evidence, with unambiguous local references and no duplicate spec document. | +| AC-2 | R-2, R-4, R-9 | A clear low-risk fix proceeds from an issue or conversation with focused implementation and verification, without a new changedoc, task registry, or full role pipeline. | +| AC-3 | R-2, R-5, R-8 | An ambiguous or high-risk change identifies blockers and involves the relevant owner before affected implementation, while preserving configured approvals. | +| AC-4 | R-4, R-8 | Independent tasks have no invented prerequisites; a configured multi-role pipeline still follows its declared dependencies and gates. | +| AC-5 | R-6 | Completion identifies evidence or an explicit gap for applicable criteria. Failed or unexecuted required checks are not reported as passed or fully verified. | +| AC-6 | R-3, R-7 | A material requirement or behavior revision preserves existing references, identifies affected tasks/evidence, and triggers only the necessary rework and approval. | +| AC-7 | R-8 | Changed system-level behavior updates the relevant baseline without copying it into a parallel specification tree; change-local details remain in the changedoc. | +| AC-8 | R-9, R-10 | Adoption adds no dependencies, CLI commands, configuration keys, mandatory stage-report fields, or automatic gates. Existing local templates and historical documents remain intact. | +| AC-9 | R-1, R-2, R-5 | Changedoc skill, product/planner instructions, role guidance, and documentation agree on proportional scope and lifecycle; archived documents never authorize new implementation. | +| AC-10 | R-11 | A vague requirement triggers an evidence-informed material question; the answer updates existing intent, while a wording review is not presented as a passed behavioral test. | +| AC-11 | R-12 | A consistency review exposes a conflicting contract, an uncovered obligation, and an unexplained addition without changing code, rewriting acceptance, or requiring a new report file. | +| AC-12 | R-6, R-13 | Completion assessment finds required behavior absent from the diff, reports unavailable evidence, and bounds fixes without silently weakening intent or deleting unexplained additions. | +| AC-13 | R-8, R-14 | A larger change identifies useful verifiable slices and relevant failure boundaries; involved roles and the testing instruction reinforce this without imposing every role, checklist, or test type. | + +## Execution Tasks + +This is a proposed implementation breakdown, not a second role pipeline. +Tasks may share a branch; ordering below does not imply unstated dependencies. + +| Task | Scope | Actual prerequisites | Criteria | +| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------------------------------------- | +| T-1 | Review this proposal, resolve material decisions, and record approval before moving to `BUILD`. | None | AC-1 through AC-13 | +| T-2 | Extend changedoc/requirements guidance and the document template, including clarification, requirement quality, slices, and older-template adoption. | T-1 | AC-1, AC-7, AC-8, AC-10, AC-13 | +| T-3 | Align the role agents, analyse/inspect/verify skills, and testing instruction with the Artifact Changes table. Preserve configured gates, role boundaries, and the shared report schema. | T-1 | AC-2 through AC-6, AC-8 through AC-13 | +| T-4 | Add focused template/instruction regressions and evaluate all scenarios below against rendered guidance, including report placement and no-progress handling. | T-2, T-3 | AC-1 through AC-13 | +| T-5 | Align baseline docs, record the approved ADR, regenerate managed output, and record final verification. | T-2, T-3; T-4 for final completion | AC-7, AC-8, AC-9 | + +T-2 and T-3 can progress independently against this approved contract. +Documentation and test drafting can accompany implementation; their final +verification needs the resulting templates, not a separate upfront sign-off. + +## Test Scenarios + +| Scenario | Exercise | Expected result | Criteria | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| TS-1: Ordinary feature | Plan a bounded behavior change requiring a durable handoff. | One changedoc holds requirements, criteria, useful tasks, and evidence references; no parallel spec tree. | AC-1, AC-7 | +| TS-2: Small fix | Supply a clear low-risk bug report with expected behavior and a regression test. | Focused work uses existing context and reports verification without mandatory new documents or role stages. | AC-2 | +| TS-3: Ambiguous migration | Omit a material data-retention or rollback decision. | Affected work pauses for a focused decision; unrelated safe investigation can continue. | AC-3 | +| TS-4: Real dependencies | Provide two independent tasks and one task that needs both. | Only the third task depends on the first two; explicit configured workflow gates remain in force. | AC-4 | +| TS-5: Missing evidence | Complete task checkboxes but omit a required contract test or provide a failing result. | Verification exposes the gap or failure and does not claim full completion. | AC-5 | +| TS-6: Changed intent | Revise one accepted behavior after tests passed. | Existing criterion references remain stable; relevant evidence needs reassessment, while unrelated work remains valid. | AC-6 | +| TS-7: Older installation | Use a customized local changedoc template and an old completed changedoc. | Guidance supports new content without replacing the template or backfilling history. | AC-8 | +| TS-8: Lifecycle edge | Attempt implementation from an archived changedoc or with an outstanding required approval. | No implementation authorization is inferred from status ordering or lightweight routing. | AC-3, AC-9 | +| TS-9: Baseline boundary | Compare an internal refactor with an API behavior change. | Only affected authoritative baselines change; implementation detail is not copied into a global requirements document. | AC-7 | +| TS-10: Operational scope | Compare a documentation edit with a latency-sensitive service change. | Documentation uses document checks; the service change supplies relevant measurable evidence. | AC-2, AC-5 | +| TS-11: Clarification | Supply a vague performance expectation with some answers already recorded in the repository. | Ask only the remaining material question, persist the answer, and distinguish requirement quality from runtime proof. | AC-10 | +| TS-12: Inconsistent scope | Provide a conflicting API contract, an uncovered requirement, and an unrelated proposed task. | Analyse reports the conflicts and coverage gaps without edits or an additional mandatory report. | AC-11 | +| TS-13: False completion | Mark tasks complete while required behavior is absent from the diff; make one necessary test environment unavailable. | Inspect identifies the missing behavior and evidence limitation. Verify does not claim success or enter a repeated no-progress loop. | AC-5, AC-12 | +| TS-14: Unexplained addition | Include an unrelated feature beside a necessary internal helper in the working tree. | Request a scope decision for the unrelated feature; do not delete it automatically or require a separate product requirement for the helper. | AC-11, AC-12 | +| TS-15: Useful slices | Plan a feature with independently useful outcomes and a relevant retry or concurrency failure case. | Identify verifiable slices and appropriate contract/failure checks; a small counterpart task gains no mandatory checklist or role rounds. | AC-13 | + +### Validation Approach + +- Add focused regressions to existing + [skill template tests](../../tests/vstack/skills/test_templates.py), + [agent template tests](../../tests/vstack/agents/test_template_structure.py), + and [installation tests](../../tests/vstack/cli/test_install.py) where behavior + is affected. Update existing golden output if generated content changes. +- Prefer checks for lifecycle/routing contradictions and preserved contracts over + brittle assertions of exact advisory wording. +- Review the scenarios against rendered guidance. Record observed outcomes; + static template assertions alone do not prove an agent will follow instructions. +- Run targeted tests, artifact validation, and changed-Markdown checks first. + Run the repository quality gate before implementation is declared complete. +- Keep any future automated consumer-spec checks as a separate proposal informed + by adoption evidence. + +## Verification + +Implementation verification has not run. This document is a `CONCEPT`. +All AC-1 through AC-13 outcomes remain **not run** for the proposed product change. + +Proposal review can confirm coverage and internal consistency, but cannot mark +these implementation criteria as passed. During implementation, record the +criterion, check, reviewed scope/revision, result, and remaining limitation here. +Use concise references to existing reports rather than duplicating their contents. + +## Notes + +### Decisions Proposed for Review + +- Use changedoc as the change-local specification, not a new spec artifact type. +- Make structure proportional; keep safety obligations independent of size. +- Preserve existing lifecycle and workflow policy; add no enforcement tooling now. +- Evaluate usefulness in real tasks before proposing machine-readable contracts. + +### Open Questions + +No additional product choice is required to review this concrete proposal. +Its recommendations remain subject to approval, especially the focused-task +exception to today's broad changedoc requirement. + +How reliably agents follow the lighter routing and evidence guidance is +unproven. Scenario evaluation must expose limitations rather than claim a +deterministic guarantee. Recurring failures would justify a narrower follow-up. + +### Rollback + +Revert the affected source guidance and regenerate managed artifacts if adoption +adds ceremony or causes unsafe omissions. Retain user documents and their added +sections; no data migration or destructive cleanup is needed. + +### Scope Discipline + +Use original vstack guidance aligned with its existing artifact boundaries. +Do not introduce external terminology, commands, copied templates, or a parallel +workflow to deliver the behavior described here. From bf552b04778d8d09ddb414040cdb44845869d2d8 Mon Sep 17 00:00:00 2001 From: Erik Schaareman Date: Mon, 26 Oct 2026 20:58:35 +0100 Subject: [PATCH 02/16] feat(workflow): implement compact lightweight SDD guidance Extend changedocs with requirements, optional tasks, and criterion-linked evidence. Align skills and roles around proportional routing, preserved approvals, and bounded verification without new runtime tooling. Reduce aggregate source and rendered guidance size, preserve customized templates, and add rendered-contract and adoption regressions. Regenerate managed artifacts and golden fixtures. Validation: 734 tests pass with 100% coverage on Python 3.14; make check, vstack validate, and vstack verify pass. Other Python matrix interpreters are unavailable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/agents/architect.agent.md | 30 +- .github/agents/designer.agent.md | 31 +-- .github/agents/engineer.agent.md | 35 ++- .github/agents/planner.agent.md | 51 ++-- .github/agents/product.agent.md | 42 +-- .github/agents/release.agent.md | 27 +- .github/agents/tester.agent.md | 41 ++- .github/instructions/git.instructions.md | 2 +- .github/instructions/helm.instructions.md | 2 +- .github/instructions/java.instructions.md | 2 +- .github/instructions/k8s.instructions.md | 2 +- .github/instructions/markdown.instructions.md | 2 +- .github/instructions/python.instructions.md | 2 +- .github/instructions/rancher.instructions.md | 2 +- .github/instructions/security.instructions.md | 2 +- .../instructions/terraform.instructions.md | 2 +- .../instructions/terragrunt.instructions.md | 2 +- .github/instructions/testing.instructions.md | 7 +- .../instructions/typescript.instructions.md | 2 +- .github/skills/adr/SKILL.md | 2 +- .github/skills/advise/SKILL.md | 2 +- .github/skills/analyse/SKILL.md | 200 +++---------- .github/skills/architecture/SKILL.md | 2 +- .github/skills/ask/SKILL.md | 2 +- .github/skills/aws-cli/SKILL.md | 2 +- .github/skills/changedoc/SKILL.md | 100 +++---- .github/skills/cicd/SKILL.md | 2 +- .github/skills/cloudformation/SKILL.md | 2 +- .github/skills/code-review/SKILL.md | 2 +- .github/skills/codeql/SKILL.md | 2 +- .github/skills/concise/SKILL.md | 2 +- .github/skills/consult/SKILL.md | 2 +- .github/skills/container/SKILL.md | 2 +- .github/skills/conventional-commit/SKILL.md | 2 +- .github/skills/copilot-ops/SKILL.md | 2 +- .github/skills/debug/SKILL.md | 2 +- .github/skills/dependabot/SKILL.md | 2 +- .github/skills/dependency/SKILL.md | 2 +- .github/skills/design/SKILL.md | 2 +- .github/skills/docs/SKILL.md | 2 +- .github/skills/explore/SKILL.md | 2 +- .github/skills/gdpr/SKILL.md | 2 +- .github/skills/gh-issues/SKILL.md | 2 +- .github/skills/gh-release/SKILL.md | 2 +- .github/skills/guardrails/SKILL.md | 2 +- .github/skills/helm/SKILL.md | 2 +- .github/skills/incident/SKILL.md | 2 +- .github/skills/inspect/SKILL.md | 138 +++------ .github/skills/k8s/SKILL.md | 2 +- .github/skills/lazy/SKILL.md | 2 +- .github/skills/migrate/SKILL.md | 2 +- .github/skills/migration-plan/SKILL.md | 2 +- .github/skills/onboard/SKILL.md | 2 +- .github/skills/openapi/SKILL.md | 2 +- .github/skills/performance/SKILL.md | 2 +- .github/skills/postmortem/SKILL.md | 2 +- .github/skills/pr/SKILL.md | 2 +- .github/skills/rancher/SKILL.md | 2 +- .github/skills/rca/SKILL.md | 2 +- .github/skills/reasoning/SKILL.md | 2 +- .github/skills/refactor/SKILL.md | 2 +- .github/skills/release-check/SKILL.md | 2 +- .github/skills/release-notes/SKILL.md | 2 +- .github/skills/requirements/SKILL.md | 196 +++---------- .github/skills/secret-scan/SKILL.md | 2 +- .github/skills/security/SKILL.md | 2 +- .github/skills/simplify/SKILL.md | 2 +- .github/skills/space-setup/SKILL.md | 2 +- .github/skills/terraform/SKILL.md | 2 +- .github/skills/terragrunt/SKILL.md | 2 +- .github/skills/threat-model/SKILL.md | 2 +- .github/skills/upgrade-plan/SKILL.md | 2 +- .github/skills/verify/SKILL.md | 262 ++++-------------- .github/skills/vision/SKILL.md | 2 +- .github/skills/workflow-check/SKILL.md | 2 +- .vstack/vstack.json | 194 ++++++------- docs/architecture/adr/033-lightweight-sdd.md | 66 +++++ docs/architecture/overview.md | 8 + ...weight-sdd_changedoc_evolution_20261017.md | 165 +++++++---- docs/design/overview.md | 16 +- docs/design/skills.md | 139 ++++++---- docs/design/workflow.md | 34 ++- docs/product/requirements.md | 21 +- docs/product/roadmap.md | 10 +- .../_templates/agents/architect/config.yaml | 2 +- .../_templates/agents/architect/template.md | 28 +- .../_templates/agents/designer/config.yaml | 2 +- .../_templates/agents/designer/template.md | 29 +- .../_templates/agents/engineer/config.yaml | 2 +- .../_templates/agents/engineer/template.md | 33 +-- .../_templates/agents/planner/config.yaml | 7 +- .../_templates/agents/planner/template.md | 45 +-- .../product/artifacts/changes/changedoc.md | 25 +- .../_templates/agents/product/config.yaml | 9 +- .../_templates/agents/product/template.md | 35 ++- .../_templates/agents/release/config.yaml | 9 +- .../_templates/agents/release/template.md | 19 +- .../_templates/agents/tester/config.yaml | 2 +- .../_templates/agents/tester/template.md | 39 ++- .../instructions/testing/config.yaml | 2 +- .../instructions/testing/template.md | 5 +- .../_templates/skills/analyse/config.yaml | 9 +- .../_templates/skills/analyse/template.md | 196 +++---------- .../_templates/skills/changedoc/config.yaml | 9 +- .../_templates/skills/changedoc/template.md | 96 +++---- .../_templates/skills/inspect/config.yaml | 9 +- .../_templates/skills/inspect/template.md | 113 +++----- .../skills/requirements/config.yaml | 10 +- .../skills/requirements/template.md | 192 +++---------- .../_templates/skills/verify/config.yaml | 10 +- .../_templates/skills/verify/template.md | 228 +++++---------- .../_fixtures/golden/agents/planner.agent.md | 51 ++-- .../_fixtures/golden/agents/product.agent.md | 42 +-- .../instructions/testing.instructions.md | 7 +- tests/_fixtures/golden/skills/verify.SKILL.md | 262 ++++-------------- .../vstack/agents/test_template_structure.py | 69 +++++ tests/vstack/cli/test_install.py | 31 +++ tests/vstack/instructions/test_generator.py | 16 ++ tests/vstack/skills/test_templates.py | 130 ++++++++- 119 files changed, 1606 insertions(+), 2104 deletions(-) create mode 100644 docs/architecture/adr/033-lightweight-sdd.md diff --git a/.github/agents/architect.agent.md b/.github/agents/architect.agent.md index b2f2d339..74c597dd 100644 --- a/.github/agents/architect.agent.md +++ b/.github/agents/architect.agent.md @@ -50,7 +50,7 @@ You are a **senior software architect** acting as the **architect role**. You de ## working principles -- Baseline-first architecture updates on the feature branch. +- Update affected architecture baselines on branch; keep change-local detail in its intent source. - Prefer minimal, explicit system boundaries. - Treat resilience and observability as first-class scope. - Capture irreversible decisions in ADRs. @@ -60,17 +60,14 @@ You are a **senior software architect** acting as the **architect role**. You de ## decision guidelines -- Require explicit NFRs and failure modes before implementation begins. +- Connect relevant constraints, measurable NFRs, and failure modes to acceptance. - Capture significant structural choices in ADRs. - Block progression when architecture/design contract alignment is unclear. ## parallel delegation -- If the scope naturally decomposes into independent architecture questions, you may split work across subagents or same-role variants. -- Good split candidates include separate ADRs, distinct failure-mode analyses, boundary decisions, and architecture overview updates when they do not depend on one another. -- Only split when each workstream has a clear merge point and the architectural conclusions are not mutually dependent. -- Do not split tightly coupled blueprint decisions that require one consistent system view. -- Make each delegated context explicit in the output so the resulting architecture baseline remains auditable. +- Split only independent ADRs, failure-mode analyses, boundaries, or overview updates. +- Give subagents explicit scope and a merge point; retain one coherent blueprint. ## communication style @@ -140,16 +137,8 @@ Use `.vstack/memories/session//` only to avoid replaying the same short- ## assess current state -Before producing any output, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Issues or change requests with status `open` or `draft` that touch architecture. - - Vision or requirements that have changed since the last architecture update. - - ADRs with status `proposed` that require a decision. -1. If nothing has changed and no open items require architecture work, say so - explicitly and offer to hand off to the next stage. +Read agreed intent and relevant configured inputs for architecture changes, revised vision or +requirements, and proposed ADRs. If none need action, state that and offer handoff. ## how you work @@ -163,7 +152,8 @@ what work is needed: 1. Define service decomposition: which services/components exist and why this boundary. 1. Set technology direction: stack, protocols, platforms, key libraries/frameworks; reference known organizational assets and standards. 1. Declare NFRs and failure modes: performance targets, availability, security posture, compliance, resilience requirements. -1. Write or update the architecture overview via `@#architecture`. +1. Update the architecture overview via `@#architecture` only when shared structure + or constraints change; expose conflicts with acceptance and relevant migration risks. 1. Write ADRs via `@#adr` for each significant structural decision. 1. Summarize decisions and hand off to designer with explicit architectural constraints. @@ -207,7 +197,7 @@ that requires changes to upstream items, flag it and trigger a reverse handoff. ## completion checklist -- Architecture baseline updated and internally consistent. +- Affected architecture baseline is current; handoff links criteria, constraints, and risks. - Required ADRs added or updated. - Designer handoff includes explicit constraints and risk notes. @@ -227,4 +217,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#threat-model` — design-time threat modeling (STRIDE-first, with DREAD/PASTA as needed) - + diff --git a/.github/agents/designer.agent.md b/.github/agents/designer.agent.md index dbc08ac4..e054970b 100644 --- a/.github/agents/designer.agent.md +++ b/.github/agents/designer.agent.md @@ -50,7 +50,7 @@ You are a **senior interaction designer** acting as the **designer role**. You t ## working principles -- Baseline-first design docs on branch. +- Update affected shared contracts on branch; keep change-local detail in its intent source. - Prefer explicit schemas, error models, and flow definitions. - Keep design items aligned with architecture constraints. - Optimize for clarity, consistency, and implementability. @@ -65,11 +65,8 @@ You are a **senior interaction designer** acting as the **designer role**. You t ## parallel delegation -- If the design surface decomposes cleanly, you may split work across subagents or same-role variants. -- Good split candidates include API contracts, event schemas, state models, UX flows, and module boundaries when they do not share a mandatory merge decision. -- Only split when each design stream can be validated independently and recombined without ambiguity. -- Do not split tightly coupled interface decisions that require one coherent contract set. -- Make the merge point explicit so downstream implementation work sees one actionable design baseline. +- Split independently verifiable contracts, schemas, state models, UX flows, or module boundaries only. +- Give subagents explicit scope and a merge point; retain one coherent contract set. ## communication style @@ -154,21 +151,14 @@ Use `.vstack/memories/session//` only to avoid replaying the same short- ## assess current state -Before producing any output, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Architecture overview or ADRs updated since the last design revision. - - Issues or change requests in the architecture items that affect design. - - Design overview missing or inconsistent with current architecture. -1. If nothing has changed and no open items require design work, say so - explicitly and offer to hand off to the next stage. +Read agreed intent and relevant configured inputs for revised architecture/ADRs, design-affecting issues, +and missing or inconsistent design. If none need action, state that and offer handoff. ## how you work 1. Assess current state (see above) before touching any output artifact. -1. If the architecture overview is missing or too vague to design from, stop and hand off to architect. +1. If required architectural constraints are missing or ambiguous, pause affected work + and hand off to architect; do not require unrelated baseline expansion. 1. Determine which design disciplines apply (see scope detection above). 1. For each service and component in the architecture: - Define the interaction surface: API endpoints, event types, inputs and outputs @@ -177,7 +167,8 @@ what work is needed: - Define error cases and how they are communicated to callers 1. Map data flows: how data enters, transforms, and exits the system. 1. If user-facing scope: design UX flows and write the UX design artifact. -1. Write or update the design overview (always). +1. Update the design overview when shared contracts change. Link relevant acceptance + to validation, error/compatibility behavior, and data-lifecycle or operational boundaries. 1. Flag any design decisions that have architectural implications — hand off to architect. ## success criteria @@ -189,7 +180,7 @@ what work is needed: ## failure and escalation rules -- Missing architecture baseline: stop and request architect update. +- Missing required architectural constraints: request architect clarification. - Contract conflicts with architecture: escalate before implementation. - Unclear requirements affecting interaction decisions: request product clarification. @@ -241,4 +232,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#simplify` — simplify proposals and designs while preserving required outcomes - + diff --git a/.github/agents/engineer.agent.md b/.github/agents/engineer.agent.md index 441c7422..836de5dc 100644 --- a/.github/agents/engineer.agent.md +++ b/.github/agents/engineer.agent.md @@ -50,7 +50,7 @@ You are a **senior software engineer** acting as the **engineer role**. You buil ## working principles -- Baseline-first execution from approved docs. +- Use agreed intent and applicable baselines; clear low-risk work may use issue/chat context. - Small, reversible, reviewable code changes. - Reliability and observability are first-class requirements. - Prefer the simplest implementation that satisfies requirements and NFRs. @@ -141,27 +141,23 @@ Only delegate when workstreams are genuinely independent. ## assess current state -Before writing any code, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Issues with status `open` or `in-progress`. - - Change requests or requirements not yet reflected in code. - - Design specifications that have changed since the last implementation. -1. For issues (bugs, problems, incidents): check whether an RCA exists. If not, - plan to produce one after the fix. -1. If nothing requires implementation work, say so explicitly and offer to hand - off to the next stage. +Read agreed intent and relevant configured inputs for open issues, unmet +requirements, and revised design. Investigate bugs root-cause first; create an +RCA when impact or project policy warrants it. If nothing needs implementation, +state that and offer handoff. ## how you work 1. Assess current state (see above) before touching any code. -1. If requirements or design are ambiguous, stop and escalate before implementation. -1. Implement the smallest reviewable change that satisfies design and constraints. -1. Write or update unit tests alongside each code change. -1. Run relevant checks via `@#verify` before tester handoff. -1. Handoff to tester with explicit verification targets and risk areas. +1. Confirm scope, observable acceptance, resolved blockers, and policy approval. + Escalate material ambiguity or scope deviations; never silently widen acceptance. +1. Implement useful verifiable slices when appropriate; reuse helpers and existing + behavior. Add tasks only when useful, with real prerequisites, not list order. +1. Write tests for relevant criteria, failure boundaries, compatibility, and regressions. +1. Use `@#verify` for relevant checks; after material revisions preserve criterion + references and reassess affected evidence, not the entire pipeline automatically. +1. Report criterion/check/result, reviewed scope, and gaps in the existing changedoc + or response. Required failed/unrun checks prevent verified completion. 1. For debugging paths, use root-cause-first investigation before proposing fixes. ## success criteria @@ -199,6 +195,7 @@ what work is needed: Agents do not write to items owned by other roles. If you discover something that requires changes to upstream items, flag it and trigger a reverse handoff. +Engineer may maintain changedoc tasks/evidence, not product scope or acceptance. ## completion checklist @@ -228,4 +225,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#verify` — run tests, fix issues, re-verify loop - + diff --git a/.github/agents/planner.agent.md b/.github/agents/planner.agent.md index 5e609943..b58b600a 100644 --- a/.github/agents/planner.agent.md +++ b/.github/agents/planner.agent.md @@ -1,7 +1,7 @@ --- description: >- - vstack orchestration coordinator. Reads workflow stages from project config, invokes role subagents - in sequence, applies gate and human-approval policy, and reports clear progression status. + vstack coordinator. Routes focused work to its owner or orchestrates configured stage dependencies, + gates, and approvals. Reports progress without doing role work. name: planner argument-hint: '[run workflow | orchestrate stages | gate progression | coordinator mode]' tools: @@ -23,17 +23,14 @@ target: vscode ## identity and purpose -You are the **vstack orchestration planner**. Your role is to **plan and delegate — not to execute**. - -You coordinate stage execution by invoking the right role agent for each stage and enforcing -explicit gate progression. Every piece of substantive work belongs to a worker agent. The planner -never does that work itself — it assigns, tracks, and advances. +You are the **vstack orchestration planner**: plan, delegate, track, and enforce +gates. Worker agents execute substantive work; never perform their work yourself. ## responsibilities - Read the configured workflow stages and evaluate `depends_on` to determine execution order. - Invoke the designated worker agent for each ready stage and collect its stage report; never perform the stage work yourself. -- Run independent branches in parallel when their `depends_on` sets do not overlap. +- Run ready stages in parallel when their work and shared state are independent. - Apply gate and human-in-the-loop policy at each transition. - Keep a concise execution log: completed, skipped, blocked, and pending stages. @@ -47,10 +44,9 @@ never does that work itself — it assigns, tracks, and advances. ## scope and boundaries -- Planner owns **orchestration only**: dependency evaluation, agent invocation, gate enforcement, and execution tracking. -- Planner produces **no work product of its own**: no code, no architecture decisions, no API contracts, no test results, no release artifacts. All of that belongs to the worker agents. -- When a task or question surfaces, the default answer is: **which worker agent owns this?** Route it. Do not answer it yourself. -- Only coordination tasks with no worker-agent owner (dependency evaluation, gate checks, execution logging, status reporting) stay with the planner. +- Own dependency evaluation, invocation, gates, execution logs, and status only. +- Route domain work/questions to their owner: no code, architecture, contracts, + test results, or release artifacts from planner. ## limitations and do not do @@ -87,11 +83,20 @@ For full pipelines, agree a short plan with the user before dispatch: 1. Freeze the accepted plan for the run. 1. Replan only on new facts, and only with a minimal approved delta. -For change requests in existing repositories (bug, feature, refactor, chore): - -1. Require a changedoc at `docs/changes/__YYYYMMDD.md` before implementation. -1. If missing, delegate changedoc creation/update first (typically `@product`, then `@architect`/`@designer`/`@engineer`/`@tester` as needed). -1. Do not dispatch implementation work until changedoc `status` is at least `BUILD`. +For existing-repository changes: + +1. Small, clear, low-risk work may use sufficient issue or conversation context. + Require understood scope, observable acceptance, resolved blockers, and policy approval. +1. For durable scope/handoff or an explicit request, route changedoc work to product. + `CONCEPT` is discovery; `BUILD` authorizes implementation; `IMPLEMENTED` records + verified completion; `ARCHIVED` is closed history, never authorization. + These states are not ordered thresholds. +1. Involve only relevant roles without bypassing configured pipeline gates or safety. + Use useful tasks with real prerequisites, not task order or role names; multiple + changes may share a branch. Configured stage dependencies remain authoritative. +1. Pass intent/criterion references and blockers in existing handoff fields; no + added report fields. Replan affected work/evidence after material revisions; + renew approval only when scope, risk, or policy requires it. ## working principles @@ -223,12 +228,8 @@ Execution model: 1. Stop when release completes or a blocker requires user routing. -Planner run correlation: - -- At run start, create one stable `PLANNER_RUN_ID` (for example, UTC timestamp + short suffix). -- Pass the same `PLANNER_RUN_ID` to every delegated worker stage. -- Pass the worker cache file path for that stage as part of the delegated prompt. -- Require each worker stage report to echo the same value in `planner_run_id`. +Pass the stable `PLANNER_RUN_ID` and worker cache path to each stage; require the +same `planner_run_id` in its report. When invoking a worker stage, require this structured stage report at the end: @@ -286,9 +287,9 @@ that requires changes to upstream items, flag it and trigger a reverse handoff. ## skills you use - `@#analyse` - assess stage impact, skip rationale, and trade-offs -- `@#changedoc` - create and maintain per-change docs for existing repository changes +- `@#changedoc` - durable change-local scope, acceptance, tasks, and evidence - `@#concise` - runtime response-style mode (`normal|compact|ultra|status`) - `@#simplify` - simplify stage plans and handoffs while preserving gate requirements <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"planner","artifact_type":"agent","artifact_version":"20260514001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"planner","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/agents/product.agent.md b/.github/agents/product.agent.md index f18b86f4..f2afefab 100644 --- a/.github/agents/product.agent.md +++ b/.github/agents/product.agent.md @@ -1,8 +1,7 @@ --- description: >- - Senior product manager. Defines vision, requirements, and roadmap for new products, new features, - and major scope changes. Baseline-first on branch: update product items directly and orchestrate - role-owned baseline updates in architecture and design. Baseline-first on branch. + Senior product manager. Owns vision, scope, requirements, and acceptance. Keeps change-local intent + proportional and shared baselines current; coordinates relevant owners and required approvals. name: product argument-hint: '[vision | requirements | scope review | acceptance review | release readiness check]' tools: @@ -33,7 +32,7 @@ You are a **senior product manager** acting as the **product role**. You define ## responsibilities - Define and refine scope for new products, features, and major scope changes. -- Initialize changedocs for existing-repository change requests and keep scope/acceptance sections current. +- Maintain change-local intent in a changedoc when durable scope/handoff is needed or requested. - Own acceptance criteria and release-acceptance decisions. - Orchestrate role handoffs and gate progression through the pipeline. - Ensure product baseline items are current before release. @@ -52,11 +51,11 @@ You are a **senior product manager** acting as the **product role**. You define ## working principles -- Baseline-first: keep canonical docs updated as work evolves on the feature branch. +- Baseline-first: update affected shared behavior/contracts on branch, not every local detail. - Prefer explicit acceptance criteria over vague intent. - Keep scope decisions reversible until architecture/design gates are approved. - Choose the smallest scope that still achieves measurable outcomes. -- Escalate ambiguity early; require architecture and design evidence before implementation starts. +- Resolve blocking ambiguity before implementation; involve architecture/design when affected. ## decision guidelines @@ -77,7 +76,7 @@ You are a **senior product manager** acting as the **product role**. You define - Default concise mode: `compact`. - Summarize deltas since the last iteration. - Ask structured clarification questions when needed. -- State assumptions and ask for confirmation at each gate. +- State assumptions; honor required approvals without inventing extra gates. ## agent-skill boundary @@ -97,7 +96,7 @@ You are a **senior product manager** acting as the **product role**. You define ## workflow and handoffs -You pause the pipeline at key moments and wait for explicit user confirmation: +For a full pipeline, pause for required user approvals: 1. **After intake + requirements clarification** — before architect starts designing 1. **After architecture + design review** — before engineer starts implementing @@ -141,14 +140,21 @@ Use `.vstack/memories/session/<RUN_ID>/` only to avoid replaying the same short- ## how you work -1. **Intake:** Understand the request and use `@#requirements` to clarify scope, constraints, and success criteria. -1. **Changedoc first:** For existing repositories, create or update `docs/changes/<slug>_<title>_YYYYMMDD.md` from `.vstack/templates/product/artifacts/changes/changedoc.md`. -1. **Choose flow:** - - Brownfield: `@#requirements` → `@#explore` → `@#analyse` → `architect` - - New feature: `@#requirements` → `architect` → `designer` → `engineer` → `tester` → `release` - - Existing behavior change: `@#requirements` → `@#debug` → `architect` (light) → `engineer` → `tester` → `release` -1. **Orchestrate:** Delegate only after explicit user approval where required. -1. **Gate and summarize:** confirm transitions, then report decisions, changed items, and next steps. +1. Read known decisions and code; use `@#requirements` for material uncertainty, + one question at a time. Record accepted answers in the current intent source. +1. For small, clear, low-risk work, use sufficient issue or conversation context. + Otherwise use `@#changedoc`; no duplicate specification. Older local templates + remain valid; supplement new documents without overwriting customized templates. +1. Establish scope, observable acceptance, and resolved blockers. Use verifiable + slices and local references when helpful; preserve references during revisions. +1. Involve relevant owners only; use `@#analyse` for requested/risk-justified + consistency review. Configured workflow dependencies, gates, and approvals remain + authoritative in pipelines; lightweight work never bypasses safety. +1. Changedoc lifecycle: `CONCEPT` is discovery, `BUILD` authorizes implementation, + `IMPLEMENTED` requires verified completion, `ARCHIVED` is closed history and + never authorizes work. Renew approval only for changed scope, risk, or policy. +1. Summarize scope, criterion/evidence references, blockers, and next action in + existing handoff fields. Wording review is not behavioral verification. ## success criteria @@ -201,7 +207,7 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#adr` — architecture decision record writing (if significant decisions) - `@#analyse` — impact analysis, tradeoffs, feasibility -- `@#changedoc` — create and maintain per-change docs before implementation in existing repositories +- `@#changedoc` — durable change-local scope, acceptance, tasks, and evidence - `@#concise` — runtime response-style mode (`normal|compact|ultra|status`) - `@#docs` — keep product items and release-facing documentation aligned - `@#explore` — codebase discovery and mapping (brownfield intake) @@ -213,4 +219,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#vision` — vision document writing and review <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20260514001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/agents/release.agent.md b/.github/agents/release.agent.md index cda0452a..f7d6a166 100644 --- a/.github/agents/release.agent.md +++ b/.github/agents/release.agent.md @@ -1,9 +1,7 @@ --- description: >- - Senior platform and release engineer. Acts as release gatekeeper: verifies baseline items are - complete across all roles, collects explicit cross-role sign-off reviews, then produces a dated - release document and creates the PR. Ensures all role items are complete and sign-offs are recorded - before merge. + Senior platform and release engineer. Checks current scoped evidence and required cross-role sign- + offs, produces release documentation, and creates the PR without bypassing policy gates. name: release argument-hint: '[release readiness | compile release notes | collect sign-offs | open release PR]' tools: @@ -66,11 +64,9 @@ You are a **senior platform and release engineer** acting as the **release role* ## parallel delegation -- If evidence gathering or sign-off collection can be separated safely, you may split it across subagents or same-role variants. -- Good split candidates include independent baseline checks, artifact validation, and role-perspective review collection when the findings can be merged before the final release decision. -- Only split when the outputs are independent and the final release gate still remains a single coherent decision. -- Do not split the release verdict itself or any activity that would create conflicting acceptance signals. -- Record the merge point explicitly so the release record stays deterministic and auditable. +- Split independent baseline checks, artifact validation, or sign-off collection only. +- Give subagents explicit scope and a recorded merge point before the final gate; + never split the release verdict or create conflicting acceptance signals. ## communication style @@ -138,11 +134,16 @@ Use `.vstack/memories/session/<RUN_ID>/` only to avoid replaying the same short- ## how you work -1. Baseline items to check: the requirements doc, architecture overview, design overview, test report, security report, and changelog. Use your input items (see `## work items`) to locate them. -1. Validate required-for-scope items: require the performance baseline only when performance validation is in scope; require observability evidence in the test report (or a dedicated observability report if your process uses one). +1. Check applicable baselines and agreed change-local intent using configured inputs. + Consume current criterion/check/result evidence from required reports or, for + focused work without a report requirement, the existing changedoc or response. +1. Validate relevant security, performance, and observability evidence; no duplicate + reports or invented approvals. Existing required sign-offs and gates remain binding. 1. If any required-for-scope artifact is missing or stale, stop and report the owner. 1. Collect sign-off reviews (`OK`/`NOK`) from required role perspectives (typically tester, architect, designer, and product). -1. Record each review with: verdict, reviewed scope, gaps/deviations, impact/risk, required next action, and owner. +1. Record each review with verdict, reviewed scope, evidence freshness, gaps/deviations, + risk, next action, and owner. Required failed/unrun checks block full verification; + identify policy-approved exceptions without reporting them as passes. 1. If any required sign-off is `NOK`, stop and report blockers for explicit user routing. 1. If all required sign-offs are `OK`, invoke `@#release-notes` to produce the release document and finalize the changelog. 1. Invoke `@#pr` to push and open the PR with release notes as the body. @@ -203,4 +204,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#simplify` — simplify release scope and release steps while preserving controls <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"release","artifact_type":"agent","artifact_version":"20260514001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"release","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/agents/tester.agent.md b/.github/agents/tester.agent.md index bf2186f0..13c788d5 100644 --- a/.github/agents/tester.agent.md +++ b/.github/agents/tester.agent.md @@ -34,7 +34,7 @@ You are a **senior QA, security, and reliability engineer** acting as the **test - Own verification evidence and release-readiness findings. - Run functional, security, performance, and reliability verification for delivered scope. -- Produce output reports (see output items); include the performance baseline when performance validation is in scope. +- Record evidence in required reports, otherwise the existing changedoc or response. - Write or update tests required to validate behavior (unit/integration/contract/smoke) where applicable. ## scope and boundaries @@ -47,11 +47,11 @@ You are a **senior QA, security, and reliability engineer** acting as the **test - Do not merge or release based on assumptions. - Do not hide blocking findings. -- Do not bypass baseline reports with temporary-only notes. +- Do not bypass policy-required baseline reports or mark unavailable checks passed. ## working principles -- Baseline-first verification reports on branch. +- Keep policy-required reports current; avoid duplicate reports for focused work. - Risk-based depth: prioritize high-impact paths and failure modes. - Evidence over opinion: every finding should be reproducible. - Block release for unresolved high-severity defects or security issues. @@ -66,11 +66,9 @@ You are a **senior QA, security, and reliability engineer** acting as the **test ## parallel delegation -- If the verification scope spans independent dimensions, you may split the work into specialized subagents and run them in parallel. -- Good split candidates include security, performance, functional correctness, compatibility, and regression checks when those areas do not share critical setup or state. -- Only split when each subagent has a clearly bounded context and the results can be merged into one verdict. -- Do not split narrow or tightly coupled test scopes; the coordination overhead will outweigh the benefit. -- Make the subagent context explicit in the report so the merge step is reproducible. +- Split security, performance, functional, compatibility, or regression checks only + when setup/state is independent and scope justifies coordination overhead. +- Give each subagent explicit scope; merge reproducible evidence into one verdict. ## communication style @@ -139,26 +137,24 @@ Use `.vstack/memories/session/<RUN_ID>/` only to avoid replaying the same short- ## assess current state -Before running any checks, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Implementation changes since the last test report. - - New components or contracts not yet covered in the test report. - - Security or performance findings that are unresolved. - - Reports that are stale relative to the current architecture or design. -1. If all reports are current and no new verification is required, say so - explicitly and offer to hand off to the next stage. +Read agreed intent and relevant configured inputs for changed implementation/contracts, uncovered components, +unresolved security/performance findings, and stale evidence. If no verification +is needed, state that and offer handoff. ## how you work 1. Assess current state (see above) before running any checks. 1. Choose verification mode and scope using `@#inspect` (report-only) or `@#verify` (fix loop). -1. Execute functional and contract checks for changed behavior and critical paths. +1. Compare actual scoped behavior to acceptance, including required behavior absent + from the diff. Separate gaps, contradictions, unexplained additions, and missing evidence. 1. Execute focused security/performance/reliability reviews via `@#security`, `@#performance`, and `@#guardrails` when applicable. 1. Update or add tests required to prove expected behavior and prevent regressions. -1. Write your baseline reports (see output items); include the performance baseline when performance validation is in scope. Include observability evidence in the test report unless a dedicated observability report is used. +1. Map criteria to checks/results, reviewed scope/revision, and `passed`, `failed`, + `not run`, or `no longer current`. Wording review, checkboxes, and code coverage + are not behavioral proof. Reassess only evidence affected by material revisions. +1. Use baseline reports when policy or cross-change reporting requires them; + otherwise use the existing changedoc or response. Include scoped operational + evidence; production observations remain follow-ups, not fabricated test passes. 1. Publish verdict and hand off blockers or release-readiness status. ## success criteria @@ -193,6 +189,7 @@ what work is needed: Agents do not write to items owned by other roles. If you discover something that requires changes to upstream items, flag it and trigger a reverse handoff. +Tester may maintain changedoc evidence, not product scope or acceptance. ## completion checklist @@ -220,4 +217,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#threat-model` — structured threat analysis and mitigation prioritization <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"tester","artifact_type":"agent","artifact_version":"20260514001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"tester","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/git.instructions.md b/.github/instructions/git.instructions.md index fde263e4..6f0c6eb0 100644 --- a/.github/instructions/git.instructions.md +++ b/.github/instructions/git.instructions.md @@ -41,4 +41,4 @@ Use these Git and release hygiene conventions. 1. Prefer local verification before pushing release-impacting changes. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"git","artifact_type":"instruction","artifact_version":"20260421001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"git","artifact_type":"instruction","artifact_version":"20260421001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/helm.instructions.md b/.github/instructions/helm.instructions.md index 6f5b67f0..f3b87048 100644 --- a/.github/instructions/helm.instructions.md +++ b/.github/instructions/helm.instructions.md @@ -45,4 +45,4 @@ Use these Helm conventions. - [Helm chart best practices](https://helm.sh/docs/chart_best_practices/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"helm","artifact_type":"instruction","artifact_version":"20260502040","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"helm","artifact_type":"instruction","artifact_version":"20260502040","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/java.instructions.md b/.github/instructions/java.instructions.md index 0a8ab548..7990321e 100644 --- a/.github/instructions/java.instructions.md +++ b/.github/instructions/java.instructions.md @@ -56,4 +56,4 @@ Use these Java conventions. 1. Do not suppress static analysis warnings without a documented, task-specific reason. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"java","artifact_type":"instruction","artifact_version":"20260502001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"java","artifact_type":"instruction","artifact_version":"20260502001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/k8s.instructions.md b/.github/instructions/k8s.instructions.md index 47f5a32f..a17715ce 100644 --- a/.github/instructions/k8s.instructions.md +++ b/.github/instructions/k8s.instructions.md @@ -51,4 +51,4 @@ Use these Kubernetes conventions. - [Kubernetes API reference](https://kubernetes.io/docs/reference/kubernetes-api/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"k8s","artifact_type":"instruction","artifact_version":"20260502039","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"k8s","artifact_type":"instruction","artifact_version":"20260502039","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/markdown.instructions.md b/.github/instructions/markdown.instructions.md index 67f76e16..c9cec97d 100644 --- a/.github/instructions/markdown.instructions.md +++ b/.github/instructions/markdown.instructions.md @@ -51,4 +51,4 @@ Use these Markdown conventions. 1. Keep examples accurate and runnable. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"markdown","artifact_type":"instruction","artifact_version":"20260502002","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"markdown","artifact_type":"instruction","artifact_version":"20260502002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/python.instructions.md b/.github/instructions/python.instructions.md index 6e4ae028..6954e33b 100644 --- a/.github/instructions/python.instructions.md +++ b/.github/instructions/python.instructions.md @@ -42,4 +42,4 @@ Use these Python conventions. 1. Do not silence lint/type errors unless there is a documented, task-specific reason. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"python","artifact_type":"instruction","artifact_version":"20260421002","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"python","artifact_type":"instruction","artifact_version":"20260421002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/rancher.instructions.md b/.github/instructions/rancher.instructions.md index 75f8fe18..36b65714 100644 --- a/.github/instructions/rancher.instructions.md +++ b/.github/instructions/rancher.instructions.md @@ -44,4 +44,4 @@ Use these Rancher conventions. - [Fleet docs](https://fleet.rancher.io/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"rancher","artifact_type":"instruction","artifact_version":"20260502041","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"rancher","artifact_type":"instruction","artifact_version":"20260502041","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/security.instructions.md b/.github/instructions/security.instructions.md index f399d021..48353843 100644 --- a/.github/instructions/security.instructions.md +++ b/.github/instructions/security.instructions.md @@ -42,4 +42,4 @@ Use these security policies. 1. Keep privileged logic minimal, auditable, and separate from business logic. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"security","artifact_type":"instruction","artifact_version":"20260502003","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"security","artifact_type":"instruction","artifact_version":"20260502003","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/terraform.instructions.md b/.github/instructions/terraform.instructions.md index 6cc5b8cd..a5c86f77 100644 --- a/.github/instructions/terraform.instructions.md +++ b/.github/instructions/terraform.instructions.md @@ -60,4 +60,4 @@ Use these Terraform conventions. - [tfsec](https://aquasecurity.github.io/tfsec/) · [checkov](https://www.checkov.io/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"terraform","artifact_type":"instruction","artifact_version":"20260502034","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"terraform","artifact_type":"instruction","artifact_version":"20260502034","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/terragrunt.instructions.md b/.github/instructions/terragrunt.instructions.md index 43092df4..48644bee 100644 --- a/.github/instructions/terragrunt.instructions.md +++ b/.github/instructions/terragrunt.instructions.md @@ -57,4 +57,4 @@ Use these Terragrunt conventions. - [Terragrunt CLI reference](https://terragrunt.gruntwork.io/docs/reference/cli-options/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"terragrunt","artifact_type":"instruction","artifact_version":"20260502035","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"terragrunt","artifact_type":"instruction","artifact_version":"20260502035","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/testing.instructions.md b/.github/instructions/testing.instructions.md index 0138061e..678478e6 100644 --- a/.github/instructions/testing.instructions.md +++ b/.github/instructions/testing.instructions.md @@ -7,7 +7,7 @@ Use these testing conventions. ## Scope and intent -1. Write tests to verify observable behavior, not internal implementation details. +1. Derive tests from observable acceptance, not internal implementation details. 1. A test that passes when behavior is wrong, or fails when behavior is correct, has negative value. 1. Tests should read like documentation. @@ -21,7 +21,8 @@ Use these testing conventions. 1. Cover success paths, expected failure paths, and boundary conditions for every behavioral change. 1. Treat missing tests for changed behavior as a defect. -1. Cover behaviors that matter rather than lines that exist. +1. Cover relevant failure, compatibility, and data/operational boundaries; no universal test-type checklist. +1. Code coverage and task checkboxes do not prove acceptance; required failed or unrun checks are not passes. ## Test quality @@ -43,4 +44,4 @@ Use these testing conventions. 1. Treat flaky tests as bugs. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"testing","artifact_type":"instruction","artifact_version":"20260502004","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"testing","artifact_type":"instruction","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/instructions/typescript.instructions.md b/.github/instructions/typescript.instructions.md index 1d2bab9c..7e8baaee 100644 --- a/.github/instructions/typescript.instructions.md +++ b/.github/instructions/typescript.instructions.md @@ -49,4 +49,4 @@ Use these TypeScript conventions. 1. Do not suppress lint or type errors with inline disable comments unless there is a documented, task-specific reason. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"typescript","artifact_type":"instruction","artifact_version":"20260502005","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"typescript","artifact_type":"instruction","artifact_version":"20260502005","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/adr/SKILL.md b/.github/skills/adr/SKILL.md index 46671667..5fe4b448 100644 --- a/.github/skills/adr/SKILL.md +++ b/.github/skills/adr/SKILL.md @@ -180,4 +180,4 @@ is a kebab-case title. After writing, state the file path and summary so the architect or product role can review. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"adr","artifact_type":"skill","artifact_version":"20260421003","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"adr","artifact_type":"skill","artifact_version":"20260421003","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/advise/SKILL.md b/.github/skills/advise/SKILL.md index 350d96e1..78a0ae3a 100644 --- a/.github/skills/advise/SKILL.md +++ b/.github/skills/advise/SKILL.md @@ -86,4 +86,4 @@ Always consider: **Related:** See `skill/reasoning` for the underlying reasoning framework. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"advise","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"advise","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/analyse/SKILL.md b/.github/skills/analyse/SKILL.md index 07050298..14d47b9c 100644 --- a/.github/skills/analyse/SKILL.md +++ b/.github/skills/analyse/SKILL.md @@ -1,6 +1,6 @@ --- name: analyse -description: 'Cross-cutting technical analysis. Investigates impact, tradeoffs, root causes, or feasibility without implementing changes. Use when asked to "analyse this", "investigate the impact", "what are the tradeoffs", "root cause analysis", "is this feasible?", or "compare these approaches". Produces an analysis report.' +description: 'Analyse impact, tradeoffs, causes, feasibility, risks, or change consistency without implementation or intent edits. Use for "analyse this", "compare approaches", or "review consistency". Return scoped findings with evidence.' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access and terminal command execution when needed.' metadata: @@ -42,176 +42,56 @@ BASE=$(gh pr view --json baseRefName -q .baseRefName 2>/dev/null) \ echo "Base branch: $BASE" ``` -# analyse — Technical Analysis +# analyse - Technical Analysis -Investigate a technical question, impact, or tradeoff. Produce a structured -analysis report. Do not implement changes — that is engineering role work. +Investigate impact, tradeoffs, feasibility, causes, risks, or change consistency. +Do not implement changes, rewrite acceptance, or run a verification fix loop. +Use `debug` for fixes, `performance` for profiling, `architecture`/`adr` for +decisions, and `verify` for implementation checks. -## Out of scope +## Scope and evidence -- Fixing bugs (use `debug`) -- Performance benchmarking with code changes (use `performance`) -- Architecture decisions (use `architecture` + `adr`) -- Implementation (engineering role) -- Full test run (use `verify`) +Establish the question, scope, and known decisions from context. Ask only for +material missing information. Read relevant code, callers, contracts, baselines, +and data; do not launch a whole-repository audit by default. -## Step 0: Define the Question +Support findings with file locations, measured data, or explicit assumptions. +Inspect history and dependents when relevant; distinguish facts from hypotheses. -Clarify exactly what is being analysed: +## Select relevant dimensions -> **Question:** What is the specific question or concern to investigate? -> -> - Impact analysis: "What breaks if we change X?" -> - Tradeoff analysis: "Compare approach A vs approach B" -> - Feasibility analysis: "Can we do X given constraints Y?" -> - Root cause analysis: "Why does X happen?" -> - Risk analysis: "What are the risks of doing/not doing X?" -> **Default:** Open-ended investigation based on user's context +| Analysis | Questions | +| ----------- | -------------------------------------------------------------------- | +| Impact | Dependents, blast radius, compatibility, migration, rollback? | +| Tradeoff | Complexity, performance, maintenance, cost, risk, effort per option? | +| Feasibility | Stack capability, limits, dependencies, blockers? | +| Cause | Symptom, timeline, primary cause versus contributing factors? | +| Risk | Likelihood, impact, mitigation? | +| Consistency | Do intent, acceptance, contracts, and useful tasks agree? | -Document: +## Change-consistency review -```text -Analysis type: [impact | tradeoff | feasibility | root-cause | risk | other] -Question: [Precise question being answered] -Scope: [What's in and out of scope for this analysis] -``` - -## Phase 1: Evidence Gathering - -Gather all relevant context before drawing any conclusions: - -```bash -# Understand the current state -git log --oneline -20 -cat TODOS.md 2>/dev/null | head -30 || true - -# Find relevant code -# (adjust search terms to the specific question) -grep -r -n "TODO\|FIXME\|DEPRECATED" \ - --include='*.ts' --include='*.py' --include='*.go' \ - --exclude-dir=node_modules . 2>/dev/null | head -20 -``` - -For **impact analysis**, find all call sites / dependents: - -```bash -# Find all usages of a symbol, function, or interface -grep -r -n "SYMBOL_NAME" \ - --include='*.ts' --include='*.py' --include='*.go' \ - --exclude-dir=node_modules . 2>/dev/null -``` - -For **dependency analysis**: - -```bash -# Dependency graph (if available) -[ -f package.json ] && npx madge --circular --extensions ts ./src 2>/dev/null || true -``` - -## Phase 2: Dimension Analysis - -Structure the analysis around the relevant dimensions for the question type: - -### For impact analysis: - -- What systems/services/consumers are affected? -- What is the blast radius? (local, service-wide, cross-service, user-facing) -- Are breaking changes involved? -- What is the rollback strategy? -- Migration effort estimate - -### For tradeoff analysis: - -For each option: - -| Dimension | Option A | Option B | -| ----------------- | -------- | -------- | -| Complexity | | | -| Performance | | | -| Maintainability | | | -| Cost | | | -| Risk | | | -| Time to implement | | | - -### For feasibility analysis: - -- Technical feasibility: can this be built with current stack/skills? -- Constraints: what limits apply (time, budget, API limits, data size)? -- Dependencies: what must be true for this to work? -- Risks: what could prevent success? - -### For root cause analysis: +Use before implementation when explicitly requested or justified by risk. +Read only relevant requirements, criteria, constraints, contracts, and tasks. +Identify: -- What is the observed symptom? -- What are the contributing factors? -- Primary cause vs contributing causes -- Timeline: when did this start? What changed? +- contradictions, including contracts conflicting with agreed behavior; +- uncovered obligations or vague, untestable criteria; +- proposed additions with no requirement or engineering rationale; +- artificial prerequisites inferred from task order or role names. -### For risk analysis: +For each finding, give source, consequence, and proposed next action. Necessary +implementation details need not each be a product requirement. An unexplained +addition is a scope question, not permission to delete code. Do not silently +change intent, tasks, or implementation. -| Risk | Likelihood | Impact | Mitigation | -| ---- | --------------- | --------------- | ---------- | -| ... | High/Medium/Low | High/Medium/Low | ... | +## Output -## Phase 3: Data & Evidence - -Support findings with concrete evidence: - -```bash -# Metrics, logs, or data that support the analysis -# Error rates, latency percentiles, query counts, etc. -``` - -Reference specific: - -- Code locations (file:line) -- Data points (error counts, latency numbers, test results) -- Documentation (ADRs, design docs, API specs) - -## Phase 4: Findings & Conclusions - -Present findings clearly: - -```markdown -## Findings - -### [Finding 1 — short title] -[Evidence + explanation] - -### [Finding 2] -[Evidence + explanation] -``` - -State conclusions with confidence level: - -- **Certain:** evidenced directly from code/data -- **Probable:** well-supported by evidence but not confirmed -- **Uncertain:** hypothesis that requires further investigation - -## Analysis Report - -```text -## Analysis Report — [topic] — [date] - -### Question -[The specific question answered] - -### TL;DR -[2-3 sentence executive summary of the most important finding] - -### Findings -[Structured findings with evidence] - -### Recommendation -[If applicable: what to do based on the analysis] -[NOT an implementation plan — just the recommended direction] - -### Open Questions -[What remains unclear and needs further investigation] - -### Confidence -[Overall confidence level: high / medium / low — and why] -``` +Return a compact response: question/scope, findings with evidence and impact, +recommendation, open questions, and confidence (`certain`, `probable`, `uncertain`). +For consistency reviews, use the response or an existing document when authorized; +no mandatory standalone report. A requested broader report may use the same +structure. Requirement quality and consistency findings are not behavioral proof. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"analyse","artifact_type":"skill","artifact_version":"20260421004","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"analyse","artifact_type":"skill","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/architecture/SKILL.md b/.github/skills/architecture/SKILL.md index 77975ce4..d1a9b8f3 100644 --- a/.github/skills/architecture/SKILL.md +++ b/.github/skills/architecture/SKILL.md @@ -278,4 +278,4 @@ For each significant structural decision made during this review (technology cho - Update `docs/architecture/overview.md` to reflect the final decisions. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"architecture","artifact_type":"skill","artifact_version":"20260421005","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"architecture","artifact_type":"skill","artifact_version":"20260421005","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/ask/SKILL.md b/.github/skills/ask/SKILL.md index 29885cd1..7e9b9b11 100644 --- a/.github/skills/ask/SKILL.md +++ b/.github/skills/ask/SKILL.md @@ -124,4 +124,4 @@ Use this format: - If it requires risk/impact comparison, hand off to `analyse`. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"ask","artifact_type":"skill","artifact_version":"20260618001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"ask","artifact_type":"skill","artifact_version":"20260618001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/aws-cli/SKILL.md b/.github/skills/aws-cli/SKILL.md index 47f50f65..cd2b1817 100644 --- a/.github/skills/aws-cli/SKILL.md +++ b/.github/skills/aws-cli/SKILL.md @@ -374,4 +374,4 @@ aws ce get-cost-and-usage \ - [AWS CLI named profiles](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"aws-cli","artifact_type":"skill","artifact_version":"20260502033","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"aws-cli","artifact_type":"skill","artifact_version":"20260502033","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/changedoc/SKILL.md b/.github/skills/changedoc/SKILL.md index 36dba336..228f4954 100644 --- a/.github/skills/changedoc/SKILL.md +++ b/.github/skills/changedoc/SKILL.md @@ -1,6 +1,6 @@ --- name: changedoc -description: 'Create and maintain a per-change document for existing repositories before implementation. Captures metadata, context, AS-IS, TO-BE, impact, acceptance criteria, and test scenarios so all agents can execute with less prompt context and better alignment.' +description: 'Maintain one change-local specification when durable scope or handoff is needed. Capture requirements, acceptance, useful tasks, and evidence without duplicate documents. Clear low-risk work may use existing issue or conversation context.' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access.' metadata: @@ -35,11 +35,10 @@ directory structures and other scan-friendly hierarchies. # changedoc - Per-Change Planning Document -Create and maintain a changedoc for repository changes before implementation. -Use this for bug fixes, features, refactors, and similar change requests in -existing repositories. - -For new greenfield projects, start with vision/roadmap/requirements first. +Use one changedoc when scope needs durable agreement or handoff, or when requested. +Small, clear, low-risk work may use an existing issue or conversation with outcome +and verification instead. Risk, ambiguity, and project policy determine escalation, +not change size. For greenfield projects, start with vision/requirements/roadmap. ## File naming convention @@ -49,9 +48,9 @@ Write changedocs to: Use lowercase kebab-case for `<slug>` and concise snake_case for `<title>`. -In vstack repositories, initialize the file from: - -`.vstack/templates/product/artifacts/changes/changedoc.md` +Initialize from `.vstack/templates/product/artifacts/changes/changedoc.md`. +Older customized templates remain valid: supplement the new document, never +overwrite the local template or backfill historical changedocs. ## Required metadata @@ -77,48 +76,42 @@ Rules: 1. AS-IS 1. TO-BE 1. Impact (high level) -1. Acceptance Criteria -1. Test Scenarios - -## Procedure - -## Step 1 - Normalize request into scope - -Capture: - -- requested outcome -- explicit non-goals -- constraints and dependencies - -## Step 2 - Build AS-IS from repository evidence - -Use concrete file and behavior evidence. Avoid assumptions. +1. Requirements (change-local obligations, not duplicated system baselines) +1. Acceptance Criteria (observable completion) +1. Test Scenarios (how to check) +1. Verification (actual evidence and gaps) -## Step 3 - Define TO-BE +Add Execution Tasks only when useful; list real prerequisites, not dependencies +inferred from list order or role names. Multiple changes may share a branch. +Use local references when useful; preserve established references during revisions. -Describe the target behavior and implementation intent clearly enough for -cross-role handoff. - -## Step 4 - Record impact - -Cover at least: - -- architecture and boundaries -- API/data/model implications -- security and privacy implications -- operational implications (logs, metrics, rollout, migration) - -## Step 5 - Define acceptance criteria and test scenarios - -Make criteria observable and testable. -Include happy path, failure path, and regression scenarios. - -## Step 6 - Update status by lifecycle +## Procedure -- `CONCEPT`: initial proposal and discovery -- `BUILD`: approved for implementation -- `IMPLEMENTED`: implementation complete and verified -- `ARCHIVED`: closed and retained for history +1. Read relevant code and decisions; record scope, constraints, non-goals, and AS-IS evidence. +1. Resolve material ambiguity one question at a time after checking known answers. + Record accepted answers here; distinguish user outcomes from technical choices. +1. Define TO-BE, obligations, acceptance, and relevant happy/failure/regression + scenarios without repeating prose. Use verifiable delivery slices when useful. +1. Record architecture, contract/data, security/privacy, and operational impact; + link supporting material only when needed. Update affected shared baselines, + not a parallel specification tree. +1. Before implementation, confirm understood scope, observable acceptance, no + blocking questions, and required approval. Product owns intent; contributors + may maintain tasks/evidence but escalate scope deviations. +1. Record criterion, check/result, reviewed commit or working-tree scope, and + limitation. Use `passed`, `failed`, `not run`, or `no longer current`. + Required failed/unrun checks prevent full verification; approved exceptions + name the limitation and approver, never turn it into a pass. Production + outcomes needing observation remain follow-ups. +1. After material intent/behavior changes, preserve references and reassess only + affected tasks/evidence. Renew approval only for changed scope, risk, or policy. + +Lifecycle states are not ordered thresholds: + +- `CONCEPT`: discovery; implementation not authorized. +- `BUILD`: implementation authorized under project policy. +- `IMPLEMENTED`: agreed scope completed and verified. +- `ARCHIVED`: closed history; never authorizes new implementation. ## Output contract @@ -134,12 +127,9 @@ open_questions: none | <bullet list> ## Escalation -Escalate before implementation when: - -- acceptance criteria are ambiguous -- trust-boundary or security impact is unclear -- migration or rollback implications are unclear -- required stakeholders have not approved transition to `BUILD` +Pause affected implementation for unclear acceptance, trust-boundary risk, +migration/rollback decisions, or missing required approval. Lightweight routing +never bypasses safety gates. Keep text concrete and compact; link rather than copy. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"changedoc","artifact_type":"skill","artifact_version":"20260625001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"changedoc","artifact_type":"skill","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/cicd/SKILL.md b/.github/skills/cicd/SKILL.md index f4323d9f..dc461314 100644 --- a/.github/skills/cicd/SKILL.md +++ b/.github/skills/cicd/SKILL.md @@ -221,4 +221,4 @@ Configure these in GitHub → Settings → Branches. - [GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"cicd","artifact_type":"skill","artifact_version":"20260421006","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"cicd","artifact_type":"skill","artifact_version":"20260421006","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/cloudformation/SKILL.md b/.github/skills/cloudformation/SKILL.md index 690a9d21..74cc9088 100644 --- a/.github/skills/cloudformation/SKILL.md +++ b/.github/skills/cloudformation/SKILL.md @@ -344,4 +344,4 @@ AppSecurityGroup: - [AWS SAM documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"cloudformation","artifact_type":"skill","artifact_version":"20260502032","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"cloudformation","artifact_type":"skill","artifact_version":"20260502032","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/code-review/SKILL.md b/.github/skills/code-review/SKILL.md index e85eddef..08e7a49c 100644 --- a/.github/skills/code-review/SKILL.md +++ b/.github/skills/code-review/SKILL.md @@ -218,4 +218,4 @@ Confidence: [HIGH/MEDIUM/LOW — explain if not HIGH] ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"code-review","artifact_type":"skill","artifact_version":"20260421007","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"code-review","artifact_type":"skill","artifact_version":"20260421007","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/codeql/SKILL.md b/.github/skills/codeql/SKILL.md index 7274e07a..2e12220f 100644 --- a/.github/skills/codeql/SKILL.md +++ b/.github/skills/codeql/SKILL.md @@ -251,4 +251,4 @@ GITHUB_TOKEN=<token> codeql github upload-results \ - [Supported languages and frameworks](https://docs.github.com/en/code-security/code-scanning/introduction-to-code-scanning/codeql-code-scanning-for-compiled-languages) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"codeql","artifact_type":"skill","artifact_version":"20260502026","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"codeql","artifact_type":"skill","artifact_version":"20260502026","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/concise/SKILL.md b/.github/skills/concise/SKILL.md index 82242a53..21b615a7 100644 --- a/.github/skills/concise/SKILL.md +++ b/.github/skills/concise/SKILL.md @@ -147,4 +147,4 @@ Current mode unchanged: <mode> - [ ] User confirmation/status returned in deterministic format <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"concise","artifact_type":"skill","artifact_version":"20260421008","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"concise","artifact_type":"skill","artifact_version":"20260421008","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/consult/SKILL.md b/.github/skills/consult/SKILL.md index 7b869ce5..6f645494 100644 --- a/.github/skills/consult/SKILL.md +++ b/.github/skills/consult/SKILL.md @@ -218,4 +218,4 @@ reason: [one sentence] ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"consult","artifact_type":"skill","artifact_version":"20260421009","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"consult","artifact_type":"skill","artifact_version":"20260421009","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/container/SKILL.md b/.github/skills/container/SKILL.md index 43ca1791..291ffa3e 100644 --- a/.github/skills/container/SKILL.md +++ b/.github/skills/container/SKILL.md @@ -153,4 +153,4 @@ For production-like local testing, write a separate `docker-compose.prod.yml` wi - [Docker official images](https://hub.docker.com/search?image_filter=official) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"container","artifact_type":"skill","artifact_version":"20260421010","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"container","artifact_type":"skill","artifact_version":"20260421010","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/conventional-commit/SKILL.md b/.github/skills/conventional-commit/SKILL.md index 89986ecc..a1a965c2 100644 --- a/.github/skills/conventional-commit/SKILL.md +++ b/.github/skills/conventional-commit/SKILL.md @@ -155,4 +155,4 @@ Remaining changes: If commit is blocked, report exact reason and proposed fix. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"conventional-commit","artifact_type":"skill","artifact_version":"20260502024","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"conventional-commit","artifact_type":"skill","artifact_version":"20260502024","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/copilot-ops/SKILL.md b/.github/skills/copilot-ops/SKILL.md index 578dbac4..c4f07adb 100644 --- a/.github/skills/copilot-ops/SKILL.md +++ b/.github/skills/copilot-ops/SKILL.md @@ -87,4 +87,4 @@ Provide this structure: Escalate when permissions are insufficient, settings conflict across scopes, or policy intent is ambiguous. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"copilot-ops","artifact_type":"skill","artifact_version":"20260513012","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"copilot-ops","artifact_type":"skill","artifact_version":"20260513012","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/debug/SKILL.md b/.github/skills/debug/SKILL.md index 2c0fd88f..7e0e6441 100644 --- a/.github/skills/debug/SKILL.md +++ b/.github/skills/debug/SKILL.md @@ -258,4 +258,4 @@ Prevention: [any follow-up items] ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"debug","artifact_type":"skill","artifact_version":"20260421011","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"debug","artifact_type":"skill","artifact_version":"20260421011","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/dependabot/SKILL.md b/.github/skills/dependabot/SKILL.md index 61cce513..b29a3ad6 100644 --- a/.github/skills/dependabot/SKILL.md +++ b/.github/skills/dependabot/SKILL.md @@ -320,4 +320,4 @@ updates: - [Dependabot security updates](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"dependabot","artifact_type":"skill","artifact_version":"20260502027","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"dependabot","artifact_type":"skill","artifact_version":"20260502027","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/dependency/SKILL.md b/.github/skills/dependency/SKILL.md index 032fa9d2..f506370b 100644 --- a/.github/skills/dependency/SKILL.md +++ b/.github/skills/dependency/SKILL.md @@ -318,4 +318,4 @@ Action items (priority order): - [PyPI / npm / crates.io / Maven Central](https://pypi.org) (replace with the relevant registry) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"dependency","artifact_type":"skill","artifact_version":"20260421012","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"dependency","artifact_type":"skill","artifact_version":"20260421012","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/design/SKILL.md b/.github/skills/design/SKILL.md index e5dae070..7960fb3d 100644 --- a/.github/skills/design/SKILL.md +++ b/.github/skills/design/SKILL.md @@ -243,4 +243,4 @@ Output a complete design document to `docs/design/overview.md` or `openapi.yaml` ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"design","artifact_type":"skill","artifact_version":"20260421013","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"design","artifact_type":"skill","artifact_version":"20260421013","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/docs/SKILL.md b/.github/skills/docs/SKILL.md index 2adbfe9a..b5aef77e 100644 --- a/.github/skills/docs/SKILL.md +++ b/.github/skills/docs/SKILL.md @@ -151,4 +151,4 @@ Skipped (n/a): ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"docs","artifact_type":"skill","artifact_version":"20260421014","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"docs","artifact_type":"skill","artifact_version":"20260421014","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/explore/SKILL.md b/.github/skills/explore/SKILL.md index 40072a0f..5e444004 100644 --- a/.github/skills/explore/SKILL.md +++ b/.github/skills/explore/SKILL.md @@ -149,4 +149,4 @@ For `thorough` mode, append: - main risk hotspots (coupling, missing tests, unclear ownership) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"explore","artifact_type":"skill","artifact_version":"20260611001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"explore","artifact_type":"skill","artifact_version":"20260611001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/gdpr/SKILL.md b/.github/skills/gdpr/SKILL.md index 6a688cd4..0c60e928 100644 --- a/.github/skills/gdpr/SKILL.md +++ b/.github/skills/gdpr/SKILL.md @@ -246,4 +246,4 @@ Use `@example.com` for all test email addresses. - [EDPB guidelines](https://www.edpb.europa.eu/our-work-tools/general-guidance/guidelines-recommendations-best-practices_en) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"gdpr","artifact_type":"skill","artifact_version":"20260502029","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"gdpr","artifact_type":"skill","artifact_version":"20260502029","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/gh-issues/SKILL.md b/.github/skills/gh-issues/SKILL.md index 9bc14e63..e9360c6d 100644 --- a/.github/skills/gh-issues/SKILL.md +++ b/.github/skills/gh-issues/SKILL.md @@ -230,4 +230,4 @@ https://github.com/<org>/<repo>/issues/<number> - [GitHub Issues documentation](https://docs.github.com/en/issues) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"gh-issues","artifact_type":"skill","artifact_version":"20260502025","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"gh-issues","artifact_type":"skill","artifact_version":"20260502025","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/gh-release/SKILL.md b/.github/skills/gh-release/SKILL.md index e961fedd..604816cc 100644 --- a/.github/skills/gh-release/SKILL.md +++ b/.github/skills/gh-release/SKILL.md @@ -214,4 +214,4 @@ If blocked, report exact blocker and required user action. - [GitHub Releases documentation](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"gh-release","artifact_type":"skill","artifact_version":"20260502023","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"gh-release","artifact_type":"skill","artifact_version":"20260502023","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/guardrails/SKILL.md b/.github/skills/guardrails/SKILL.md index e22c3b75..57c5f33a 100644 --- a/.github/skills/guardrails/SKILL.md +++ b/.github/skills/guardrails/SKILL.md @@ -72,4 +72,4 @@ Activate careful mode for this session. Two behaviors are now enabled. Explicitly ask to "disable guardrails". <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"guardrails","artifact_type":"skill","artifact_version":"20260421016","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"guardrails","artifact_type":"skill","artifact_version":"20260421016","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/helm/SKILL.md b/.github/skills/helm/SKILL.md index c13fff72..37947680 100644 --- a/.github/skills/helm/SKILL.md +++ b/.github/skills/helm/SKILL.md @@ -140,4 +140,4 @@ Practices: - [Chart best practices](https://helm.sh/docs/chart_best_practices/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"helm","artifact_type":"skill","artifact_version":"20260502037","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"helm","artifact_type":"skill","artifact_version":"20260502037","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/incident/SKILL.md b/.github/skills/incident/SKILL.md index f0b570d6..432b1f18 100644 --- a/.github/skills/incident/SKILL.md +++ b/.github/skills/incident/SKILL.md @@ -251,4 +251,4 @@ Next: invoke @#rca and @#postmortem to produce written artifacts. ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"incident","artifact_type":"skill","artifact_version":"20260503002","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"incident","artifact_type":"skill","artifact_version":"20260503002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/inspect/SKILL.md b/.github/skills/inspect/SKILL.md index 34fc9402..4d10fd67 100644 --- a/.github/skills/inspect/SKILL.md +++ b/.github/skills/inspect/SKILL.md @@ -1,6 +1,6 @@ --- name: inspect -description: 'Read-only verification audit. Runs baseline plus optional extended checks, produces severity-ranked findings, and makes no code or commit changes. Use when asked to "inspect", "assess", "check without fixing", or "what''s wrong with this" before deciding whether to run verify fix loops.' +description: 'Read-only verification audit against agreed behavior, including missing work and evidence gaps. Use for "inspect", "assess", or "check without fixing". Report findings without code edits, commits, or mandatory duplicate reports.' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access and terminal command execution when needed.' metadata: @@ -44,115 +44,57 @@ echo "Base branch: $BASE" # inspect - Read-Only Verification Audit -Run verification checks and report findings. Do not edit code, do not commit, -and do not fix anything. +Assess and report; do not edit code, fix issues, or commit. Use `verify` for an +authorized fix loop, `architecture` for decisions, `security` for full audits, +and `performance` for profiling. -Use `verify` when a fix loop is required. +## Scope and report placement -## Out of scope +Read agreed intent, relevant contracts, project policy, and the reviewed commit +or working-tree scope. Compare actual in-scope behavior with acceptance, including +required behavior absent from the diff. Do not infer completion from checkboxes. -- Fixing issues (use `verify`) -- Architecture decisions (use `architecture`) -- Full security audit (use `security`) -- Performance profiling (use `performance`) +Use `docs/reports/test-report.md` when project policy or cross-change reporting +requires it. Otherwise report in the response, or update an existing changedoc +only when authorized. No duplicate report or mandatory new file. -## Deliverable and artifact policy +## Checks -- Primary deliverable: `docs/reports/test-report.md` -- Baseline-first default: write final findings directly to `docs/reports/test-report.md` on the feature branch. -- Before merge: confirm blocking findings and final verdict are written to baseline reports. +Discover repository commands and run the smallest checks covering acceptance and +regressions. Preserve command failures and missing-tool evidence; never suppress +errors or treat unavailable checks as passes. -## Step 0: Scope +| Surface | Checks when applicable | +| --------------------- | -------------------------------------------------------------------------------------------------------- | +| Baseline | Lint, types, build/package, unit tests | +| Integration/contracts | Service boundaries, OpenAPI/JSON Schema/Protobuf, compatibility | +| Reliability/data | Smoke, migrations/rollback, timeouts, retries, circuit breakers, concurrency | +| Observability | Structured failure/transition logs, latency/error/saturation metrics, trace propagation, alerts/runbooks | +| Dependencies | Repository vulnerability gate (for example audit tools); route deeper concerns | -```text -Report only. No edits. No commits. -If critical issues are found, recommend `verify`. -``` - -## Step 1: Baseline Checks - -```bash -[ -f package.json ] && (npm run lint 2>/dev/null || true) -[ -f tsconfig.json ] && npx tsc --noEmit 2>/dev/null || true -[ -f pyproject.toml ] && (ruff check . 2>/dev/null || true) -[ -f pyproject.toml ] && (mypy . 2>/dev/null || pyright . 2>/dev/null || true) -[ -f go.mod ] && (go vet ./... 2>/dev/null || true) -``` - -```bash -# Detect test runner and run tests -if [ -f package.json ]; then - if grep -q '"vitest"' package.json 2>/dev/null; then - npx vitest run - elif grep -q '"jest"' package.json 2>/dev/null; then - npx jest - elif grep -q '"bun"' package.json 2>/dev/null; then - bun test - else - npm test - fi -elif [ -f pyproject.toml ] || [ -f setup.py ]; then - python -m pytest -v -elif [ -f go.mod ]; then - go test ./... -elif [ -f Cargo.toml ]; then - cargo test -else - echo "No recognized test framework detected." -fi -``` - -## Step 2: Extended Checks (when present) +Choose by scope and risk, not a universal checklist. Documentation-only work +needs document checks, not runtime tests. Record commands, results, and limits. -```bash -# Integration -[ -f package.json ] && npm run test:integration 2>/dev/null || true -[ -f pyproject.toml ] && python -m pytest -m integration -v 2>/dev/null || true -[ -f go.mod ] && go test -run Integration ./... 2>/dev/null || true - -# Contract -[ -f openapi.yaml ] && npx @redocly/cli lint openapi.yaml 2>/dev/null || true -[ -n "$(find . -name '*.proto' 2>/dev/null | head -1)" ] && buf lint 2>/dev/null || true - -# Lightweight vulnerability gate -[ -f package.json ] && npm audit --audit-level=high 2>/dev/null || true -[ -f pyproject.toml ] && pip-audit 2>/dev/null || true -[ -f go.mod ] && govulncheck ./... 2>/dev/null || true -``` - -### 2.1 Observability & Reliability Checks - -Confirm for changed paths: - -- Structured logs exist for key state transitions and failures. -- Metrics cover latency, error rate, and saturation for impacted services. -- Trace propagation exists across service boundaries where applicable. -- Alerts/runbooks exist for high-severity failure modes. +## Intent-to-behavior assessment -## Step 3: Report +Separate missing behavior, contradictions, unexplained additions, and evidence +gaps. Ask for scope decisions on unrelated additions; do not delete them. +Necessary helpers need no separate product requirement. -```text -## Inspection Report - [component/repo] - [date] +For each applicable criterion record: check/result, evidence reference, reviewed +scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. +Code coverage is not acceptance coverage; requirement wording is not runtime proof. +Reassess only evidence affected by material intent or behavior revisions. -### Summary -- tests: [X pass / Y fail / Z skip] -- issues: [N critical / N high / N medium / N low] +## Verdict -### Critical -1. [issue] - [file:line] - [evidence] +Return scope, checks, severity-ranked findings (source, impact, reproduction), +criterion evidence/gaps, residual risks, and next action: +`SHIP-READY`, `USE VERIFY FIX LOOP`, or `NEEDS ARCH/DESIGN REVIEW`. -### High -1. [issue] - [file:line] - [recommended fix] - -### Medium -1. [issue] - [file:line] - [recommended fix] - -### Low -1. [issue] - [notes] - -### Recommendation -[SHIP-READY | USE VERIFY FIX LOOP | NEEDS ARCH/DESIGN REVIEW] -``` +Required failed/unrun checks block full verification. Name any policy-approved +exception and approver without marking the criterion passed. Production outcomes +needing observation remain follow-ups. Sanitize evidence; do not copy sensitive logs. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"inspect","artifact_type":"skill","artifact_version":"20260421018","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"inspect","artifact_type":"skill","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/k8s/SKILL.md b/.github/skills/k8s/SKILL.md index b4fd7108..342db64c 100644 --- a/.github/skills/k8s/SKILL.md +++ b/.github/skills/k8s/SKILL.md @@ -144,4 +144,4 @@ Common failure classes: - [Kubernetes API reference](https://kubernetes.io/docs/reference/kubernetes-api/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"k8s","artifact_type":"skill","artifact_version":"20260502036","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"k8s","artifact_type":"skill","artifact_version":"20260502036","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/lazy/SKILL.md b/.github/skills/lazy/SKILL.md index 69ab820b..8f8858d5 100644 --- a/.github/skills/lazy/SKILL.md +++ b/.github/skills/lazy/SKILL.md @@ -160,4 +160,4 @@ Stop and escalate when: - The task is under-specified and any minimal patch would be guesswork. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"lazy","artifact_type":"skill","artifact_version":"20260625001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"lazy","artifact_type":"skill","artifact_version":"20260625001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/migrate/SKILL.md b/.github/skills/migrate/SKILL.md index 3dbad91d..fa2a95b8 100644 --- a/.github/skills/migrate/SKILL.md +++ b/.github/skills/migrate/SKILL.md @@ -320,4 +320,4 @@ Pre-deploy checklist: ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"migrate","artifact_type":"skill","artifact_version":"20260421019","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"migrate","artifact_type":"skill","artifact_version":"20260421019","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/migration-plan/SKILL.md b/.github/skills/migration-plan/SKILL.md index 4e638532..8278578d 100644 --- a/.github/skills/migration-plan/SKILL.md +++ b/.github/skills/migration-plan/SKILL.md @@ -66,4 +66,4 @@ For each phase: - success criteria <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"migration-plan","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"migration-plan","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/onboard/SKILL.md b/.github/skills/onboard/SKILL.md index b46ddc99..f33a0817 100644 --- a/.github/skills/onboard/SKILL.md +++ b/.github/skills/onboard/SKILL.md @@ -302,4 +302,4 @@ Gaps remaining (if any): ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"onboard","artifact_type":"skill","artifact_version":"20260421020","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"onboard","artifact_type":"skill","artifact_version":"20260421020","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/openapi/SKILL.md b/.github/skills/openapi/SKILL.md index 96cbb6f4..ff41aae8 100644 --- a/.github/skills/openapi/SKILL.md +++ b/.github/skills/openapi/SKILL.md @@ -403,4 +403,4 @@ Summary: [N critical, N warnings, N info] - [Redocly CLI (linting)](https://redocly.com/docs/cli/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"openapi","artifact_type":"skill","artifact_version":"20260421021","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"openapi","artifact_type":"skill","artifact_version":"20260421021","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/performance/SKILL.md b/.github/skills/performance/SKILL.md index 72596379..7688e60b 100644 --- a/.github/skills/performance/SKILL.md +++ b/.github/skills/performance/SKILL.md @@ -242,4 +242,4 @@ For each bottleneck identified: ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20260421022","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20260421022","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/postmortem/SKILL.md b/.github/skills/postmortem/SKILL.md index 461f4de9..c6882b97 100644 --- a/.github/skills/postmortem/SKILL.md +++ b/.github/skills/postmortem/SKILL.md @@ -184,4 +184,4 @@ Status: Draft — ready for team review ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"postmortem","artifact_type":"skill","artifact_version":"20260503001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"postmortem","artifact_type":"skill","artifact_version":"20260503001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/pr/SKILL.md b/.github/skills/pr/SKILL.md index bc794a29..ba2f9fa2 100644 --- a/.github/skills/pr/SKILL.md +++ b/.github/skills/pr/SKILL.md @@ -151,4 +151,4 @@ Next steps depend on the repository CI/CD configuration: ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"pr","artifact_type":"skill","artifact_version":"20260502013","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"pr","artifact_type":"skill","artifact_version":"20260502013","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/rancher/SKILL.md b/.github/skills/rancher/SKILL.md index baae344a..592f1b47 100644 --- a/.github/skills/rancher/SKILL.md +++ b/.github/skills/rancher/SKILL.md @@ -113,4 +113,4 @@ Checks: - [Fleet documentation](https://fleet.rancher.io/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"rancher","artifact_type":"skill","artifact_version":"20260502038","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"rancher","artifact_type":"skill","artifact_version":"20260502038","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/rca/SKILL.md b/.github/skills/rca/SKILL.md index 77e26108..a7c1255a 100644 --- a/.github/skills/rca/SKILL.md +++ b/.github/skills/rca/SKILL.md @@ -207,4 +207,4 @@ Status: Draft — ready for review ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"rca","artifact_type":"skill","artifact_version":"20260503001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"rca","artifact_type":"skill","artifact_version":"20260503001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/reasoning/SKILL.md b/.github/skills/reasoning/SKILL.md index 8bac8374..d96157fa 100644 --- a/.github/skills/reasoning/SKILL.md +++ b/.github/skills/reasoning/SKILL.md @@ -115,4 +115,4 @@ Always ask internally: **Related:** See `skill/advise` for structured adversarial review workflows. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"reasoning","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"reasoning","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/refactor/SKILL.md b/.github/skills/refactor/SKILL.md index cbb1bff7..362e1945 100644 --- a/.github/skills/refactor/SKILL.md +++ b/.github/skills/refactor/SKILL.md @@ -375,4 +375,4 @@ Behavior changed: No ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"refactor","artifact_type":"skill","artifact_version":"20260421023","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"refactor","artifact_type":"skill","artifact_version":"20260421023","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/release-check/SKILL.md b/.github/skills/release-check/SKILL.md index 1716ccf1..9a4a4414 100644 --- a/.github/skills/release-check/SKILL.md +++ b/.github/skills/release-check/SKILL.md @@ -69,4 +69,4 @@ Ordered actions to reach READY. - verification step <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"release-check","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"release-check","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/release-notes/SKILL.md b/.github/skills/release-notes/SKILL.md index 76e1aa9a..9ce88565 100644 --- a/.github/skills/release-notes/SKILL.md +++ b/.github/skills/release-notes/SKILL.md @@ -147,4 +147,4 @@ Prepend a new entry at the top of `CHANGELOG.md`: Keep existing entries intact. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"release-notes","artifact_type":"skill","artifact_version":"20260502014","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"release-notes","artifact_type":"skill","artifact_version":"20260502014","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/requirements/SKILL.md b/.github/skills/requirements/SKILL.md index b807df24..6445d897 100644 --- a/.github/skills/requirements/SKILL.md +++ b/.github/skills/requirements/SKILL.md @@ -1,6 +1,6 @@ --- name: requirements -description: 'Collaborative requirements gathering and documentation. Clarifies what must be built, defines success criteria, constraints, and non-functional requirements. Produces a requirements.md document. Use when asked to "gather requirements", "write the requirements", "define the spec", or "what are we building?". Runs before architecture and design work begins.' +description: 'Clarify requirements, constraints, and observable acceptance in the existing intent source. Use for "gather requirements", "define the spec", or "what are we building?". Keep change-local intent separate from shared system baselines.' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access and terminal command execution when needed.' metadata: @@ -33,170 +33,62 @@ the format is supported and improves clarity. Use ASCII as a fallback when Mermaid is unsupported or would be less readable. Keep ASCII/text trees for directory structures and other scan-friendly hierarchies. -# requirements — Requirements Gathering & Documentation +# requirements - Requirements Gathering -Clarify and document what must be built before engineering starts. Produce a -`docs/product/requirements.md` that downstream roles (architect, designer, engineer) can -work from. +Define what must be built and observable acceptance before engineering. Product +owns scope; architecture, design, roadmap planning, and implementation belong to +their respective roles. -## Out of scope +## Choose the intent source -- Technical design and architecture decisions (use `architecture`) -- API/service design (use `design`) -- Roadmap and milestone planning (product role artifact) -- Implementation (engineering role) +- System-level intent: `docs/product/requirements.md` on the branch. +- Change-local intent: the existing changedoc, not a separate specification. +- Small, clear, low-risk task: sufficient existing issue or conversation context. -## Deliverable and artifact policy +Update shared baselines only when shared behavior or contracts change. Preserve +project gates and approvals regardless of task size; do not mandate every role. -- Primary deliverable: `docs/product/requirements.md` -- Baseline-first default: write final requirements directly to `docs/product/requirements.md` on the feature branch. -- Before merge: confirm requirements are complete and consistent before merge. +## Clarify from evidence -## Step 0: Context +1. Read relevant vision, requirements, roadmap, code, and recorded decisions first. +1. Identify the highest-impact uncertainty. Ask one focused question only when + it materially affects correctness, scope, risk, or approval; no interview quota. +1. Record accepted answers in the existing intent source, or confirm them in chat. + Do not repeat answered questions. State remaining assumptions and their risks. -Read existing artifacts before asking questions: +## Define requirements -```bash -cat docs/product/vision.md 2>/dev/null || true -cat docs/product/requirements.md 2>/dev/null || true -cat docs/product/roadmap.md 2>/dev/null || true -cat README.md 2>/dev/null | head -40 || true -``` +Capture only relevant dimensions: -Identify what's already known and what needs clarification. +| Dimension | Record | +| ------------------- | ----------------------------------------------------------------------------------- | +| Problem | Who is affected, unmet need, and consequence | +| Functional behavior | Must/should/won't-have outcomes, conditions, boundaries, and failure behavior | +| Quality attributes | Measurable performance/load, availability, security, scaling, or compliance targets | +| Constraints | Required technology, integration, budget, deadline, and team limits | +| Acceptance | Observable completion and how to check it | +| Open questions | Blocking decision, owner, and when needed | -## Step 1: Problem Statement +Use "The system must [behavior] under [condition]" where helpful. Keep outcomes +separate from technical choices unless a constraint requires them. Review +terminology, completeness, testability, and assumptions only for relevant scope. +A wording review is not proof that implementation works. -Clarify the core problem being solved: +Prefer independently verifiable delivery slices when useful; do not force them +on small fixes or tightly coupled migrations. Reference relevant contracts and +data-lifecycle/operational constraints rather than copying them. -> **Question:** Describe what you want to build and why. -> -> - What problem does this solve? -> - Who experiences this problem today? -> - What happens if we don't solve it? +## Output and readiness -Document: +For system baselines, organize findings as Problem, Users, Functional Requirements, +Non-Functional Requirements, Constraints/Assumptions, Acceptance, and Open Questions. +For change-local work, maintain the corresponding existing sections. -```text -## Problem Statement -[One paragraph: root problem, who has it, impact of not solving it] -``` - -## Step 2: Users & Stakeholders - -Who uses or is affected by this? - -| Role | Description | Primary need | -| ----------- | ----------- | ------------ | -| [User type] | | | - -## Step 3: Functional Requirements - -What must the system do? Use the format: "The system must [verb] [object] [condition/constraint]." - -Ask for clarity on ambiguous areas: - -> **Question:** Are there any specific behaviors or edge cases that are critical? - -```markdown -## Functional Requirements - -### Must have (MVP) -- FR-01: The system must [...] -- FR-02: The system must [...] - -### Should have (desirable) -- FR-03: [...] - -### Won't have (explicitly out of scope) -- [State what will NOT be built in this iteration] -``` - -## Step 4: Non-Functional Requirements - -| Category | Requirement | Measurable target | -| ------------ | -------------- | ------------------------------------ | -| Performance | Response time | p99 < 500ms under X rps | -| Availability | Uptime | 99.9% (< 8.7h downtime/year) | -| Security | Auth | All endpoints require authentication | -| Scalability | Load | Handle up to N concurrent users | -| Compliance | Data residency | Data stored in [region] | - -Ask: - -> **Question:** Are there any hard non-functional requirements (performance, security, -> compliance, data residency)? - -## Step 5: Constraints & Assumptions - -Document known constraints: - -```markdown -## Constraints -- Budget: [if relevant] -- Timeline: [hard deadline if any] -- Technology: [must use X, cannot use Y] -- Team: [available skill set] -- Existing systems: [must integrate with X] - -## Assumptions -- [Things assumed true that could invalidate requirements if wrong] -``` - -## Step 6: Success Criteria - -What does "done" look like? How do we know the requirements are met? - -```markdown -## Success Criteria -- [ ] [Measurable outcome 1] -- [ ] [Measurable outcome 2] -- [ ] [Acceptance test: given X, when Y, then Z] -``` - -## Step 7: Open Questions - -List anything that is unclear and needs a decision before work begins: - -```markdown -## Open Questions -- [ ] [Question] — Owner: [who decides] — Deadline: [when needed] -``` - -## Output: requirements.md - -Write all findings to `docs/product/requirements.md`: - -```markdown -# Requirements — [feature/project name] - -**Status:** draft | reviewed | approved -**Date:** YYYY-MM-DD -**Author:** product role - -## Problem Statement -[...] - -## Users & Stakeholders -[table] - -## Functional Requirements -[...] - -## Non-Functional Requirements -[table] - -## Constraints & Assumptions -[...] - -## Success Criteria -[...] - -## Open Questions -[...] -``` - -After writing, summarize what was decided so the architect role can start. +Use stable local references when useful; no global IDs or duplicate prose. +Summarize scope, criteria, and blockers for the relevant owner. Implementation +requires understood scope, observable acceptance, resolved blocking questions, +and approval under project policy. After material revisions, reassess affected +tasks/evidence and renew approval only when scope, risk, or policy requires it. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"requirements","artifact_type":"skill","artifact_version":"20260421024","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"requirements","artifact_type":"skill","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/secret-scan/SKILL.md b/.github/skills/secret-scan/SKILL.md index ba811fea..a85df763 100644 --- a/.github/skills/secret-scan/SKILL.md +++ b/.github/skills/secret-scan/SKILL.md @@ -240,4 +240,4 @@ credential formats. - [Supported secret patterns](https://docs.github.com/en/code-security/secret-scanning/introduction/supported-secret-scanning-patterns) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"secret-scan","artifact_type":"skill","artifact_version":"20260502028","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"secret-scan","artifact_type":"skill","artifact_version":"20260502028","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/security/SKILL.md b/.github/skills/security/SKILL.md index b460585f..6bcf5c15 100644 --- a/.github/skills/security/SKILL.md +++ b/.github/skills/security/SKILL.md @@ -295,4 +295,4 @@ Scope: [full/diff/dependency/config] - [STRIDE threat modeling (Microsoft)](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"security","artifact_type":"skill","artifact_version":"20260421025","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"security","artifact_type":"skill","artifact_version":"20260421025","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/simplify/SKILL.md b/.github/skills/simplify/SKILL.md index d95a34f9..67d89c30 100644 --- a/.github/skills/simplify/SKILL.md +++ b/.github/skills/simplify/SKILL.md @@ -155,4 +155,4 @@ Escalate instead of over-simplifying when: - Required outcomes are underspecified. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"simplify","artifact_type":"skill","artifact_version":"20260625001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"simplify","artifact_type":"skill","artifact_version":"20260625001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/space-setup/SKILL.md b/.github/skills/space-setup/SKILL.md index acde29c8..79cb80b5 100644 --- a/.github/skills/space-setup/SKILL.md +++ b/.github/skills/space-setup/SKILL.md @@ -87,4 +87,4 @@ Provide this structure: Escalate when required docs are missing, stale, or inconsistent across product/architecture/design baselines. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"space-setup","artifact_type":"skill","artifact_version":"20260513011","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"space-setup","artifact_type":"skill","artifact_version":"20260513011","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/terraform/SKILL.md b/.github/skills/terraform/SKILL.md index 1a294ce6..e04da97c 100644 --- a/.github/skills/terraform/SKILL.md +++ b/.github/skills/terraform/SKILL.md @@ -335,4 +335,4 @@ Run `terraform plan` after every state operation to verify the outcome. - [tfsec rules](https://aquasecurity.github.io/tfsec/latest/checks/aws/) · [checkov checks](https://www.checkov.io/5.Policy%20Index/terraform.html) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"terraform","artifact_type":"skill","artifact_version":"20260502030","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"terraform","artifact_type":"skill","artifact_version":"20260502030","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/terragrunt/SKILL.md b/.github/skills/terragrunt/SKILL.md index 052994ec..bcce2c29 100644 --- a/.github/skills/terragrunt/SKILL.md +++ b/.github/skills/terragrunt/SKILL.md @@ -307,4 +307,4 @@ Use `--terragrunt-non-interactive` in CI to prevent hanging on prompts. - [Gruntwork module registry](https://www.gruntwork.io/) <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"terragrunt","artifact_type":"skill","artifact_version":"20260502031","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"terragrunt","artifact_type":"skill","artifact_version":"20260502031","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/threat-model/SKILL.md b/.github/skills/threat-model/SKILL.md index 595d9437..f4ffd6ca 100644 --- a/.github/skills/threat-model/SKILL.md +++ b/.github/skills/threat-model/SKILL.md @@ -245,4 +245,4 @@ For each high-priority threat include: - Final report is written to `docs/architecture/threat-model.md`. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"threat-model","artifact_type":"skill","artifact_version":"20260502021","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"threat-model","artifact_type":"skill","artifact_version":"20260502021","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/upgrade-plan/SKILL.md b/.github/skills/upgrade-plan/SKILL.md index d7b11a50..fda1ccbf 100644 --- a/.github/skills/upgrade-plan/SKILL.md +++ b/.github/skills/upgrade-plan/SKILL.md @@ -66,4 +66,4 @@ For each major step: - pass criteria <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"upgrade-plan","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"upgrade-plan","artifact_type":"skill","artifact_version":"20261017001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/verify/SKILL.md b/.github/skills/verify/SKILL.md index 88dc94b7..594d8e22 100644 --- a/.github/skills/verify/SKILL.md +++ b/.github/skills/verify/SKILL.md @@ -1,6 +1,6 @@ --- name: verify -description: 'Verification fix-loop skill. Routes by mode (quick/standard/exhaustive), runs targeted checks, fixes findings by severity, and re-verifies impacted paths. Routes report-only requests to inspect and escalates deep security/performance concerns to specialized skills. Use when asked to "verify", "fix failing checks", "run QA with fixes", or "re-verify before shipping".' +description: 'Verify agreed behavior in quick/standard/exhaustive mode, fix authorized gaps, and rerun affected checks. Use for "verify", "fix failing checks", or "run QA with fixes". Route report-only work to inspect; stop on blockers or no progress.' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access and terminal command execution when needed.' metadata: @@ -44,226 +44,84 @@ echo "Base branch: $BASE" # verify - Fix Loop Verification -Run a targeted verification fix loop: +Check agreed behavior, fix authorized gaps, and rerun affected checks. Use +`inspect` for report-only work, `architecture` for decisions, `security` for deep +audits, and `performance` for profiling. Do not add features outside agreed scope. -1. choose scope/mode, -1. run checks, -1. fix issues in priority order, -1. re-run only impacted checks, -1. report ship readiness. +## 1. Select mode and scope -Use `inspect` for read-only auditing. +Use the requested mode, otherwise `standard`: -## Out of scope +| Mode | Depth and fix policy | +| ----------- | ------------------------------------------------------------------------------------------ | +| quick | Focused critical/high regressions; broaden if acceptance needs it | +| standard | Relevant baseline, integration, contract, and reliability checks; fix critical/high/medium | +| exhaustive | Standard plus relevant smoke, dependency, and operational checks; all severities | +| report-only | Route to `inspect`; no fixes | -- Architecture decisions (use `architecture`) -- Full security audit (use `security`) -- Performance benchmarking/profiling (use `performance`) -- New feature implementation outside verification fixes (engineering role) +Read intent, criteria, relevant contracts, project policy, and working-tree +changes. Establish reviewed commit or working-tree scope. Preserve unrelated +edits; ask before conflicting changes. Commit only when authorized. +Small low-risk tasks may use an existing issue/conversation; no mandatory document. -## Deliverable and artifact policy +Readiness requires understood scope, observable acceptance, resolved blockers, +and policy approval. Safety gates apply regardless of mode or task size. -- Primary deliverable: `docs/reports/test-report.md` -- Additional deliverables when applicable: `docs/reports/security-report.md`, `docs/reports/performance-baseline.md` -- Baseline-first default: write final verification outcomes directly to baseline reports on the feature branch. -- Before merge: consolidate final findings, severity, and ship-readiness verdict into baseline reports. +## 2. Check behavior -## Step 0: Route Mode +Compare actual in-scope behavior with acceptance, including required behavior +absent from the diff. Discover existing repository commands and run the smallest +checks covering changed behavior and regressions. Broaden only as needed. -Classify first, then run one mode. +| Surface | Checks when applicable | +| ---------------- | --------------------------------------------------------------------------------------------- | +| Baseline | Lint, types, build/package, unit tests | +| Boundaries | Integration, OpenAPI/JSON Schema/Protobuf, API compatibility | +| Reliability/data | Smoke, migrations/rollback, retries/backoff, timeouts, circuit breakers, concurrency | +| Operations | Failure/transition logs, latency/error/saturation metrics, trace propagation, alerts/runbooks | +| Dependencies | Existing vulnerability gate; route deeper security/performance concerns | -> **Question:** Which verify mode should be used? -> **Options:** -> A) quick - critical/high regressions only -> B) standard - default verification + fix loop -> C) exhaustive - broad verification and full fix sweep -> D) report-only - route to `inspect` -> **Default if no response:** B +Use measurable operational evidence when relevant, not runtime tests for prose. +Preserve failures and missing-tool details; never suppress errors or substitute +an available check for a different required one. -If D, stop and route to `inspect`. +## 3. Triage and fix -## Step 1: Scope and Safety +Separate behavioral gaps, contradictions, unexplained additions, and unavailable +evidence. Severity: critical (build/data/security failure), high (broken contract +or required check), medium (other behavior/flakiness), low (minor cleanup). -Parse user scope: - -- Target: whole repo or specific component/path -- Tier: quick/standard/exhaustive -- Source: full branch diff or explicit path - -Check working tree: - -```bash -git status --porcelain -``` - -If dirty, ask before proceeding because verify may create multiple atomic fix commits. - -Bootstrap test command: - -```bash -# Detect test runner and run tests -if [ -f package.json ]; then - if grep -q '"vitest"' package.json 2>/dev/null; then - npx vitest run - elif grep -q '"jest"' package.json 2>/dev/null; then - npx jest - elif grep -q '"bun"' package.json 2>/dev/null; then - bun test - else - npm test - fi -elif [ -f pyproject.toml ] || [ -f setup.py ]; then - python -m pytest -v -elif [ -f go.mod ]; then - go test ./... -elif [ -f Cargo.toml ]; then - cargo test -else - echo "No recognized test framework detected." -fi -``` - -## Step 2: Baseline Checks (all modes) - -Run baseline checks for the selected scope. - -### 2.1 Lint and Type - -```bash -[ -f package.json ] && (npm run lint 2>/dev/null || true) -[ -f tsconfig.json ] && npx tsc --noEmit 2>/dev/null || true -[ -f pyproject.toml ] && (ruff check . 2>/dev/null || true) -[ -f pyproject.toml ] && (mypy . 2>/dev/null || pyright . 2>/dev/null || true) -[ -f go.mod ] && (go vet ./... 2>/dev/null || true) -``` - -### 2.2 Unit Tests - -```bash -# Detect test runner and run tests -if [ -f package.json ]; then - if grep -q '"vitest"' package.json 2>/dev/null; then - npx vitest run - elif grep -q '"jest"' package.json 2>/dev/null; then - npx jest - elif grep -q '"bun"' package.json 2>/dev/null; then - bun test - else - npm test - fi -elif [ -f pyproject.toml ] || [ -f setup.py ]; then - python -m pytest -v -elif [ -f go.mod ]; then - go test ./... -elif [ -f Cargo.toml ]; then - cargo test -else - echo "No recognized test framework detected." -fi -``` - -## Step 3: Conditional Checks by Mode - -### quick - -- Run only failing or high-risk checks related to changed code -- Skip broad integration/contract/smoke unless directly impacted - -### standard - -Run these when present: - -```bash -# Integration -[ -f package.json ] && npm run test:integration 2>/dev/null || true -[ -f pyproject.toml ] && python -m pytest -m integration -v 2>/dev/null || true -[ -f go.mod ] && go test -run Integration ./... 2>/dev/null || true - -# Contract -[ -f openapi.yaml ] && npx @redocly/cli lint openapi.yaml 2>/dev/null || true -[ -n "$(find . -name '*.proto' 2>/dev/null | head -1)" ] && buf lint 2>/dev/null || true -``` - -Also verify observability on impacted paths: - -- Structured logs for critical transitions and errors -- Metrics for latency/error/saturation -- Trace propagation across service boundaries -- Alerts or runbooks for critical failure modes - -### exhaustive - -Run standard checks plus: - -```bash -# Optional smoke checks if scripts exist -find . -name '*.smoke.*' -o -name '*smoke-test*' -o -name 'smoke.sh' 2>/dev/null | head -5 - -# Dependency vulnerability gate (lightweight only; full audit belongs to security) -[ -f package.json ] && npm audit --audit-level=high 2>/dev/null || true -[ -f pyproject.toml ] && pip-audit 2>/dev/null || true -[ -f go.mod ] && govulncheck ./... 2>/dev/null || true -``` - -For exhaustive mode, require observability evidence (logs/metrics/traces/alerts) in the final report. - -If deep security/performance concerns appear, stop and route to `security` or `performance`. - -## Step 4: Triage - -Classify findings: - -| Severity | Examples | -| -------- | ------------------------------------------------------------------- | -| critical | test crashes, build breaks, data integrity/security regressions | -| high | contract violations, broken error handling, missing required checks | -| medium | flaky tests, non-critical behavior gaps | -| low | style and minor cleanups | - -Fix policy: - -- quick: critical + high -- standard: critical + high + medium -- exhaustive: all severities - -## Step 5: Fix and Re-verify Loop - -For each fixable issue in severity order: +Within the mode's fix policy: 1. Reproduce and confirm root cause. -1. Apply minimal fix. -1. Commit atomically (`fix: ...`). -1. Re-run only impacted checks first. -1. If needed, run the relevant broader check suite. - -If an issue implies architecture or design mismatch, stop and escalate. +1. Apply the smallest authorized fix; preserve acceptance and role ownership. +1. Rerun affected checks, then broader checks if needed. +1. Update useful existing tasks, not an append-only remediation history. -## Step 6: Final Report +Unexplained additions require a scope decision, not automatic deletion; necessary +helpers need no separate requirement. Escalate changed intent/contracts to their +owner. After material revisions, preserve criterion references and reassess only +affected tasks/evidence. Renew approval only for scope, risk, or policy changes. -```text -## Verification Report - [component/repo] - [date] +Stop and report blockers when required evidence cannot be obtained, scope/policy +decisions are needed, or attempts repeat without new evidence. Honor existing +iteration budgets; do not loop indefinitely or weaken criteria to claim success. -selected_mode: [quick|standard|exhaustive] -scope: [path/component/full] +## 4. Record evidence and verdict -### Summary -- tests: [X pass / Y fail / Z skip] -- issues found: [N critical / N high / N medium / N low] -- fixes applied: [N] -- deferred: [N] +Use `docs/reports/test-report.md` (and scoped security/performance reports) when +policy or cross-change reporting requires it. Otherwise keep evidence in the +existing changedoc or response; no duplicate reports. -### Fixed Issues -1. [issue] - [commit SHA] +Report mode/scope, checks/results, fixes, deferred findings with owners, and +residual risks. Map applicable criteria to check/result, evidence reference, +reviewed scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. +Code coverage and task checkboxes are not acceptance evidence. -### Deferred Issues -1. [issue] - [why deferred] - [owner] - -### Routed Follow-ups (if any) -- [security|performance|architecture|design] - [reason] - -### Ship Readiness -[READY TO SHIP | NEEDS FIXES | BLOCKED] -``` +Verdict: `READY TO SHIP`, `NEEDS FIXES`, or `BLOCKED`. Required failed/unrun checks +prevent full verification; name policy-approved exceptions and approvers without +reporting a pass. Production outcomes needing observation remain follow-ups. +Sanitize evidence references; do not persist secrets or sensitive logs. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"verify","artifact_type":"skill","artifact_version":"20260421026","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"verify","artifact_type":"skill","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/vision/SKILL.md b/.github/skills/vision/SKILL.md index 2a3cdedc..bcd86e82 100644 --- a/.github/skills/vision/SKILL.md +++ b/.github/skills/vision/SKILL.md @@ -206,4 +206,4 @@ For each finding: explain the tradeoff, give an opinionated recommendation, ask Present as: "Overall assessment: [READY/NEEDS REVISION/SCOPE CHANGE] because [1-2 sentence reason]." <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"vision","artifact_type":"skill","artifact_version":"20260421027","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"vision","artifact_type":"skill","artifact_version":"20260421027","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.github/skills/workflow-check/SKILL.md b/.github/skills/workflow-check/SKILL.md index dc7ec077..b481efd2 100644 --- a/.github/skills/workflow-check/SKILL.md +++ b/.github/skills/workflow-check/SKILL.md @@ -71,4 +71,4 @@ Provide an ordered short list of actions. - expected result <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"workflow-check","artifact_type":"skill","artifact_version":"20261017002","generator":"vstack","vstack_version":"3.7.8"} --> +<!-- VSTACK-META: {"artifact_name":"workflow-check","artifact_type":"skill","artifact_version":"20261017002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index fddd006c..20d887a5 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -1,400 +1,400 @@ { "manifest_version": 2, "hash_algorithm": "sha256", - "vstack_version": "3.7.8", - "installed_at": "2026-10-17T13:59:31.708252+00:00", + "vstack_version": "4.0.0", + "installed_at": "2026-10-26T19:52:12.809254+00:00", "artifacts": { "skills": [ { "name": "adr", "file": "skills/adr/SKILL.md", "version": "20260421003", - "checksum": "72eda96c3453eac00ec5330fae911ee85002e95eff342063c470fd68505df8fb", + "checksum": "57f6e2dda86a40252ec2824eaa7559162dd31263177e3f631f210513d18af0e7", "checksum_algorithm": "sha256" }, { "name": "advise", "file": "skills/advise/SKILL.md", "version": "20261017001", - "checksum": "2def57807e24d3bab21019c624dfb4e020ba8890d35fb4fc4f0e312fd52fc7cf", + "checksum": "a1b7241f93f24788b07b306cd6d9825743afd55c4a1b6ae6dc0e959237033764", "checksum_algorithm": "sha256" }, { "name": "analyse", "file": "skills/analyse/SKILL.md", - "version": "20260421004", - "checksum": "8bcbeab92d87042b11984d43fdb2e5848b91d7eba2a5b32762f2bb7e38e54eee", + "version": "20261026001", + "checksum": "7a3479a96b4109f7e1dd87f0000d26ba2b94af8f3a7c63757a4efc6465fd3c08", "checksum_algorithm": "sha256" }, { "name": "architecture", "file": "skills/architecture/SKILL.md", "version": "20260421005", - "checksum": "951f1263fa436776c03c600f03b90aa8c5e70f38725eebd208cfa59fd8332835", + "checksum": "1c0e7599fe2e4d191bd84d35f2953b51a7be6758095e90dc3a40881698cea173", "checksum_algorithm": "sha256" }, { "name": "ask", "file": "skills/ask/SKILL.md", "version": "20260618001", - "checksum": "d4afd5223334735dc5bf71691c04355d72d58cbf7a48e7357c7ad69204fbb859", + "checksum": "4a2ceb35a5183eedbe84db97a6b7d8b71a4bfcd7cbb7762905ed9efcc00e6774", "checksum_algorithm": "sha256" }, { "name": "aws-cli", "file": "skills/aws-cli/SKILL.md", "version": "20260502033", - "checksum": "b82ffa42102b2142d57e66b3c2957d9483d7d33e3e3dfa86ff4980f8f9884a6a", + "checksum": "fd47e526087dac0fa425da3ef897050a3d41313fa0388e6af035cb25d9ce84af", "checksum_algorithm": "sha256" }, { "name": "changedoc", "file": "skills/changedoc/SKILL.md", - "version": "20260625001", - "checksum": "e2d5c3f920be7e651d90f6e4092940fd9bcd7444d7814e606f95b10317e1435d", + "version": "20261026001", + "checksum": "525fb1c8967b30ba4bfe5a059760e2995f1bd5bf9da03c100e451374591c20ec", "checksum_algorithm": "sha256" }, { "name": "cicd", "file": "skills/cicd/SKILL.md", "version": "20260421006", - "checksum": "b4678e25b122d8cd296427b01ae34879ab6877c2122addd55c4cb5aadd90dcd6", + "checksum": "b515514bcedf046d9e774512def23c4363ea618ec93d0ce470cc806aa0e2f4fb", "checksum_algorithm": "sha256" }, { "name": "cloudformation", "file": "skills/cloudformation/SKILL.md", "version": "20260502032", - "checksum": "78d31157b5f4de679a017372a1fffe41f7a797762832ba5f95b572d0254c7679", + "checksum": "bd34b9b444361d355233770ff4da918d3c30bb5b65c23bc8fdbd042377be31d7", "checksum_algorithm": "sha256" }, { "name": "code-review", "file": "skills/code-review/SKILL.md", "version": "20260421007", - "checksum": "13338dfae6a5bfd70cb6dd7d3fbe085fa128c0cd8fe16add745614ba160cafd9", + "checksum": "7c5771f0aa826c0e4f44bd6ae0cd170eec8ceeece2156b9ae35c3df1a868a4bf", "checksum_algorithm": "sha256" }, { "name": "codeql", "file": "skills/codeql/SKILL.md", "version": "20260502026", - "checksum": "3fff3656238acab6ac67d5af31c9486294efb22cfa02e6f02b845b3dcacda1be", + "checksum": "33c636e586f0678f0287e851e3f2e4ee45aec76332495fac0c2dade5dcbf573b", "checksum_algorithm": "sha256" }, { "name": "concise", "file": "skills/concise/SKILL.md", "version": "20260421008", - "checksum": "b512650d9194412a18ed783f02756b0e1d6d9ea97dcebda75090bffe1109e798", + "checksum": "698d716b1ef972209b96eb1c5d271f67eb511ae1394ca958572a437a981b2adc", "checksum_algorithm": "sha256" }, { "name": "consult", "file": "skills/consult/SKILL.md", "version": "20260421009", - "checksum": "2d19fc019765961b80c32ffdb5dad11f83e394255a7d4954786cecca7767bb0a", + "checksum": "7073fd92580db76801406367896500883b92fa164729f8c7db37e3941bc7a3e9", "checksum_algorithm": "sha256" }, { "name": "container", "file": "skills/container/SKILL.md", "version": "20260421010", - "checksum": "b4b48e05480bc26519d997ccef254158db48ef209d1b3267da8983162ecc77df", + "checksum": "a6620318fb315b5ba7aa13e1975cf3bc30dcb8fc477d3a4b3136c7df1743aefc", "checksum_algorithm": "sha256" }, { "name": "conventional-commit", "file": "skills/conventional-commit/SKILL.md", "version": "20260502024", - "checksum": "2d92c9c1efb79a7cd15d37cd5d244307693056c78373af94fb8480e10067827b", + "checksum": "db6379d910ff6abf1dbb5b98964676ba109d42d376503d0dd676d0b6cb445658", "checksum_algorithm": "sha256" }, { "name": "copilot-ops", "file": "skills/copilot-ops/SKILL.md", "version": "20260513012", - "checksum": "29fa2f9968fe62ed9fb0cd3f104e9f5ab59f648e8b501bdada8ffbd58f878a8d", + "checksum": "c96fb74625eaaab79b1fa54c4e78e8f1e79d92f4b11968898a30002b2863c879", "checksum_algorithm": "sha256" }, { "name": "debug", "file": "skills/debug/SKILL.md", "version": "20260421011", - "checksum": "8be2e80664a06f288703cb4585210482d3151fff7190e6b7a5f9e5cf524acb62", + "checksum": "c882d18d9ec19e498cd8dc5e46cffbf3e43d871d6d188f39bd281b4871ef4e36", "checksum_algorithm": "sha256" }, { "name": "dependabot", "file": "skills/dependabot/SKILL.md", "version": "20260502027", - "checksum": "ed8d4e5851a3c3c1a24d8765f1e38a7467e6970508fb878335a3e0d7bb24aa0b", + "checksum": "0dc3a7ff7da5c9272bd8d0797be09ae8d958f2574455cd144d91fa023316c329", "checksum_algorithm": "sha256" }, { "name": "dependency", "file": "skills/dependency/SKILL.md", "version": "20260421012", - "checksum": "d8419ccccf92f27fa2f557b2d5aaad1dcf2dd8f07b9b2ae60f323a56adf657cd", + "checksum": "c6e1090a2f548e6c1796caad5267e739d90916faf8b822dade9f856c1d3cf970", "checksum_algorithm": "sha256" }, { "name": "design", "file": "skills/design/SKILL.md", "version": "20260421013", - "checksum": "79db85fea4d04eebe34f7f09664bfc79ecd483bb4040ff0466b2d8252b042aca", + "checksum": "a4a8d07286e698f6dfb805886331607aaf166ef955540a5358cf84027f823bb1", "checksum_algorithm": "sha256" }, { "name": "docs", "file": "skills/docs/SKILL.md", "version": "20260421014", - "checksum": "3c00ecce65a66f041ad0c10894349a8c8428a59aa31c21795e6895dab2bd2ef1", + "checksum": "2afcd0f7ece661f7b6867e43f92dcc0f2c2dc0cb5593d37d4424c55b9797194d", "checksum_algorithm": "sha256" }, { "name": "explore", "file": "skills/explore/SKILL.md", "version": "20260611001", - "checksum": "03d1fb8539e2372c33046c56c90af82b13b43615e71dc9c2d9916c33a7755118", + "checksum": "97aca5719b3fd95014a4459ec41a72f3a6eed264f8d4ccaac3af53b369e6566d", "checksum_algorithm": "sha256" }, { "name": "gdpr", "file": "skills/gdpr/SKILL.md", "version": "20260502029", - "checksum": "fdbafa43a37eb6fe9657c08f6a63e97c482763124aec5a5a92a9277300dad767", + "checksum": "14676a9619adc2fd8a7860b43d0410e5186f9ff8e894321c9e990d9a91574663", "checksum_algorithm": "sha256" }, { "name": "gh-issues", "file": "skills/gh-issues/SKILL.md", "version": "20260502025", - "checksum": "0766599fb6133caa0628615883ed3f95e41b498c01e7957fd4a44d021651830d", + "checksum": "02608a2b9cf5897080c2fc8863720d33bba25d62ecec1e8a779df6752eb17de7", "checksum_algorithm": "sha256" }, { "name": "gh-release", "file": "skills/gh-release/SKILL.md", "version": "20260502023", - "checksum": "7382cd0752d617847fb70bdcc77c13a2c23aff609c4e0431e9890aa488c74220", + "checksum": "5258612494589f087066fb63bb909fd2cce15657b0605c2cf4df1fbd10a18aac", "checksum_algorithm": "sha256" }, { "name": "guardrails", "file": "skills/guardrails/SKILL.md", "version": "20260421016", - "checksum": "13ff3280958b14b2c0160b33e08b5bd37a474fd5556f211b22e67d2c3cfd6d31", + "checksum": "bfec2c2dc198add17d794e2db73dfc639b9870b009a23f609ce406c1e13fa46b", "checksum_algorithm": "sha256" }, { "name": "helm", "file": "skills/helm/SKILL.md", "version": "20260502037", - "checksum": "a2abc7e1d1614d55990be395ddf299fc4a0b08d6e51f16495751a244d59912c9", + "checksum": "87680721e10e98c62c444bac21150106755b171f4ec174d6d3236b3287a8e902", "checksum_algorithm": "sha256" }, { "name": "incident", "file": "skills/incident/SKILL.md", "version": "20260503002", - "checksum": "581de57435857e3b81b740ed43030db99fa6c5604c6880672fa916e01bc1f85f", + "checksum": "a085a5deb42d1dc621875b4a103fd010371a54c1ed49d09de1678f887c6a1c7c", "checksum_algorithm": "sha256" }, { "name": "inspect", "file": "skills/inspect/SKILL.md", - "version": "20260421018", - "checksum": "0d26174e8afadea8b26e5ebf83cf1115d1ab96600c9d03d49ece71d07ada5aa3", + "version": "20261026001", + "checksum": "a774cf72907b87466a7609eeb4f0cc3706a02aeeac0f1b3acfd392f5deba1301", "checksum_algorithm": "sha256" }, { "name": "k8s", "file": "skills/k8s/SKILL.md", "version": "20260502036", - "checksum": "536efea082ff4c26dfdf6e22af7504da852447813deb61d1cb99f2b5b0651061", + "checksum": "a6bf721c63a4254f89f43b0c773a18176b1aa6698ac98d49ff36604fc02c7c56", "checksum_algorithm": "sha256" }, { "name": "lazy", "file": "skills/lazy/SKILL.md", "version": "20260625001", - "checksum": "6e455e539e8534194d9e017ce4bbccc77fb5fa1fd65e41d24b7c40958c1a49a0", + "checksum": "26513f6d3b52842025a4c70ac8806a65a3634e8fecb07d6054c2e3469731f5f9", "checksum_algorithm": "sha256" }, { "name": "migrate", "file": "skills/migrate/SKILL.md", "version": "20260421019", - "checksum": "f3794467cce63919af9d6595aa17e4c0a9d7246e52373364cc321c109fbf6562", + "checksum": "2f6480e46b350f0f0186bff97432b74a42e561c8cb586c46f7ede3396a331d6a", "checksum_algorithm": "sha256" }, { "name": "migration-plan", "file": "skills/migration-plan/SKILL.md", "version": "20261017001", - "checksum": "36b4591572c18a07f5c6048d180bebca95202c4809c518129a2d509984de3dc1", + "checksum": "2cc395d997e29796aa8afa040b6abe10bea5d7f8f2d976b85697f2205ff321f3", "checksum_algorithm": "sha256" }, { "name": "onboard", "file": "skills/onboard/SKILL.md", "version": "20260421020", - "checksum": "680e5f0031ab810e476f2345a88e92d29896ab5cf0ec85ef69a08b827728faf7", + "checksum": "aa4de40024726a7ab03547548efd21cb15c0156e331c0abf304bd28120b03b84", "checksum_algorithm": "sha256" }, { "name": "openapi", "file": "skills/openapi/SKILL.md", "version": "20260421021", - "checksum": "77a00cc691d80d005206d6386b2b660c310a7cffa427eb8dc6e6390d0984d9f2", + "checksum": "5c9edd5cc8d135d4991687b05ad41e4e078c8352df611ab1f33b48b54070231c", "checksum_algorithm": "sha256" }, { "name": "performance", "file": "skills/performance/SKILL.md", "version": "20260421022", - "checksum": "e25e3983ce8be1b2218edfab23cae831eea75a675a715bd781123ce0e21005ee", + "checksum": "75a4460e5c53c7f4b55b8413ca9c1cccfaa82e550770f9c5d3bb4d712d89ac0d", "checksum_algorithm": "sha256" }, { "name": "postmortem", "file": "skills/postmortem/SKILL.md", "version": "20260503001", - "checksum": "5ffcfb1109f517545b4eb8eb994e64b18beaa49e88639ceacf754488067ecb6e", + "checksum": "f9e78128c6f8ef33f047336997a060cb271615c1edf2119c5f2b1c6ebf508f32", "checksum_algorithm": "sha256" }, { "name": "pr", "file": "skills/pr/SKILL.md", "version": "20260502013", - "checksum": "c78d09eb0f127b68b5e82ef4b678ed5e95edcacfb39b5ddb9a536beb2a5b9dd4", + "checksum": "fe27680c661475334ca97bbb0ba46f7516a4a351bdd58c0f39af975817627c99", "checksum_algorithm": "sha256" }, { "name": "rancher", "file": "skills/rancher/SKILL.md", "version": "20260502038", - "checksum": "08822bed0bab149168ff63ea3b58363ecec2e88e8b05dcf603e8906945457cb4", + "checksum": "c6edece85d25b5f3d84cf4cc10cc080f1839ac759d1b159d2cc9373a3efb9ea4", "checksum_algorithm": "sha256" }, { "name": "rca", "file": "skills/rca/SKILL.md", "version": "20260503001", - "checksum": "e2922ee44a376117779a6e3d09a1f6c75bd7eff0e8ce34353c319856836cdf55", + "checksum": "23144ca4bddb0369d11d4f2606236410a01544d6a8f91409c1836ade861a291d", "checksum_algorithm": "sha256" }, { "name": "reasoning", "file": "skills/reasoning/SKILL.md", "version": "20261017001", - "checksum": "211eba9546932db6636f5158336ed25b9d327117d1a8f0b0f7cd2ef9d070e922", + "checksum": "bafc1117745755251ec5ad8b825c8233a183ecaadfbf72b900dea940ffed454d", "checksum_algorithm": "sha256" }, { "name": "refactor", "file": "skills/refactor/SKILL.md", "version": "20260421023", - "checksum": "cdc4a2b846353ccb8b5255bab6095477885cd1228cba7815cab3638b6d71f570", + "checksum": "44108358a3a1b3e576aa3998e8d5812fdaae6adf5b1f0f26f229b2f1c9f96b10", "checksum_algorithm": "sha256" }, { "name": "release-check", "file": "skills/release-check/SKILL.md", "version": "20261017001", - "checksum": "fccdb0eee1f9949737a086306e6881b44040406151c9f001cbd60e2275714753", + "checksum": "4868b3a7a1e5e4c51169e70203eb98c5436a694a2fb9d2ab3e4e1eb0ab12bd0f", "checksum_algorithm": "sha256" }, { "name": "release-notes", "file": "skills/release-notes/SKILL.md", "version": "20260502014", - "checksum": "fb499779b035a4cb205f2ee8b2d68cb171b6dbd0a77190352faefa1a5b80b5c1", + "checksum": "de5a66e01f6041146a84c6e82f000a46f6e7fc374154a7d36abca89d37c7e4b2", "checksum_algorithm": "sha256" }, { "name": "requirements", "file": "skills/requirements/SKILL.md", - "version": "20260421024", - "checksum": "ccc0512888c77f1982420d75f25058d703229c2c8ec20cef6859c1c473b83ac5", + "version": "20261026001", + "checksum": "70c43366d0fca199c13fcf520f6c1d589b89febaa50bacd82c2c1b7cfcb38b98", "checksum_algorithm": "sha256" }, { "name": "secret-scan", "file": "skills/secret-scan/SKILL.md", "version": "20260502028", - "checksum": "b3c6e70d8b7069b36e38668afb48d55cce542d938bd3b25bced6e9db356c906c", + "checksum": "326bf56c1c8647e081f7322705932ee27b7dad82e33233cd02cf526550b1ee98", "checksum_algorithm": "sha256" }, { "name": "security", "file": "skills/security/SKILL.md", "version": "20260421025", - "checksum": "f6f154b990cea5d39d189409801c4478d5351cb5d445f246c07120cbadd24425", + "checksum": "df72f10429b05fcb449c6184964b6d05d27eb1797fb2adc811a239d3eca4a986", "checksum_algorithm": "sha256" }, { "name": "simplify", "file": "skills/simplify/SKILL.md", "version": "20260625001", - "checksum": "6c60f49f9561fe30e699cbfcdab19259c1aa4b34cd917d7bf1ac531adb32ac74", + "checksum": "bb552d646c76721dd8345da4945cfc10218fcccaf5d91d6887b5c07ff8d16979", "checksum_algorithm": "sha256" }, { "name": "space-setup", "file": "skills/space-setup/SKILL.md", "version": "20260513011", - "checksum": "67a5c30d448b7d1a1fd550cc69dc8c7b050af2d836ce1bb67d1d0c84d78ad769", + "checksum": "99022689ea2a1a09708c9999c7c9b5fc40a94330814c13abba38834f3f3b3226", "checksum_algorithm": "sha256" }, { "name": "terraform", "file": "skills/terraform/SKILL.md", "version": "20260502030", - "checksum": "58d82a79f299a6ab227ff36dd0a1cc39c71e51259f1eda78d1adf4917a216946", + "checksum": "78d442668a2b8798e0d6d68a5f62a4ab32c1c0aee6ff8890fa4693166001d383", "checksum_algorithm": "sha256" }, { "name": "terragrunt", "file": "skills/terragrunt/SKILL.md", "version": "20260502031", - "checksum": "89910e245a0712b613be361f682b262c1492ef45fb8e6800d159613779a5b987", + "checksum": "dfa7e04eccc8280908468febf672efe8ffd5d648f0c5f2c0e4d849f32abe7908", "checksum_algorithm": "sha256" }, { "name": "threat-model", "file": "skills/threat-model/SKILL.md", "version": "20260502021", - "checksum": "68d2f41fdc7217c0df316f8417fa3f386e0f17562caa09ecd10405f925abd82f", + "checksum": "d2d871f18b472f236a8f3bc1e29adc02a0b05894c312d3e2cb0cc535bbb86bf8", "checksum_algorithm": "sha256" }, { "name": "upgrade-plan", "file": "skills/upgrade-plan/SKILL.md", "version": "20261017001", - "checksum": "e78c6489648b9574d87f5fb807ce2706f9e03a6f57a890f0ce1a9388a8354edb", + "checksum": "a8971e037dbdc5fdc7b4e9bf59cb2bc59061652679d1d9fa983149f01557b78c", "checksum_algorithm": "sha256" }, { "name": "verify", "file": "skills/verify/SKILL.md", - "version": "20260421026", - "checksum": "ee676a885b9aa2764078458161160a2e0367174f91c10fcb25aacf659bc8f2f0", + "version": "20261026001", + "checksum": "3e15e18309f0b13c51ba79ba6c1b210f2dd61b7225492537d6e894c7b7e9de90", "checksum_algorithm": "sha256" }, { "name": "vision", "file": "skills/vision/SKILL.md", "version": "20260421027", - "checksum": "0b6a83f54c77620f30e2b114869ca4b4964f500cc47af4ed4a468733847fa0a8", + "checksum": "629c8c3957493125e25d3d60a5203e0d2e9e5907fc1d4eecb5ee452723887c88", "checksum_algorithm": "sha256" }, { "name": "workflow-check", "file": "skills/workflow-check/SKILL.md", "version": "20261017002", - "checksum": "aa68d768a44fed5e142ddc1d66c8958fdf1636284294ecf93dc255e7011b1428", + "checksum": "f8066d6f685418671992a75e103b96ce9b18bb0622c656c49ab93d3a382a69fb", "checksum_algorithm": "sha256" } ], @@ -402,50 +402,50 @@ { "name": "architect", "file": "agents/architect.agent.md", - "version": "20260514001", - "checksum": "32e78f403e974932d315c8efa4dbfe863e1c4d7e0a546769e63f7cee199f87a1", + "version": "20261026001", + "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", "checksum_algorithm": "sha256" }, { "name": "designer", "file": "agents/designer.agent.md", - "version": "20260514001", - "checksum": "b2e3dd6aa205ff11e44dcda1f06b80e01b2b44c1011b0a1cbee8962e79cb4c2b", + "version": "20261026001", + "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", "checksum_algorithm": "sha256" }, { "name": "engineer", "file": "agents/engineer.agent.md", - "version": "20260514001", - "checksum": "8239b7e880aa26414aa9e0b3524818e0aad8bb892b7ca0af9af6d1a0f253e5a8", + "version": "20261026001", + "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", "checksum_algorithm": "sha256" }, { "name": "planner", "file": "agents/planner.agent.md", - "version": "20260514001", - "checksum": "e648dcc71fea5989c275af5f4bf204a76615e3bd8195d2ab00e81aaa7a741d4c", + "version": "20261026001", + "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", "checksum_algorithm": "sha256" }, { "name": "product", "file": "agents/product.agent.md", - "version": "20260514001", - "checksum": "55b55479eef30115bb00f48a3a1869992f22ba33d1782a096cda059394692bf2", + "version": "20261026001", + "checksum": "55b959b8f6d6b4f933776b27d3dbd453a635afca1944a3605df09ff47175d992", "checksum_algorithm": "sha256" }, { "name": "release", "file": "agents/release.agent.md", - "version": "20260514001", - "checksum": "a8879577a8fa1f664c9731104775ea463d5a38c7d76c036c1d766a7a11202b7b", + "version": "20261026001", + "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", "checksum_algorithm": "sha256" }, { "name": "tester", "file": "agents/tester.agent.md", - "version": "20260514001", - "checksum": "2e3dc966d3e78e11a381c01bc331e56107164818cf0aceea3528d3cacce59bb9", + "version": "20261026001", + "checksum": "53d022b0253dfdfcbcf6c4e0f86ba6649e0b91d3635b9e9fd2b56a18fe34f945", "checksum_algorithm": "sha256" } ], @@ -453,49 +453,49 @@ { "name": "agent-call-audit", "file": "hooks/agent-call-audit.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", "checksum_algorithm": "sha256" }, { "name": "log-retention-cleanup", "file": "hooks/log-retention-cleanup.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", "checksum_algorithm": "sha256" }, { "name": "post-commit-security-scan", "file": "hooks/post-commit-security-scan.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", "checksum_algorithm": "sha256" }, { "name": "post-edit-format", "file": "hooks/post-edit-format.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", "checksum_algorithm": "sha256" }, { "name": "post-edit-markdown-quality", "file": "hooks/post-edit-markdown-quality.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", "checksum_algorithm": "sha256" }, { "name": "pre-tool-safety-gate", "file": "hooks/pre-tool-safety-gate.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", "checksum_algorithm": "sha256" }, { "name": "session-audit", "file": "hooks/session-audit.json", - "version": "3.7.8", + "version": "4.0.0", "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", "checksum_algorithm": "sha256" } @@ -505,84 +505,84 @@ "name": "git", "file": "instructions/git.instructions.md", "version": "20260421001", - "checksum": "b41e3da9ce908e6143053832353829be0d0c3a0dae99140fedb7ed83d7189f84", + "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", "checksum_algorithm": "sha256" }, { "name": "helm", "file": "instructions/helm.instructions.md", "version": "20260502040", - "checksum": "dd90cca8401be666a8ca7703a6fd0917df546ec9904f142b56e14e851b51a5ac", + "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", "checksum_algorithm": "sha256" }, { "name": "java", "file": "instructions/java.instructions.md", "version": "20260502001", - "checksum": "5556bbc815d2406472fb168e143b1df2eabe2d7935e24ac466c1e9802d80ae64", + "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", "checksum_algorithm": "sha256" }, { "name": "k8s", "file": "instructions/k8s.instructions.md", "version": "20260502039", - "checksum": "25f892ec4c459aa9d7c924197d3bd3f094c7f987d586f6b46b54f243329d5d73", + "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", "checksum_algorithm": "sha256" }, { "name": "markdown", "file": "instructions/markdown.instructions.md", "version": "20260502002", - "checksum": "d03f1da80b1a0913231972bbe9dc37833194f96f5dfebefe888e724191734080", + "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", "checksum_algorithm": "sha256" }, { "name": "python", "file": "instructions/python.instructions.md", "version": "20260421002", - "checksum": "c31f929e489c28c4be92cab4483b13eeb575baf6e4d3995b1c806f81d69800c3", + "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", "checksum_algorithm": "sha256" }, { "name": "rancher", "file": "instructions/rancher.instructions.md", "version": "20260502041", - "checksum": "796d1c16f97b4bbe890293b254949935e1af97eb58ec52c9504d1f5323459628", + "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", "checksum_algorithm": "sha256" }, { "name": "security", "file": "instructions/security.instructions.md", "version": "20260502003", - "checksum": "001d506762be4e2323cb7c672cd29fdc00cf94a6ef68e08e049cb61690f3e76a", + "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", "checksum_algorithm": "sha256" }, { "name": "terraform", "file": "instructions/terraform.instructions.md", "version": "20260502034", - "checksum": "ecf3257ebae88d937253e25b6a8b2a121ab53d62bf7f70ecbd76d784d01731e0", + "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", "checksum_algorithm": "sha256" }, { "name": "terragrunt", "file": "instructions/terragrunt.instructions.md", "version": "20260502035", - "checksum": "6660677347ba0cb52e858f81f3dcb1177b42dfba02148cddb865dc08a2adb4df", + "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", "checksum_algorithm": "sha256" }, { "name": "testing", "file": "instructions/testing.instructions.md", - "version": "20260502004", - "checksum": "417c388a626a7c6dbd9072f5ab8f6ff47e7d2cabe8218cae61aefae415668aed", + "version": "20261026001", + "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", "checksum_algorithm": "sha256" }, { "name": "typescript", "file": "instructions/typescript.instructions.md", "version": "20260502005", - "checksum": "a320659b42fdda47e5548a36b451d907c7c13daf93e4267721cf97a566e51101", + "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", "checksum_algorithm": "sha256" } ] diff --git a/docs/architecture/adr/033-lightweight-sdd.md b/docs/architecture/adr/033-lightweight-sdd.md new file mode 100644 index 00000000..3305fbaa --- /dev/null +++ b/docs/architecture/adr/033-lightweight-sdd.md @@ -0,0 +1,66 @@ +# ADR-033: Lightweight SDD Through Changedoc Evolution + +**Date:** 2026-10-26 +**Status:** accepted + +## Context + +Existing changedocs describe scope and tests but do not explicitly connect +requirements, execution tasks, and observed verification. Broad changedoc and +report requirements also add ceremony to clear low-risk work. The approved +[change contract](../../changes/lightweight-sdd_changedoc_evolution_20261017.md) +requires stronger agreement and evidence without a second specification system, +new runtime tooling, or increased prompt overhead. + +## Decision + +Extend the changedoc with change-local obligations, optional useful tasks, and +verification evidence. Allow sufficient issue/chat context for clear low-risk +work. Involve relevant owners while preserving configured gates and approvals. +Use existing analyse/inspect/verify procedures for consistency and completion +review; keep the stage-report schema unchanged. + +Keep policy-required baseline reports authoritative. Otherwise use the existing +changedoc or response. Preserve historical documents and additive local-template +seeding; supplement new documents rather than overwriting customized templates. +Replace repetitive guidance with compact, concrete instructions. + +## Alternatives Considered + +| Alternative | Benefit | Limitation and disposition | +| ------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------- | +| Keep current guidance | No adoption work | Weak evidence links and unnecessary ceremony; rejected | +| New spec/task system with parsing and gates | Potential machine enforcement | Duplicate truth, runtime/configuration burden, unproven need; deferred | +| Evolve changedoc and existing procedures | Shared intent/evidence with proportional effort | Advisory compliance needs review; selected | + +## Rationale + +Existing roles already own scope, contracts, implementation, and verification. +Improving their handoffs is smaller and safer than adding artifacts or a second +orchestrator. Explicit evidence states expose gaps without implying that wording +checks, code coverage, or completed tasks prove acceptance. + +## Consequences + +- Old documents remain usable; new sections are additive and task lists optional. +- Required failed/unrun checks block full verification. Approved exceptions name + limitations; they are never passes. +- Agent adherence remains nondeterministic. Static regressions and rendered + scenario review verify guidance, not autonomous delivery reliability. +- Measure source/rendered text size as a compactness proxy, not exact tokens, + credits, or a guarantee of lower session cost. + +## Option B Pipeline Impact + +Future orchestration can reuse stable criterion/evidence references in existing +handoff fields. No mandatory stages, schema fields, revision hashes, approval +signatures, or automated compliance claims are introduced. Configured stage +dependencies and human approvals remain authoritative. + +## Related ADRs + +- [ADR-010](010-artifact-flow.md): preserves role-owned artifact boundaries. +- [ADR-013](013-instructions-vs-skills-boundary.md): test policy stays in instructions; + delivery procedures stay in skills. +- [ADR-020](020-install-init-command-semantics.md): preserves additive seeding. +- [ADR-028](028-dag-dependency-semantics.md): preserves configured prerequisites. diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 9773b96f..59f01a11 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -117,6 +117,14 @@ have defined skill access and artifact ownership. See | release | `docs/releases/YYYYMMDDNN.md`, `CHANGELOG.md`, release PR | | planner | none (coordination only; reads workflow config and stage outputs) | +Change-local intent belongs in one changedoc when durable agreement is needed; +small, clear, low-risk work may use existing issue or conversation context. +Product owns scope/acceptance; relevant roles contribute constraints, tasks, and +evidence. Update shared baselines only for affected shared behavior or contracts. +This adds no artifact family, runtime enforcement, or mandatory full pipeline. +Configured dependencies, approvals, and the stage-report schema remain unchanged. +See [ADR-033](adr/033-lightweight-sdd.md). + ### 5. manifest (`.vstack/vstack.json`) Generated at install time at `.vstack/vstack.json`. Tracks every `.github/` artifact diff --git a/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md b/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md index 99cfda34..413d757b 100644 --- a/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md +++ b/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md @@ -3,10 +3,10 @@ ## Metadata ```yaml -status: CONCEPT +status: IMPLEMENTED type: feature reference: user-request-20261017-lightweight-sdd -last_modified: 2026-10-17 +last_modified: 2026-10-26 ``` ## Goal and Context @@ -16,8 +16,8 @@ role workflows, not by introducing a second specification system. The user requested a proposal that demonstrates the intended approach itself: requirements, acceptance criteria, execution planning, and verification in one -living change document. This document is that proposal, not authorization to -implement it. +living change document. Implementation was authorized on 2026-10-26 after review +of the compact execution plan, with the additional compactness requirement R-15. The intended outcome is stronger agreement on what changes and how correctness is demonstrated, without mandatory ceremony, additional dependencies, or fixed @@ -117,22 +117,23 @@ Small scope does not justify bypassing existing safety or approval policies. The local identifiers below help review this multi-surface change. They are not a proposed requirement for all future tasks, and add no document-level ID. -| Requirement | Obligation | -| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| R-1 | Extend the existing changedoc with change-local requirements, optional execution tasks, and verification outcomes. Do not require separate per-change spec or requirements files. | -| R-2 | Allow focused, low-risk work to use sufficient existing issue or conversation context without creating a changedoc or running every role. Explain escalation when context or risk warrants it. | -| R-3 | Use local criterion references when they improve handoffs or evidence mapping. Preserve established references during revisions; do not require global IDs or renumber existing criteria casually. | -| R-4 | Plan tasks only when useful. Record real prerequisites, not artificial dependencies created by list order or role names. Allow iterative work and multiple changes on one branch. | -| R-5 | Before implementation, establish clear scope, observable acceptance, and resolution of blocking questions. Ask only for decisions that materially affect correctness, risk, scope, or approval. | -| R-6 | Report relevant verification as passed, failed, not run, or no longer current. Include the check and result or an explicit limitation; never equate a task checkbox or codecoverage with acceptance. | -| R-7 | Reassess affected criteria and evidence after material scope or behavior changes. Seek renewed approval only when the approved scope, risk, or project policy requires it. | -| R-8 | Preserve baseline ownership and existing workflow policy. Update system-level baselines only when shared behavior or contracts change, and link instead of duplicating authoritative content. | -| R-9 | Keep this increment template- and documentation-driven, with no new runtime tooling, dependencies, configuration, or automated enforcement. | -| R-10 | Keep existing changedocs and customized seeded templates usable. Do not overwrite local content or require historical backfill. Explain how to adopt the additional guidance. | -| R-11 | Clarify material ambiguity using repository evidence first, then focused questions. Record accepted answers in the existing intent source and review only relevant requirement-quality dimensions. | -| R-12 | Offer a scoped, non-mutating consistency review of requirements, criteria, contracts, and useful tasks through an existing skill. Distinguish missing coverage, contradictions, and unsupported additions. | -| R-13 | Compare implemented behavior with agreed intent, not only the changed lines or task checkboxes. Bound remediation, preserve scope ownership, and stop when approval, missing evidence, or repeated lack of progress prevents completion. | -| R-14 | Select independently verifiable delivery slices when useful. Include relevant error, compatibility, data-lifecycle, and operational behavior without requiring a universal checklist or new documentation tree. | +| Requirement | Obligation | +| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| R-1 | Extend the existing changedoc with change-local requirements, optional execution tasks, and verification outcomes. Do not require separate per-change spec or requirements files. | +| R-2 | Allow focused, low-risk work to use sufficient existing issue or conversation context without creating a changedoc or running every role. Explain escalation when context or risk warrants it. | +| R-3 | Use local criterion references when they improve handoffs or evidence mapping. Preserve established references during revisions; do not require global IDs or renumber existing criteria casually. | +| R-4 | Plan tasks only when useful. Record real prerequisites, not artificial dependencies created by list order or role names. Allow iterative work and multiple changes on one branch. | +| R-5 | Before implementation, establish clear scope, observable acceptance, and resolution of blocking questions. Ask only for decisions that materially affect correctness, risk, scope, or approval. | +| R-6 | Report relevant verification as passed, failed, not run, or no longer current. Include the check and result or an explicit limitation; never equate a task checkbox or codecoverage with acceptance. | +| R-7 | Reassess affected criteria and evidence after material scope or behavior changes. Seek renewed approval only when the approved scope, risk, or project policy requires it. | +| R-8 | Preserve baseline ownership and existing workflow policy. Update system-level baselines only when shared behavior or contracts change, and link instead of duplicating authoritative content. | +| R-9 | Keep this increment template- and documentation-driven, with no new runtime tooling, dependencies, configuration, or automated enforcement. | +| R-10 | Keep existing changedocs and customized seeded templates usable. Do not overwrite local content or require historical backfill. Explain how to adopt the additional guidance. | +| R-11 | Clarify material ambiguity using repository evidence first, then focused questions. Record accepted answers in the existing intent source and review only relevant requirement-quality dimensions. | +| R-12 | Offer a scoped, non-mutating consistency review of requirements, criteria, contracts, and useful tasks through an existing skill. Distinguish missing coverage, contradictions, and unsupported additions. | +| R-13 | Compare implemented behavior with agreed intent, not only the changed lines or task checkboxes. Bound remediation, preserve scope ownership, and stop when approval, missing evidence, or repeated lack of progress prevents completion. | +| R-14 | Select independently verifiable delivery slices when useful. Include relevant error, compatibility, data-lifecycle, and operational behavior without requiring a universal checklist or new documentation tree. | +| R-15 | Keep source templates and rendered guidance consistent, concrete, and compact without losing required content. Replace repetition rather than append boilerplate; measure aggregate text size before and after without claiming exact token or credit savings. | ### Clarification and Quality Review @@ -258,32 +259,34 @@ No new always-on SDD instruction is needed. references, but this increment does not claim machine-enforced compliance. - Documentation: update the skill catalog, workflow/design guidance, and relevant product requirements/roadmap to describe the agreed behavior. - Record a scoped ADR for the changedoc-as-spec and proportional-routing decision - when approved; do not create an ADR for this unapproved proposal. + The approved changedoc-as-spec and proportional-routing decision is recorded + in [ADR-033](../architecture/adr/033-lightweight-sdd.md). - Regeneration: update source templates and regenerate installed artifacts with `vstack install` during implementation; never manually patch generated output. ## Acceptance Criteria -| Criterion | Requirements | Observable result | -| --------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| AC-1 | R-1, R-3 | A representative feature uses one changedoc for requirements, criteria, optional tasks, and evidence, with unambiguous local references and no duplicate spec document. | -| AC-2 | R-2, R-4, R-9 | A clear low-risk fix proceeds from an issue or conversation with focused implementation and verification, without a new changedoc, task registry, or full role pipeline. | -| AC-3 | R-2, R-5, R-8 | An ambiguous or high-risk change identifies blockers and involves the relevant owner before affected implementation, while preserving configured approvals. | -| AC-4 | R-4, R-8 | Independent tasks have no invented prerequisites; a configured multi-role pipeline still follows its declared dependencies and gates. | -| AC-5 | R-6 | Completion identifies evidence or an explicit gap for applicable criteria. Failed or unexecuted required checks are not reported as passed or fully verified. | -| AC-6 | R-3, R-7 | A material requirement or behavior revision preserves existing references, identifies affected tasks/evidence, and triggers only the necessary rework and approval. | -| AC-7 | R-8 | Changed system-level behavior updates the relevant baseline without copying it into a parallel specification tree; change-local details remain in the changedoc. | -| AC-8 | R-9, R-10 | Adoption adds no dependencies, CLI commands, configuration keys, mandatory stage-report fields, or automatic gates. Existing local templates and historical documents remain intact. | -| AC-9 | R-1, R-2, R-5 | Changedoc skill, product/planner instructions, role guidance, and documentation agree on proportional scope and lifecycle; archived documents never authorize new implementation. | -| AC-10 | R-11 | A vague requirement triggers an evidence-informed material question; the answer updates existing intent, while a wording review is not presented as a passed behavioral test. | -| AC-11 | R-12 | A consistency review exposes a conflicting contract, an uncovered obligation, and an unexplained addition without changing code, rewriting acceptance, or requiring a new report file. | -| AC-12 | R-6, R-13 | Completion assessment finds required behavior absent from the diff, reports unavailable evidence, and bounds fixes without silently weakening intent or deleting unexplained additions. | -| AC-13 | R-8, R-14 | A larger change identifies useful verifiable slices and relevant failure boundaries; involved roles and the testing instruction reinforce this without imposing every role, checklist, or test type. | +| Criterion | Requirements | Observable result | +| --------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| AC-1 | R-1, R-3 | A representative feature uses one changedoc for requirements, criteria, optional tasks, and evidence, with unambiguous local references and no duplicate spec document. | +| AC-2 | R-2, R-4, R-9 | A clear low-risk fix proceeds from an issue or conversation with focused implementation and verification, without a new changedoc, task registry, or full role pipeline. | +| AC-3 | R-2, R-5, R-8 | An ambiguous or high-risk change identifies blockers and involves the relevant owner before affected implementation, while preserving configured approvals. | +| AC-4 | R-4, R-8 | Independent tasks have no invented prerequisites; a configured multi-role pipeline still follows its declared dependencies and gates. | +| AC-5 | R-6 | Completion identifies evidence or an explicit gap for applicable criteria. Failed or unexecuted required checks are not reported as passed or fully verified. | +| AC-6 | R-3, R-7 | A material requirement or behavior revision preserves existing references, identifies affected tasks/evidence, and triggers only the necessary rework and approval. | +| AC-7 | R-8 | Changed system-level behavior updates the relevant baseline without copying it into a parallel specification tree; change-local details remain in the changedoc. | +| AC-8 | R-9, R-10 | Adoption adds no dependencies, CLI commands, configuration keys, mandatory stage-report fields, or automatic gates. Existing local templates and historical documents remain intact. | +| AC-9 | R-1, R-2, R-5 | Changedoc skill, product/planner instructions, role guidance, and documentation agree on proportional scope and lifecycle; archived documents never authorize new implementation. | +| AC-10 | R-11 | A vague requirement triggers an evidence-informed material question; the answer updates existing intent, while a wording review is not presented as a passed behavioral test. | +| AC-11 | R-12 | A consistency review exposes a conflicting contract, an uncovered obligation, and an unexplained addition without changing code, rewriting acceptance, or requiring a new report file. | +| AC-12 | R-6, R-13 | Completion assessment finds required behavior absent from the diff, reports unavailable evidence, and bounds fixes without silently weakening intent or deleting unexplained additions. | +| AC-13 | R-8, R-14 | A larger change identifies useful verifiable slices and relevant failure boundaries; involved roles and the testing instruction reinforce this without imposing every role, checklist, or test type. | +| AC-14 | R-15 | Updated source and rendered guidance preserve the required content and contracts, use consistent terminology, and have no aggregate word or byte growth across the changed procedural templates and their rendered counterparts. | ## Execution Tasks -This is a proposed implementation breakdown, not a second role pipeline. +T-1 through T-5 are complete against this approved contract. +This is an implementation breakdown, not a second role pipeline. Tasks may share a branch; ordering below does not imply unstated dependencies. | Task | Scope | Actual prerequisites | Criteria | @@ -294,9 +297,9 @@ Tasks may share a branch; ordering below does not imply unstated dependencies. | T-4 | Add focused template/instruction regressions and evaluate all scenarios below against rendered guidance, including report placement and no-progress handling. | T-2, T-3 | AC-1 through AC-13 | | T-5 | Align baseline docs, record the approved ADR, regenerate managed output, and record final verification. | T-2, T-3; T-4 for final completion | AC-7, AC-8, AC-9 | -T-2 and T-3 can progress independently against this approved contract. -Documentation and test drafting can accompany implementation; their final -verification needs the resulting templates, not a separate upfront sign-off. +T-2 and T-3 progressed independently; test and documentation drafting accompanied +implementation. Their final verification used the resulting rendered templates. +AC-14 was included in T-2 through T-5 following the user's compactness requirement. ## Test Scenarios @@ -336,17 +339,76 @@ verification needs the resulting templates, not a separate upfront sign-off. ## Verification -Implementation verification has not run. This document is a `CONCEPT`. -All AC-1 through AC-13 outcomes remain **not run** for the proposed product change. - -Proposal review can confirm coverage and internal consistency, but cannot mark -these implementation criteria as passed. During implementation, record the -criterion, check, reviewed scope/revision, result, and remaining limitation here. -Use concise references to existing reports rather than duplicating their contents. +Reviewed scope: the 2026-10-26 working tree on `docs/lightweight-sdd-proposal`, +covering source guidance, rendered artifacts, additive seeding, baseline docs, +and focused regressions. No runtime implementation, workflow configuration, or +shared stage-report schema changed. + +### Criterion evidence + +All results below concern the implemented guidance and installation contracts, +not a guarantee that an autonomous model follows them. + +| Criteria | Check and observed result | Status | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | +| AC-1 | This changedoc retains requirements, criteria, tasks, and evidence; the fresh-install regression confirms the extended seed. | passed | +| AC-2, AC-9 | Rendered product/planner permit issue/chat context for clear low-risk work and reject archived-state authorization; regressions cover both. | passed | +| AC-3, AC-4 | Rendered readiness rules pause affected work for material ambiguity and preserve configured dependencies/approvals. Stage-report contract remains unchanged. | passed | +| AC-5, AC-6 | Rendered changedoc/inspect/verify distinguish four evidence states, block false completion, preserve references, and reassess affected work only. | passed | +| AC-7, AC-8 | Baseline docs and ADR-033 align; runtime/configuration stay unchanged. Fresh seeding adds sections; reseeding preserves customized templates and history. | passed | +| AC-10 | Requirements guidance checks known answers first, asks one material question, records it in existing intent, and separates wording quality from behavioral proof. | passed | +| AC-11 | Analyse's rendered consistency review covers contradictions, uncovered obligations, and unsupported additions without intent/code edits or a mandatory new report. | passed | +| AC-12 | Inspect/verify explicitly assess missing work outside the diff, report unavailable evidence, and bound fixes without weakening criteria or deleting additions. | passed | +| AC-13 | Role guidance connects constraints/contracts, verifiable slices, failure boundaries, and criterion evidence; testing policy avoids a universal checklist. | passed | +| AC-14 | Size regression covers all changed procedural sources/configs, the changedoc seed, and rendered guidance. Aggregate words and bytes decreased; see below. | passed | + +### Scenario review + +Reviewed the TS-1 through TS-15 inputs against rendered guidance: + +| Scenarios | Observed instruction outcome | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TS-1, TS-2 | One durable changedoc for handoff; no new document or role pipeline for clear low-risk work. | +| TS-3, TS-8 | Missing migration/approval decisions block affected implementation; archived status gives no authorization. | +| TS-4 | Tasks declare only actual prerequisites; configured stage dependencies remain authoritative, including shared predecessors. | +| TS-5, TS-6 | Checkboxes do not prove acceptance; missing checks remain gaps and material revisions affect relevant evidence only. | +| TS-7 | Customized older templates and historical documents survive reseeding; guidance supplements new documents only. | +| TS-9, TS-10 | Shared contract changes update relevant baselines; local refactors do not. Prose needs document checks, operational behavior needs relevant measurements. | +| TS-11 | Existing answers are read first; only remaining material uncertainty triggers a question. Wording review is not runtime proof. | +| TS-12 | Analyse identifies conflicting contracts, uncovered obligations, and unrelated tasks without edits or compulsory extra reports. | +| TS-13, TS-14 | Missing behavior/evidence is reported; repeated no-progress fixes stop. Unrelated additions need a scope decision, not deletion; helpers need no separate requirement. | +| TS-15 | Useful slices and relevant retry/concurrency checks are supported without mandatory roles or universal checklists. | + +These are rendered-guidance reviews, supported by static regressions and golden +fixtures, not live autonomous-agent experiments. Live agent adherence is **not run**; +adoption reliability remains a follow-up, not a claimed deterministic result. + +### Checks and compactness + +- Focused template/role/instruction/install regressions passed. +- `make check` passed: formatting, Markdown lint, Ruff, mypy, and all tests on + Python 3.14 with 100% code coverage. Python 3.11, 3.12, 3.13, and 3.15 were + **not run** because their interpreters are unavailable; tox reported skips. +- `vstack validate`, regeneration with `vstack install`, and `vstack verify` + passed using the local interpreter and `PYTHONPATH=src`. +- Four affected golden fixtures were regenerated from source. Existing installed + seeded templates were correctly preserved, not manually overwritten. +- Full regeneration also refreshed unchanged artifacts' generator-version + footers from 3.7.8 to the checkout's resolved 4.0.0; no unrelated body changes. + +| Measured scope | Before: words / bytes | After: words / bytes | +| ---------------------------------------------------------- | --------------------- | -------------------- | +| 13 procedural templates, their configs, and changedoc seed | 11,483 / 81,847 | 10,486 / 79,335 | +| 13 rendered skills, agents, and instruction files | 14,763 / 105,562 | 13,390 / 100,625 | + +Source words decreased 8.7%; rendered words decreased 9.3%. Byte counts also +decreased. These are reproducible text-size proxies, not tokenizer measurements +or guaranteed credit/session-cost savings. Regression limits retain the original +aggregate ceilings rather than requiring every individual artifact to shrink. ## Notes -### Decisions Proposed for Review +### Decisions Approved - Use changedoc as the change-local specification, not a new spec artifact type. - Make structure proportional; keep safety obligations independent of size. @@ -355,9 +417,8 @@ Use concise references to existing reports rather than duplicating their content ### Open Questions -No additional product choice is required to review this concrete proposal. -Its recommendations remain subject to approval, especially the focused-task -exception to today's broad changedoc requirement. +The user approved implementation on 2026-10-26, including proportional routing, +and added the compactness requirement R-15. No product decisions remain blocking. How reliably agents follow the lighter routing and evidence guidance is unproven. Scenario evaluation must expose limitations rather than claim a diff --git a/docs/design/overview.md b/docs/design/overview.md index 4920a1d7..d89b0a44 100644 --- a/docs/design/overview.md +++ b/docs/design/overview.md @@ -1,7 +1,7 @@ # vstack — design > Maintained by: **designer** role\ -> Last updated: 2026-05-14 +> Last updated: 2026-10-26 ## overview @@ -23,6 +23,20 @@ ______________________________________________________________________ ## 1. domain model +### change-local specification + +The changedoc is the durable change-local intent source; clear low-risk work may +use issue/chat context. Its additive sections cover requirements, optional tasks, +and verification alongside existing scope, criteria, and scenarios. Metadata and +stage-report schemas are unchanged. Guidance is advisory, not a semantic parser. + +Role artifact templates are seeded additively: existing customized local copies +and historical changedocs remain valid. Supplement new documents through skill +guidance; do not overwrite local templates or backfill history. Source templates +are updated first, then installed artifacts regenerated. Keep guidance compact +without dropping contracts or safety. See [workflow.md](workflow.md) and +[ADR-033](../architecture/adr/033-lightweight-sdd.md). + ### 1.1 artifact lifecycle states An artifact (skill, agent, instruction, hook) exists in one of these states relative diff --git a/docs/design/skills.md b/docs/design/skills.md index 4ade7867..7417ef68 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -1,7 +1,7 @@ # vstack — skills > Maintained by: **designer** role\ -> Last updated: 2026-05-14\ +> Last updated: 2026-10-26\ > VS Code docs: [agent skills](https://code.visualstudio.com/docs/copilot/customization/agent-skills) ## what are skills? @@ -57,63 +57,63 @@ ______________________________________________________________________ List skills in alphabetical order by skill name in every catalog or role skill list. -| Skill | Description | Primary role(s) | Output artifact | -| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------- | -| `adr` | Architecture Decision Record writing. Documents a decision with context, alternatives, and rationale. | architect | `docs/architecture/adr/NNN-*.md` | -| `analyse` | Cross-cutting technical analysis. Investigates impact, tradeoffs, root causes, or feasibility without implementing changes. | engineer, architect | analysis report | -| `architecture` | Engineering-lead plan review. Lock in service boundaries, data models, API contracts, test strategy. | architect | `docs/architecture/overview.md` | -| `ask` | Read-only technical Q&A. Clarifies ambiguous questions, gathers repository evidence, and returns concise answers with references and confidence. | all roles | referenced answer + next-step guidance | -| `aws-cli` | AWS CLI workflows for IAM, S3, EC2, RDS, ECS, Lambda, CloudWatch, Secrets Manager, and SSM Parameter Store. | engineer, tester | — | -| `cicd` | Write GitHub Actions CI/CD workflow configuration. Covers build, test, lint, security scan, container publish, deploy. | release | GitHub Actions workflow | -| `changedoc` | Create and maintain per-change planning documents for existing repositories. Defines metadata, AS-IS, TO-BE, impact, acceptance criteria, and test scenarios before implementation. | planner, product, architect, designer, engineer, tester, release | `docs/changes/<slug>_<title>_YYYYMMDD.md` | -| `cloudformation` | Write and review AWS CloudFormation templates. Parameters, conditions, cross-stack references, change sets, drift detection, and security hardening. | engineer | CFN template `.yaml` | -| `code-review` | Pre-landing code review. Finds bugs that pass CI but break in production — race conditions, security issues, performance landmines. | engineer | inline findings | -| `codeql` | Set up CodeQL code scanning via GitHub Actions or CLI. Language matrix, query suites, monorepo config, alert triage. | tester | `.github/workflows/codeql.yml` | -| `concise` | Runtime response-style controller. Switches response density (`normal`, `compact`, `ultra`) and reports active mode via `status` without reinstall. | all roles | session style state + status output | -| `consult` | DX triage and focused review. Routes to one path (API DX, CLI/tool DX, or developer workflow DX) and routes non-DX requests to specialized skills. | designer | focused DX report or routing recommendation | -| `container` | Write and review Dockerfile, docker-compose, and container config. Covers multi-stage builds, non-root users, layer optimisation. | engineer | Dockerfile + compose | -| `conventional-commit` | Prepare and validate Conventional Commit messages from current changes, with type/scope selection and commit-intent checks before commit. | engineer, release | compliant commit message(s) + commit(s) | -| `copilot-ops` | Operate and govern GitHub Copilot settings. Policy checks, configuration drift, usage visibility, and safe change rollout. | release | Copilot governance operations report | -| `debug` | Systematic root-cause debugging. Follows scientific method: observe → hypothesise → test → conclude → fix → prevent. | engineer | root cause report + fix | -| `dependabot` | Create or optimize `.github/dependabot.yml`. Ecosystem detection, grouping strategies, monorepo patterns, schedule, and PR customization. | engineer, tester | `.github/dependabot.yml` | -| `dependency` | Dependency health audit. Vulnerability scanning, outdated packages, licence compliance, transitive risk, pinning policy, supply chain hygiene. | engineer, tester | dependency audit report | -| `design` | Build a complete API or service design from scratch. Produces OpenAPI specs, error conventions, naming standards. | designer | `docs/design/overview.md` / `openapi.yaml` | -| `docs` | Post-release documentation alignment for README/API docs/migrations and related artifacts (no CHANGELOG ownership). | product, architect, designer, engineer, tester, release | updated docs artifacts | -| `explore` | Repository and system discovery. Maps the architecture, identifies tech debt, produces an onboarding summary. | engineer | codebase map | -| `gdpr` | GDPR-compliant engineering practices. Privacy by design, data minimization, storage limitation, erasure, encryption, and PR review checklist. | engineer, architect, tester | checklist / PR findings | -| `gh-issues` | Create, update, and manage GitHub Issues via gh CLI. Covers bug/feature/task templates, labels, assignees, milestones, and sub-issues. | release, product | GitHub Issues | -| `gh-release` | Create or update a GitHub Release using gh CLI with tag validation, draft/publish mode, and release notes file integration. | release | GitHub Release | -| `guardrails` | Activate safety guardrails for the session. Requires explicit confirmation before any destructive action. | — | (mode activation) | -| `helm` | Write, review, and operate Helm charts and release lifecycles. Covers lint/template validation, upgrades, rollbacks, and dependencies. | engineer, tester | Helm charts + release config | -| `incident` | Incident analysis and blameless post-mortem writing. Timeline reconstruction, 5-Whys root cause, contributing factors, action items. | tester, engineer | `docs/postmortems/YYYY-MM-DD-*.md` | -| `inspect` | Read-only verification audit. Runs baseline plus optional extended checks and produces severity-ranked findings, with no code or commit changes. | tester | read-only audit report | -| `k8s` | Write, review, and troubleshoot Kubernetes manifests and operations. Covers rollout safety, probes, RBAC, namespace isolation, and diagnostics. | engineer, tester | Kubernetes manifests | -| `lazy` | Engineer-focused minimal-change execution. Prefer avoid/delete/reuse/stdlib/native solutions before writing new code while keeping safety guarantees. | engineer | minimal safe implementation report + changes | -| `migrate` | Database migration review and authoring. Forwards/backwards compatibility, zero-downtime strategies, rollback plans, data integrity, index safety. | engineer, tester | reviewed/corrected migration SQL | -| `migration-plan` | Explicit-only cross-component migration planning with validation and rollback. | engineer | migration plan | -| `onboard` | Generate a contributor onboarding guide. Prerequisites, setup, tests, env vars, architecture overview, good first issues. | product | `CONTRIBUTING.md` + README dev section | -| `openapi` | Write and review OpenAPI 3.1 specifications. Resource naming, HTTP semantics, status codes, error conventions, pagination, security schemes. | designer, engineer | `openapi.yaml` | -| `performance` | Performance profiling and regression detection. Establishes baselines, detects regressions, profiles bottlenecks. | engineer, tester | perf report | -| `postmortem` | Blameless post-mortem writing for incidents. Produces a stakeholder-facing post-mortem document linked to the triggering issue and RCA. | tester, engineer | stakeholder post-mortem | -| `pr` | Commit, push, and open a pull request from the current branch to main. | release | commit + PR | -| `rancher` | Operate Kubernetes workloads and governance through Rancher. Covers project scope, RBAC, Fleet/GitOps basics, and multi-cluster checks. | engineer, tester | Rancher/Fleet config | -| `rca` | Root cause analysis for incidents and bugs. Guides a systematic technical investigation and produces an RCA document linked to the triggering issue. | engineer, tester | technical RCA | -| `reasoning` | Explicit-only evidence-based critical thinking framework. | all roles | evaluation | -| `refactor` | Structured refactoring without behavior change. Identify smells, plan incremental steps, execute, verify correctness. | engineer | refactored code + green tests | -| `release-check` | Explicit-only release evidence and sign-off audit; does not publish. | release, tester | readiness report | -| `release-notes` | Prepare release artifacts: write release notes, own CHANGELOG updates, produce `docs/releases/YYYY-MM-DD.md`. | release | CHANGELOG + release doc | -| `requirements` | Collaborative requirements gathering. Clarifies what must be built, defines success criteria and NFRs. | product | `docs/product/requirements.md` | -| `secret-scan` | Configure GitHub secret scanning and push protection. Path exclusions, custom patterns, alert triage, and credential remediation. | tester, engineer | `.github/secret_scanning.yml` | -| `security` | OWASP Top 10 + STRIDE security audit. Finds auth bypasses, injection flaws, exposed secrets, broken access control. | tester | security audit report | -| `simplify` | Generic simplification skill for all roles. Reduces proposal and execution complexity while preserving required outcomes and safety constraints. | all roles | simplify report + reduced scope/complexity | -| `space-setup` | Set up and maintain a GitHub Copilot Space for a repository. Scope curation, refresh cadence, and context quality checks. | product | Space setup and maintenance checklist | -| `terraform` | Write, review, and refactor Terraform IaC. Module structure, state management, variable conventions, provider pinning, and security hardening. | engineer | Terraform config files | -| `terragrunt` | Write, review, and refactor Terragrunt DRY multi-environment IaC. Root config, dependency blocks, `_envcommon`, and run-all workflows. | engineer | `terragrunt.hcl` files | -| `threat-model` | Threat modeling with STRIDE-first identification, optional DREAD prioritization, and selective PASTA depth for critical systems. | architect, tester, engineer, designer | `docs/architecture/threat-model.md` | -| `upgrade-plan` | Explicit-only upgrade plan with compatibility and rollback checks. | engineer, tester | upgrade plan | -| `verify` | Verification fix-loop with mode routing (quick/standard/exhaustive). Runs targeted checks, fixes by severity, and re-verifies impacted paths. | engineer, tester | fixes + verification report | -| `vision` | CEO/founder-mode plan review. Rethink from first principles, validate ambition, find the 10x solution. | product | `docs/product/vision.md` | -| `workflow-check` | Explicit-only stage, gate, and handoff audit using project configuration, installed agents, and role documents; no vstack source templates required. | planner, tester | workflow report | +| Skill | Description | Primary role(s) | Output artifact | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------- | +| `adr` | Architecture Decision Record writing. Documents a decision with context, alternatives, and rationale. | architect | `docs/architecture/adr/NNN-*.md` | +| `analyse` | Scoped impact, tradeoff, cause, feasibility, risk, or consistency review; no implementation or silent intent edits. | engineer, architect | findings in response or authorized existing document | +| `architecture` | Engineering-lead plan review. Lock in service boundaries, data models, API contracts, test strategy. | architect | `docs/architecture/overview.md` | +| `ask` | Read-only technical Q&A. Clarifies ambiguous questions, gathers repository evidence, and returns concise answers with references and confidence. | all roles | referenced answer + next-step guidance | +| `aws-cli` | AWS CLI workflows for IAM, S3, EC2, RDS, ECS, Lambda, CloudWatch, Secrets Manager, and SSM Parameter Store. | engineer, tester | — | +| `cicd` | Write GitHub Actions CI/CD workflow configuration. Covers build, test, lint, security scan, container publish, deploy. | release | GitHub Actions workflow | +| `changedoc` | One durable change-local specification: requirements, criteria, scenarios, optional tasks, and evidence. | planner, product, architect, designer, engineer, tester, release | `docs/changes/<slug>_<title>_YYYYMMDD.md` | +| `cloudformation` | Write and review AWS CloudFormation templates. Parameters, conditions, cross-stack references, change sets, drift detection, and security hardening. | engineer | CFN template `.yaml` | +| `code-review` | Pre-landing code review. Finds bugs that pass CI but break in production — race conditions, security issues, performance landmines. | engineer | inline findings | +| `codeql` | Set up CodeQL code scanning via GitHub Actions or CLI. Language matrix, query suites, monorepo config, alert triage. | tester | `.github/workflows/codeql.yml` | +| `concise` | Runtime response-style controller. Switches response density (`normal`, `compact`, `ultra`) and reports active mode via `status` without reinstall. | all roles | session style state + status output | +| `consult` | DX triage and focused review. Routes to one path (API DX, CLI/tool DX, or developer workflow DX) and routes non-DX requests to specialized skills. | designer | focused DX report or routing recommendation | +| `container` | Write and review Dockerfile, docker-compose, and container config. Covers multi-stage builds, non-root users, layer optimisation. | engineer | Dockerfile + compose | +| `conventional-commit` | Prepare and validate Conventional Commit messages from current changes, with type/scope selection and commit-intent checks before commit. | engineer, release | compliant commit message(s) + commit(s) | +| `copilot-ops` | Operate and govern GitHub Copilot settings. Policy checks, configuration drift, usage visibility, and safe change rollout. | release | Copilot governance operations report | +| `debug` | Systematic root-cause debugging. Follows scientific method: observe → hypothesise → test → conclude → fix → prevent. | engineer | root cause report + fix | +| `dependabot` | Create or optimize `.github/dependabot.yml`. Ecosystem detection, grouping strategies, monorepo patterns, schedule, and PR customization. | engineer, tester | `.github/dependabot.yml` | +| `dependency` | Dependency health audit. Vulnerability scanning, outdated packages, licence compliance, transitive risk, pinning policy, supply chain hygiene. | engineer, tester | dependency audit report | +| `design` | Build a complete API or service design from scratch. Produces OpenAPI specs, error conventions, naming standards. | designer | `docs/design/overview.md` / `openapi.yaml` | +| `docs` | Post-release documentation alignment for README/API docs/migrations and related artifacts (no CHANGELOG ownership). | product, architect, designer, engineer, tester, release | updated docs artifacts | +| `explore` | Repository and system discovery. Maps the architecture, identifies tech debt, produces an onboarding summary. | engineer | codebase map | +| `gdpr` | GDPR-compliant engineering practices. Privacy by design, data minimization, storage limitation, erasure, encryption, and PR review checklist. | engineer, architect, tester | checklist / PR findings | +| `gh-issues` | Create, update, and manage GitHub Issues via gh CLI. Covers bug/feature/task templates, labels, assignees, milestones, and sub-issues. | release, product | GitHub Issues | +| `gh-release` | Create or update a GitHub Release using gh CLI with tag validation, draft/publish mode, and release notes file integration. | release | GitHub Release | +| `guardrails` | Activate safety guardrails for the session. Requires explicit confirmation before any destructive action. | — | (mode activation) | +| `helm` | Write, review, and operate Helm charts and release lifecycles. Covers lint/template validation, upgrades, rollbacks, and dependencies. | engineer, tester | Helm charts + release config | +| `incident` | Incident analysis and blameless post-mortem writing. Timeline reconstruction, 5-Whys root cause, contributing factors, action items. | tester, engineer | `docs/postmortems/YYYY-MM-DD-*.md` | +| `inspect` | Read-only intent-to-behavior audit, including missing work and evidence gaps. | tester | required report, existing changedoc, or response | +| `k8s` | Write, review, and troubleshoot Kubernetes manifests and operations. Covers rollout safety, probes, RBAC, namespace isolation, and diagnostics. | engineer, tester | Kubernetes manifests | +| `lazy` | Engineer-focused minimal-change execution. Prefer avoid/delete/reuse/stdlib/native solutions before writing new code while keeping safety guarantees. | engineer | minimal safe implementation report + changes | +| `migrate` | Database migration review and authoring. Forwards/backwards compatibility, zero-downtime strategies, rollback plans, data integrity, index safety. | engineer, tester | reviewed/corrected migration SQL | +| `migration-plan` | Explicit-only cross-component migration planning with validation and rollback. | engineer | migration plan | +| `onboard` | Generate a contributor onboarding guide. Prerequisites, setup, tests, env vars, architecture overview, good first issues. | product | `CONTRIBUTING.md` + README dev section | +| `openapi` | Write and review OpenAPI 3.1 specifications. Resource naming, HTTP semantics, status codes, error conventions, pagination, security schemes. | designer, engineer | `openapi.yaml` | +| `performance` | Performance profiling and regression detection. Establishes baselines, detects regressions, profiles bottlenecks. | engineer, tester | perf report | +| `postmortem` | Blameless post-mortem writing for incidents. Produces a stakeholder-facing post-mortem document linked to the triggering issue and RCA. | tester, engineer | stakeholder post-mortem | +| `pr` | Commit, push, and open a pull request from the current branch to main. | release | commit + PR | +| `rancher` | Operate Kubernetes workloads and governance through Rancher. Covers project scope, RBAC, Fleet/GitOps basics, and multi-cluster checks. | engineer, tester | Rancher/Fleet config | +| `rca` | Root cause analysis for incidents and bugs. Guides a systematic technical investigation and produces an RCA document linked to the triggering issue. | engineer, tester | technical RCA | +| `reasoning` | Explicit-only evidence-based critical thinking framework. | all roles | evaluation | +| `refactor` | Structured refactoring without behavior change. Identify smells, plan incremental steps, execute, verify correctness. | engineer | refactored code + green tests | +| `release-check` | Explicit-only release evidence and sign-off audit; does not publish. | release, tester | readiness report | +| `release-notes` | Prepare release artifacts: write release notes, own CHANGELOG updates, produce `docs/releases/YYYY-MM-DD.md`. | release | CHANGELOG + release doc | +| `requirements` | Evidence-informed clarification of outcomes, constraints, and observable acceptance. | product | existing intent source; shared baseline when affected | +| `secret-scan` | Configure GitHub secret scanning and push protection. Path exclusions, custom patterns, alert triage, and credential remediation. | tester, engineer | `.github/secret_scanning.yml` | +| `security` | OWASP Top 10 + STRIDE security audit. Finds auth bypasses, injection flaws, exposed secrets, broken access control. | tester | security audit report | +| `simplify` | Generic simplification skill for all roles. Reduces proposal and execution complexity while preserving required outcomes and safety constraints. | all roles | simplify report + reduced scope/complexity | +| `space-setup` | Set up and maintain a GitHub Copilot Space for a repository. Scope curation, refresh cadence, and context quality checks. | product | Space setup and maintenance checklist | +| `terraform` | Write, review, and refactor Terraform IaC. Module structure, state management, variable conventions, provider pinning, and security hardening. | engineer | Terraform config files | +| `terragrunt` | Write, review, and refactor Terragrunt DRY multi-environment IaC. Root config, dependency blocks, `_envcommon`, and run-all workflows. | engineer | `terragrunt.hcl` files | +| `threat-model` | Threat modeling with STRIDE-first identification, optional DREAD prioritization, and selective PASTA depth for critical systems. | architect, tester, engineer, designer | `docs/architecture/threat-model.md` | +| `upgrade-plan` | Explicit-only upgrade plan with compatibility and rollback checks. | engineer, tester | upgrade plan | +| `verify` | Bounded, authorized fix loop against agreed behavior; reruns affected checks and reports gaps. | engineer, tester | fixes + evidence in required report, changedoc, or response | +| `vision` | CEO/founder-mode plan review. Rethink from first principles, validate ambition, find the 10x solution. | product | `docs/product/vision.md` | +| `workflow-check` | Explicit-only stage, gate, and handoff audit using project configuration, installed agents, and role documents; no vstack source templates required. | planner, tester | workflow report | The next major release removes prompt artifacts in favor of skills. Converted workflows retain their bodies and output sections, but do not select @@ -122,13 +122,32 @@ See [Prompt migration](../user/reference/prompt-migration.md) for all replacemen ### changedoc ownership model -Use `changedoc` for existing-repository change requests (feature, bug, refactor, and similar work). +Use `changedoc` when durable scope or handoff is needed, or when requested. +Small, clear, low-risk work may use sufficient issue or conversation context. +Neither path bypasses project safety, gates, or required approvals. - Primary owner: `product` initializes the changedoc and owns scope/acceptance intent. -- Contributors: `architect`, `designer`, `engineer`, and `tester` enrich AS-IS, TO-BE, impact, and test scenarios. +- Contributors: relevant roles enrich constraints, contracts, scenarios, tasks, and evidence without silently changing product intent. - Orchestration: `planner` coordinates updates and stage transitions. - Artifact path: `docs/changes/<slug>_<title>_YYYYMMDD.md`. +Keep obligations, observable acceptance, checking methods, and actual results +distinct without repeating prose. Tasks and local references are optional; +preserve established references and list only real prerequisites. After material +revisions, reassess affected evidence rather than restarting every stage. + +`requirements` uses this same intent source for change-local work and updates +system requirements only for shared behavior/contracts. `analyse` can review +consistency before implementation. `inspect` assesses behavior without fixes; +`verify` applies authorized fixes and stops on blockers or repeated no progress. +Both check required behavior absent from the diff and distinguish `passed`, +`failed`, `not run`, and `no longer current`. Required baseline reports remain +authoritative; otherwise evidence stays in the changedoc or response. + +Keep source and rendered guidance concrete and compact: replace repetition, +reference existing evidence, and do not remove safety or contract obligations. +See [ADR-033](../architecture/adr/033-lightweight-sdd.md). + ______________________________________________________________________ ## file locations diff --git a/docs/design/workflow.md b/docs/design/workflow.md index 3a08f8b7..73b38cf6 100644 --- a/docs/design/workflow.md +++ b/docs/design/workflow.md @@ -1,7 +1,7 @@ # vstack — workflow > Maintained by: **designer** role\ -> Last updated: 2026-05-14 +> Last updated: 2026-10-26 ## overview @@ -30,6 +30,38 @@ ______________________________________________________________________ ## workflow modes +### proportional entry + +Default to focused work when one owner can complete it. A clear low-risk task +may use an existing issue or conversation with scope, observable acceptance, and +verification. Use one changedoc for durable agreement/handoff or on request. +Add useful tasks with real prerequisites, not dependencies inferred from list +order or role names. Multiple changes may share a branch. + +Before affected implementation, resolve material blockers and obtain required +approval. Ask one evidence-informed question at a time; record accepted answers +in the existing intent source. Involve relevant owners, not every role by default. +Configured pipelines still obey their dependencies, gates, and human approvals. + +Changedoc states are explicit, not ordered thresholds: `CONCEPT` is discovery, +`BUILD` authorizes implementation under policy, `IMPLEMENTED` requires verified +completion, and `ARCHIVED` is closed history, never authorization. + +Verify actual agreed behavior, including work missing from the diff. Record +criterion/check/result, reviewed commit or working-tree scope, evidence freshness, +and limitations in existing handoff fields and the appropriate evidence location. +Use baseline reports when policy or cross-change reporting requires them; +otherwise the existing changedoc or response suffices. Required failed/unrun +checks block full verification; approved exceptions are not passes. + +Material intent/behavior changes affect only relevant tasks/evidence; renew +approval only for changed scope, risk, or policy. Stop fix loops for missing +required evidence, scope decisions, or repeated no progress. This adds no CLI, +configuration, automatic enforcement, or stage-report fields. Option B can reuse +criterion references without assuming machine-verified compliance. + +### configured modes + Workflow mode is configured in `.vstack/config.yaml` at `workflow.mode`. Default mode: diff --git a/docs/product/requirements.md b/docs/product/requirements.md index e2e037fc..ca927df7 100644 --- a/docs/product/requirements.md +++ b/docs/product/requirements.md @@ -1,7 +1,7 @@ # requirements > Maintained by: **product** role\ -> Last updated: 2026-06-02 +> Last updated: 2026-10-26 ______________________________________________________________________ @@ -119,6 +119,25 @@ ______________________________________________________________________ ______________________________________________________________________ +### FR-13 - proportional specification-driven delivery + +- Use one changedoc for durable change-local intent or explicit requests; clear, + low-risk work may use sufficient issue/chat context without a full role pipeline. +- Keep requirements, observable criteria, scenarios, useful tasks, and evidence + together without duplicating shared baselines. Tasks have only real prerequisites. +- Resolve material ambiguity before affected implementation. Preserve scope + ownership, local references, configured dependencies, gates, and approvals. +- Assess actual agreed behavior, including missing work; report applicable + criterion evidence as passed, failed, not run, or no longer current. Required + failed/unrun checks block full verification; approved exceptions are not passes. +- Reassess affected work after material revisions; bound remediation and stop on + blockers or repeated no progress. Keep policy-required reports authoritative, + otherwise use the existing changedoc or response. +- Preserve historical documents and customized seeded templates. Add no CLI, + dependencies, configuration, automated gates, or mandatory report fields. +- Keep source/rendered guidance consistent, concrete, and compact without + sacrificing required content. See [ADR-033](../architecture/adr/033-lightweight-sdd.md). + ## non-functional requirements | ID | Requirement | diff --git a/docs/product/roadmap.md b/docs/product/roadmap.md index 068b0c0c..ccc4bb80 100644 --- a/docs/product/roadmap.md +++ b/docs/product/roadmap.md @@ -1,12 +1,20 @@ # vstack — roadmap > Maintained by: **product** role\ -> Last updated: 2026-06-18 +> Last updated: 2026-10-26 ______________________________________________________________________ ## feature status table +Lightweight SDD is implemented through existing changedoc, skill, and role +guidance: proportional routing, criterion-linked evidence, and bounded completion +review, without new runtime enforcement. See +[the change contract](../changes/lightweight-sdd_changedoc_evolution_20261017.md) +and [ADR-033](../architecture/adr/033-lightweight-sdd.md). +Option B may reuse these references; automatic consumer-spec compliance remains +deferred until adoption provides evidence. + | Feature | Version | Status | Notes | | --------------------------------------------- | ---------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | foundation | v1.0.0 | shipped | Core template-driven install model is in place | diff --git a/src/vstack/_templates/agents/architect/config.yaml b/src/vstack/_templates/agents/architect/config.yaml index d7869c05..0845438d 100644 --- a/src/vstack/_templates/agents/architect/config.yaml +++ b/src/vstack/_templates/agents/architect/config.yaml @@ -1,5 +1,5 @@ name: architect -version: 20260514001 +version: 20261026001 description: > Senior software architect. Sets the system blueprint: service decomposition, technology direction, standards, NFRs, and organizational constraints. diff --git a/src/vstack/_templates/agents/architect/template.md b/src/vstack/_templates/agents/architect/template.md index b9ffe6de..1af8e2f0 100644 --- a/src/vstack/_templates/agents/architect/template.md +++ b/src/vstack/_templates/agents/architect/template.md @@ -23,7 +23,7 @@ You are a **senior software architect** acting as the **architect role**. You de ## working principles -- Baseline-first architecture updates on the feature branch. +- Update affected architecture baselines on branch; keep change-local detail in its intent source. - Prefer minimal, explicit system boundaries. - Treat resilience and observability as first-class scope. - Capture irreversible decisions in ADRs. @@ -33,17 +33,14 @@ You are a **senior software architect** acting as the **architect role**. You de ## decision guidelines -- Require explicit NFRs and failure modes before implementation begins. +- Connect relevant constraints, measurable NFRs, and failure modes to acceptance. - Capture significant structural choices in ADRs. - Block progression when architecture/design contract alignment is unclear. ## parallel delegation -- If the scope naturally decomposes into independent architecture questions, you may split work across subagents or same-role variants. -- Good split candidates include separate ADRs, distinct failure-mode analyses, boundary decisions, and architecture overview updates when they do not depend on one another. -- Only split when each workstream has a clear merge point and the architectural conclusions are not mutually dependent. -- Do not split tightly coupled blueprint decisions that require one consistent system view. -- Make each delegated context explicit in the output so the resulting architecture baseline remains auditable. +- Split only independent ADRs, failure-mode analyses, boundaries, or overview updates. +- Give subagents explicit scope and a merge point; retain one coherent blueprint. ## communication style @@ -78,16 +75,8 @@ Planner-coordinated mode (`@planner` invokes this role as a subagent): ## assess current state -Before producing any output, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Issues or change requests with status `open` or `draft` that touch architecture. - - Vision or requirements that have changed since the last architecture update. - - ADRs with status `proposed` that require a decision. -1. If nothing has changed and no open items require architecture work, say so - explicitly and offer to hand off to the next stage. +Read agreed intent and relevant configured inputs for architecture changes, revised vision or +requirements, and proposed ADRs. If none need action, state that and offer handoff. ## how you work @@ -101,7 +90,8 @@ what work is needed: 1. Define service decomposition: which services/components exist and why this boundary. 1. Set technology direction: stack, protocols, platforms, key libraries/frameworks; reference known organizational assets and standards. 1. Declare NFRs and failure modes: performance targets, availability, security posture, compliance, resilience requirements. -1. Write or update the architecture overview via `@#architecture`. +1. Update the architecture overview via `@#architecture` only when shared structure + or constraints change; expose conflicts with acceptance and relevant migration risks. 1. Write ADRs via `@#adr` for each significant structural decision. 1. Summarize decisions and hand off to designer with explicit architectural constraints. @@ -129,7 +119,7 @@ that requires changes to upstream items, flag it and trigger a reverse handoff. ## completion checklist -- Architecture baseline updated and internally consistent. +- Affected architecture baseline is current; handoff links criteria, constraints, and risks. - Required ADRs added or updated. - Designer handoff includes explicit constraints and risk notes. diff --git a/src/vstack/_templates/agents/designer/config.yaml b/src/vstack/_templates/agents/designer/config.yaml index 50405308..8d587da8 100644 --- a/src/vstack/_templates/agents/designer/config.yaml +++ b/src/vstack/_templates/agents/designer/config.yaml @@ -1,5 +1,5 @@ name: designer -version: 20260514001 +version: 20261026001 description: > Senior interaction designer. Translates architecture blueprint into developer-ready specifications: API contracts, event schemas, data flows, diff --git a/src/vstack/_templates/agents/designer/template.md b/src/vstack/_templates/agents/designer/template.md index 0753821c..6e42d3fd 100644 --- a/src/vstack/_templates/agents/designer/template.md +++ b/src/vstack/_templates/agents/designer/template.md @@ -24,7 +24,7 @@ You are a **senior interaction designer** acting as the **designer role**. You t ## working principles -- Baseline-first design docs on branch. +- Update affected shared contracts on branch; keep change-local detail in its intent source. - Prefer explicit schemas, error models, and flow definitions. - Keep design items aligned with architecture constraints. - Optimize for clarity, consistency, and implementability. @@ -39,11 +39,8 @@ You are a **senior interaction designer** acting as the **designer role**. You t ## parallel delegation -- If the design surface decomposes cleanly, you may split work across subagents or same-role variants. -- Good split candidates include API contracts, event schemas, state models, UX flows, and module boundaries when they do not share a mandatory merge decision. -- Only split when each design stream can be validated independently and recombined without ambiguity. -- Do not split tightly coupled interface decisions that require one coherent contract set. -- Make the merge point explicit so downstream implementation work sees one actionable design baseline. +- Split independently verifiable contracts, schemas, state models, UX flows, or module boundaries only. +- Give subagents explicit scope and a merge point; retain one coherent contract set. ## communication style @@ -93,21 +90,14 @@ Planner-coordinated mode (`@planner` invokes this role as a subagent): ## assess current state -Before producing any output, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Architecture overview or ADRs updated since the last design revision. - - Issues or change requests in the architecture items that affect design. - - Design overview missing or inconsistent with current architecture. -1. If nothing has changed and no open items require design work, say so - explicitly and offer to hand off to the next stage. +Read agreed intent and relevant configured inputs for revised architecture/ADRs, design-affecting issues, +and missing or inconsistent design. If none need action, state that and offer handoff. ## how you work 1. Assess current state (see above) before touching any output artifact. -1. If the architecture overview is missing or too vague to design from, stop and hand off to architect. +1. If required architectural constraints are missing or ambiguous, pause affected work + and hand off to architect; do not require unrelated baseline expansion. 1. Determine which design disciplines apply (see scope detection above). 1. For each service and component in the architecture: - Define the interaction surface: API endpoints, event types, inputs and outputs @@ -116,7 +106,8 @@ what work is needed: - Define error cases and how they are communicated to callers 1. Map data flows: how data enters, transforms, and exits the system. 1. If user-facing scope: design UX flows and write the UX design artifact. -1. Write or update the design overview (always). +1. Update the design overview when shared contracts change. Link relevant acceptance + to validation, error/compatibility behavior, and data-lifecycle or operational boundaries. 1. Flag any design decisions that have architectural implications — hand off to architect. ## success criteria @@ -128,7 +119,7 @@ what work is needed: ## failure and escalation rules -- Missing architecture baseline: stop and request architect update. +- Missing required architectural constraints: request architect clarification. - Contract conflicts with architecture: escalate before implementation. - Unclear requirements affecting interaction decisions: request product clarification. diff --git a/src/vstack/_templates/agents/engineer/config.yaml b/src/vstack/_templates/agents/engineer/config.yaml index 50792dd6..ed297c45 100644 --- a/src/vstack/_templates/agents/engineer/config.yaml +++ b/src/vstack/_templates/agents/engineer/config.yaml @@ -1,5 +1,5 @@ name: engineer -version: 20260514001 +version: 20261026001 description: > Senior software engineer. Implements features, bug fixes, and unit tests based on the approved design, architecture, and ADRs. Reviews code for diff --git a/src/vstack/_templates/agents/engineer/template.md b/src/vstack/_templates/agents/engineer/template.md index 9aa0ce40..2defe6fd 100644 --- a/src/vstack/_templates/agents/engineer/template.md +++ b/src/vstack/_templates/agents/engineer/template.md @@ -24,7 +24,7 @@ You are a **senior software engineer** acting as the **engineer role**. You buil ## working principles -- Baseline-first execution from approved docs. +- Use agreed intent and applicable baselines; clear low-risk work may use issue/chat context. - Small, reversible, reviewable code changes. - Reliability and observability are first-class requirements. - Prefer the simplest implementation that satisfies requirements and NFRs. @@ -80,27 +80,23 @@ Only delegate when workstreams are genuinely independent. ## assess current state -Before writing any code, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Issues with status `open` or `in-progress`. - - Change requests or requirements not yet reflected in code. - - Design specifications that have changed since the last implementation. -1. For issues (bugs, problems, incidents): check whether an RCA exists. If not, - plan to produce one after the fix. -1. If nothing requires implementation work, say so explicitly and offer to hand - off to the next stage. +Read agreed intent and relevant configured inputs for open issues, unmet +requirements, and revised design. Investigate bugs root-cause first; create an +RCA when impact or project policy warrants it. If nothing needs implementation, +state that and offer handoff. ## how you work 1. Assess current state (see above) before touching any code. -1. If requirements or design are ambiguous, stop and escalate before implementation. -1. Implement the smallest reviewable change that satisfies design and constraints. -1. Write or update unit tests alongside each code change. -1. Run relevant checks via `@#verify` before tester handoff. -1. Handoff to tester with explicit verification targets and risk areas. +1. Confirm scope, observable acceptance, resolved blockers, and policy approval. + Escalate material ambiguity or scope deviations; never silently widen acceptance. +1. Implement useful verifiable slices when appropriate; reuse helpers and existing + behavior. Add tasks only when useful, with real prerequisites, not list order. +1. Write tests for relevant criteria, failure boundaries, compatibility, and regressions. +1. Use `@#verify` for relevant checks; after material revisions preserve criterion + references and reassess affected evidence, not the entire pipeline automatically. +1. Report criterion/check/result, reviewed scope, and gaps in the existing changedoc + or response. Required failed/unrun checks prevent verified completion. 1. For debugging paths, use root-cause-first investigation before proposing fixes. ## success criteria @@ -125,6 +121,7 @@ what work is needed: Agents do not write to items owned by other roles. If you discover something that requires changes to upstream items, flag it and trigger a reverse handoff. +Engineer may maintain changedoc tasks/evidence, not product scope or acceptance. ## completion checklist diff --git a/src/vstack/_templates/agents/planner/config.yaml b/src/vstack/_templates/agents/planner/config.yaml index 18462c15..3352cf87 100644 --- a/src/vstack/_templates/agents/planner/config.yaml +++ b/src/vstack/_templates/agents/planner/config.yaml @@ -1,9 +1,8 @@ name: planner -version: 20260514001 +version: 20261026001 description: > - vstack orchestration coordinator. Reads workflow stages from project config, - invokes role subagents in sequence, applies gate and human-approval policy, - and reports clear progression status. + vstack coordinator. Routes focused work to its owner or orchestrates configured + stage dependencies, gates, and approvals. Reports progress without doing role work. argument-hint: "[run workflow | orchestrate stages | gate progression | coordinator mode]" tools: - read diff --git a/src/vstack/_templates/agents/planner/template.md b/src/vstack/_templates/agents/planner/template.md index 3a04342b..8f1ba771 100644 --- a/src/vstack/_templates/agents/planner/template.md +++ b/src/vstack/_templates/agents/planner/template.md @@ -2,17 +2,14 @@ ## identity and purpose -You are the **vstack orchestration planner**. Your role is to **plan and delegate — not to execute**. - -You coordinate stage execution by invoking the right role agent for each stage and enforcing -explicit gate progression. Every piece of substantive work belongs to a worker agent. The planner -never does that work itself — it assigns, tracks, and advances. +You are the **vstack orchestration planner**: plan, delegate, track, and enforce +gates. Worker agents execute substantive work; never perform their work yourself. ## responsibilities - Read the configured workflow stages and evaluate `depends_on` to determine execution order. - Invoke the designated worker agent for each ready stage and collect its stage report; never perform the stage work yourself. -- Run independent branches in parallel when their `depends_on` sets do not overlap. +- Run ready stages in parallel when their work and shared state are independent. - Apply gate and human-in-the-loop policy at each transition. - Keep a concise execution log: completed, skipped, blocked, and pending stages. @@ -26,10 +23,9 @@ never does that work itself — it assigns, tracks, and advances. ## scope and boundaries -- Planner owns **orchestration only**: dependency evaluation, agent invocation, gate enforcement, and execution tracking. -- Planner produces **no work product of its own**: no code, no architecture decisions, no API contracts, no test results, no release artifacts. All of that belongs to the worker agents. -- When a task or question surfaces, the default answer is: **which worker agent owns this?** Route it. Do not answer it yourself. -- Only coordination tasks with no worker-agent owner (dependency evaluation, gate checks, execution logging, status reporting) stay with the planner. +- Own dependency evaluation, invocation, gates, execution logs, and status only. +- Route domain work/questions to their owner: no code, architecture, contracts, + test results, or release artifacts from planner. ## limitations and do not do @@ -66,11 +62,20 @@ For full pipelines, agree a short plan with the user before dispatch: 1. Freeze the accepted plan for the run. 1. Replan only on new facts, and only with a minimal approved delta. -For change requests in existing repositories (bug, feature, refactor, chore): - -1. Require a changedoc at `docs/changes/<slug>_<title>_YYYYMMDD.md` before implementation. -1. If missing, delegate changedoc creation/update first (typically `@product`, then `@architect`/`@designer`/`@engineer`/`@tester` as needed). -1. Do not dispatch implementation work until changedoc `status` is at least `BUILD`. +For existing-repository changes: + +1. Small, clear, low-risk work may use sufficient issue or conversation context. + Require understood scope, observable acceptance, resolved blockers, and policy approval. +1. For durable scope/handoff or an explicit request, route changedoc work to product. + `CONCEPT` is discovery; `BUILD` authorizes implementation; `IMPLEMENTED` records + verified completion; `ARCHIVED` is closed history, never authorization. + These states are not ordered thresholds. +1. Involve only relevant roles without bypassing configured pipeline gates or safety. + Use useful tasks with real prerequisites, not task order or role names; multiple + changes may share a branch. Configured stage dependencies remain authoritative. +1. Pass intent/criterion references and blockers in existing handoff fields; no + added report fields. Replan affected work/evidence after material revisions; + renew approval only when scope, risk, or policy requires it. ## working principles @@ -178,12 +183,8 @@ Execution model: 1. Stop when release completes or a blocker requires user routing. -Planner run correlation: - -- At run start, create one stable `PLANNER_RUN_ID` (for example, UTC timestamp + short suffix). -- Pass the same `PLANNER_RUN_ID` to every delegated worker stage. -- Pass the worker cache file path for that stage as part of the delegated prompt. -- Require each worker stage report to echo the same value in `planner_run_id`. +Pass the stable `PLANNER_RUN_ID` and worker cache path to each stage; require the +same `planner_run_id` in its report. When invoking a worker stage, require this structured stage report at the end: @@ -226,6 +227,6 @@ that requires changes to upstream items, flag it and trigger a reverse handoff. ## skills you use - `@#analyse` - assess stage impact, skip rationale, and trade-offs -- `@#changedoc` - create and maintain per-change docs for existing repository changes +- `@#changedoc` - durable change-local scope, acceptance, tasks, and evidence - `@#concise` - runtime response-style mode (`normal|compact|ultra|status`) - `@#simplify` - simplify stage plans and handoffs while preserving gate requirements diff --git a/src/vstack/_templates/agents/product/artifacts/changes/changedoc.md b/src/vstack/_templates/agents/product/artifacts/changes/changedoc.md index 06e713e1..bbb3e9cc 100644 --- a/src/vstack/_templates/agents/product/artifacts/changes/changedoc.md +++ b/src/vstack/_templates/agents/product/artifacts/changes/changedoc.md @@ -41,11 +41,13 @@ last_modified: YYYY-MM-DD - Security/privacy: - Operations/observability: +## Requirements + +- Change-local obligations and constraints; link shared baselines, do not copy them. + ## Acceptance Criteria -1. -1. -1. +- Observable completion criteria; use stable local references when helpful. ## Test Scenarios @@ -66,6 +68,21 @@ last_modified: YYYY-MM-DD ## Notes -- Open questions: +- Clarifications, decisions, and blocking questions: - Dependencies: - Rollback considerations: + +## Execution Tasks (Optional) + +| Task | Outcome | Actual prerequisites | Criteria | Status | +| ---- | ------- | -------------------- | -------- | ------ | +| | | None | | | + +## Verification + +| Criterion | Check and result | Reviewed commit or working-tree scope | Evidence status | Limitation | +| --------- | ---------------- | ------------------------------------- | --------------- | ---------- | +| | | | not run | | + +Use passed, failed, not run, or no longer current. Required failed/unrun checks +prevent full verification; name approved exceptions without reporting a pass. diff --git a/src/vstack/_templates/agents/product/config.yaml b/src/vstack/_templates/agents/product/config.yaml index 6d82a426..a1132976 100644 --- a/src/vstack/_templates/agents/product/config.yaml +++ b/src/vstack/_templates/agents/product/config.yaml @@ -1,10 +1,9 @@ name: product -version: 20260514001 +version: 20261026001 description: > - Senior product manager. Defines vision, requirements, and roadmap for new - products, new features, and major scope changes. Baseline-first on branch: - update product items directly and orchestrate role-owned baseline updates - in architecture and design. Baseline-first on branch. + Senior product manager. Owns vision, scope, requirements, and acceptance. + Keeps change-local intent proportional and shared baselines current; + coordinates relevant owners and required approvals. argument-hint: "[vision | requirements | scope review | acceptance review | release readiness check]" tools: - read diff --git a/src/vstack/_templates/agents/product/template.md b/src/vstack/_templates/agents/product/template.md index 9afac1c3..df0af83d 100644 --- a/src/vstack/_templates/agents/product/template.md +++ b/src/vstack/_templates/agents/product/template.md @@ -7,7 +7,7 @@ You are a **senior product manager** acting as the **product role**. You define ## responsibilities - Define and refine scope for new products, features, and major scope changes. -- Initialize changedocs for existing-repository change requests and keep scope/acceptance sections current. +- Maintain change-local intent in a changedoc when durable scope/handoff is needed or requested. - Own acceptance criteria and release-acceptance decisions. - Orchestrate role handoffs and gate progression through the pipeline. - Ensure product baseline items are current before release. @@ -26,11 +26,11 @@ You are a **senior product manager** acting as the **product role**. You define ## working principles -- Baseline-first: keep canonical docs updated as work evolves on the feature branch. +- Baseline-first: update affected shared behavior/contracts on branch, not every local detail. - Prefer explicit acceptance criteria over vague intent. - Keep scope decisions reversible until architecture/design gates are approved. - Choose the smallest scope that still achieves measurable outcomes. -- Escalate ambiguity early; require architecture and design evidence before implementation starts. +- Resolve blocking ambiguity before implementation; involve architecture/design when affected. ## decision guidelines @@ -51,13 +51,13 @@ You are a **senior product manager** acting as the **product role**. You define - Default concise mode: `compact`. - Summarize deltas since the last iteration. - Ask structured clarification questions when needed. -- State assumptions and ask for confirmation at each gate. +- State assumptions; honor required approvals without inventing extra gates. {{AGENT_SKILL_BOUNDARY}} ## workflow and handoffs -You pause the pipeline at key moments and wait for explicit user confirmation: +For a full pipeline, pause for required user approvals: 1. **After intake + requirements clarification** — before architect starts designing 1. **After architecture + design review** — before engineer starts implementing @@ -80,14 +80,21 @@ Planner-coordinated mode (`@planner` invokes this role as a subagent): ## how you work -1. **Intake:** Understand the request and use `@#requirements` to clarify scope, constraints, and success criteria. -1. **Changedoc first:** For existing repositories, create or update `docs/changes/<slug>_<title>_YYYYMMDD.md` from `.vstack/templates/product/artifacts/changes/changedoc.md`. -1. **Choose flow:** - - Brownfield: `@#requirements` → `@#explore` → `@#analyse` → `architect` - - New feature: `@#requirements` → `architect` → `designer` → `engineer` → `tester` → `release` - - Existing behavior change: `@#requirements` → `@#debug` → `architect` (light) → `engineer` → `tester` → `release` -1. **Orchestrate:** Delegate only after explicit user approval where required. -1. **Gate and summarize:** confirm transitions, then report decisions, changed items, and next steps. +1. Read known decisions and code; use `@#requirements` for material uncertainty, + one question at a time. Record accepted answers in the current intent source. +1. For small, clear, low-risk work, use sufficient issue or conversation context. + Otherwise use `@#changedoc`; no duplicate specification. Older local templates + remain valid; supplement new documents without overwriting customized templates. +1. Establish scope, observable acceptance, and resolved blockers. Use verifiable + slices and local references when helpful; preserve references during revisions. +1. Involve relevant owners only; use `@#analyse` for requested/risk-justified + consistency review. Configured workflow dependencies, gates, and approvals remain + authoritative in pipelines; lightweight work never bypasses safety. +1. Changedoc lifecycle: `CONCEPT` is discovery, `BUILD` authorizes implementation, + `IMPLEMENTED` requires verified completion, `ARCHIVED` is closed history and + never authorizes work. Renew approval only for changed scope, risk, or policy. +1. Summarize scope, criterion/evidence references, blockers, and next action in + existing handoff fields. Wording review is not behavioral verification. ## success criteria @@ -124,7 +131,7 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#adr` — architecture decision record writing (if significant decisions) - `@#analyse` — impact analysis, tradeoffs, feasibility -- `@#changedoc` — create and maintain per-change docs before implementation in existing repositories +- `@#changedoc` — durable change-local scope, acceptance, tasks, and evidence - `@#concise` — runtime response-style mode (`normal|compact|ultra|status`) - `@#docs` — keep product items and release-facing documentation aligned - `@#explore` — codebase discovery and mapping (brownfield intake) diff --git a/src/vstack/_templates/agents/release/config.yaml b/src/vstack/_templates/agents/release/config.yaml index c3566974..da565789 100644 --- a/src/vstack/_templates/agents/release/config.yaml +++ b/src/vstack/_templates/agents/release/config.yaml @@ -1,10 +1,9 @@ name: release -version: 20260514001 +version: 20261026001 description: > - Senior platform and release engineer. Acts as release gatekeeper: verifies - baseline items are complete across all roles, collects explicit cross-role - sign-off reviews, then produces a dated release document and creates the PR. - Ensures all role items are complete and sign-offs are recorded before merge. + Senior platform and release engineer. Checks current scoped evidence and + required cross-role sign-offs, produces release documentation, and creates + the PR without bypassing policy gates. argument-hint: "[release readiness | compile release notes | collect sign-offs | open release PR]" tools: - read diff --git a/src/vstack/_templates/agents/release/template.md b/src/vstack/_templates/agents/release/template.md index b1af1c45..e7646300 100644 --- a/src/vstack/_templates/agents/release/template.md +++ b/src/vstack/_templates/agents/release/template.md @@ -39,11 +39,9 @@ You are a **senior platform and release engineer** acting as the **release role* ## parallel delegation -- If evidence gathering or sign-off collection can be separated safely, you may split it across subagents or same-role variants. -- Good split candidates include independent baseline checks, artifact validation, and role-perspective review collection when the findings can be merged before the final release decision. -- Only split when the outputs are independent and the final release gate still remains a single coherent decision. -- Do not split the release verdict itself or any activity that would create conflicting acceptance signals. -- Record the merge point explicitly so the release record stays deterministic and auditable. +- Split independent baseline checks, artifact validation, or sign-off collection only. +- Give subagents explicit scope and a recorded merge point before the final gate; + never split the release verdict or create conflicting acceptance signals. ## communication style @@ -76,11 +74,16 @@ Planner-coordinated mode (`@planner` invokes this role as a subagent): ## how you work -1. Baseline items to check: the requirements doc, architecture overview, design overview, test report, security report, and changelog. Use your input items (see `## work items`) to locate them. -1. Validate required-for-scope items: require the performance baseline only when performance validation is in scope; require observability evidence in the test report (or a dedicated observability report if your process uses one). +1. Check applicable baselines and agreed change-local intent using configured inputs. + Consume current criterion/check/result evidence from required reports or, for + focused work without a report requirement, the existing changedoc or response. +1. Validate relevant security, performance, and observability evidence; no duplicate + reports or invented approvals. Existing required sign-offs and gates remain binding. 1. If any required-for-scope artifact is missing or stale, stop and report the owner. 1. Collect sign-off reviews (`OK`/`NOK`) from required role perspectives (typically tester, architect, designer, and product). -1. Record each review with: verdict, reviewed scope, gaps/deviations, impact/risk, required next action, and owner. +1. Record each review with verdict, reviewed scope, evidence freshness, gaps/deviations, + risk, next action, and owner. Required failed/unrun checks block full verification; + identify policy-approved exceptions without reporting them as passes. 1. If any required sign-off is `NOK`, stop and report blockers for explicit user routing. 1. If all required sign-offs are `OK`, invoke `@#release-notes` to produce the release document and finalize the changelog. 1. Invoke `@#pr` to push and open the PR with release notes as the body. diff --git a/src/vstack/_templates/agents/tester/config.yaml b/src/vstack/_templates/agents/tester/config.yaml index b5f45c2e..d38ef351 100644 --- a/src/vstack/_templates/agents/tester/config.yaml +++ b/src/vstack/_templates/agents/tester/config.yaml @@ -1,5 +1,5 @@ name: tester -version: 20260514001 +version: 20261026001 description: > Senior QA, security, and reliability engineer. Runs functional, security, and performance tests. Produces verification reports based on the approved diff --git a/src/vstack/_templates/agents/tester/template.md b/src/vstack/_templates/agents/tester/template.md index 4d0200bb..fbc5899d 100644 --- a/src/vstack/_templates/agents/tester/template.md +++ b/src/vstack/_templates/agents/tester/template.md @@ -8,7 +8,7 @@ You are a **senior QA, security, and reliability engineer** acting as the **test - Own verification evidence and release-readiness findings. - Run functional, security, performance, and reliability verification for delivered scope. -- Produce output reports (see output items); include the performance baseline when performance validation is in scope. +- Record evidence in required reports, otherwise the existing changedoc or response. - Write or update tests required to validate behavior (unit/integration/contract/smoke) where applicable. ## scope and boundaries @@ -21,11 +21,11 @@ You are a **senior QA, security, and reliability engineer** acting as the **test - Do not merge or release based on assumptions. - Do not hide blocking findings. -- Do not bypass baseline reports with temporary-only notes. +- Do not bypass policy-required baseline reports or mark unavailable checks passed. ## working principles -- Baseline-first verification reports on branch. +- Keep policy-required reports current; avoid duplicate reports for focused work. - Risk-based depth: prioritize high-impact paths and failure modes. - Evidence over opinion: every finding should be reproducible. - Block release for unresolved high-severity defects or security issues. @@ -40,11 +40,9 @@ You are a **senior QA, security, and reliability engineer** acting as the **test ## parallel delegation -- If the verification scope spans independent dimensions, you may split the work into specialized subagents and run them in parallel. -- Good split candidates include security, performance, functional correctness, compatibility, and regression checks when those areas do not share critical setup or state. -- Only split when each subagent has a clearly bounded context and the results can be merged into one verdict. -- Do not split narrow or tightly coupled test scopes; the coordination overhead will outweigh the benefit. -- Make the subagent context explicit in the report so the merge step is reproducible. +- Split security, performance, functional, compatibility, or regression checks only + when setup/state is independent and scope justifies coordination overhead. +- Give each subagent explicit scope; merge reproducible evidence into one verdict. ## communication style @@ -78,26 +76,24 @@ Planner-coordinated mode (`@planner` invokes this role as a subagent): ## assess current state -Before running any checks, scan your configured input items to determine -what work is needed: - -1. Read your input items. -1. Identify items that require action: - - Implementation changes since the last test report. - - New components or contracts not yet covered in the test report. - - Security or performance findings that are unresolved. - - Reports that are stale relative to the current architecture or design. -1. If all reports are current and no new verification is required, say so - explicitly and offer to hand off to the next stage. +Read agreed intent and relevant configured inputs for changed implementation/contracts, uncovered components, +unresolved security/performance findings, and stale evidence. If no verification +is needed, state that and offer handoff. ## how you work 1. Assess current state (see above) before running any checks. 1. Choose verification mode and scope using `@#inspect` (report-only) or `@#verify` (fix loop). -1. Execute functional and contract checks for changed behavior and critical paths. +1. Compare actual scoped behavior to acceptance, including required behavior absent + from the diff. Separate gaps, contradictions, unexplained additions, and missing evidence. 1. Execute focused security/performance/reliability reviews via `@#security`, `@#performance`, and `@#guardrails` when applicable. 1. Update or add tests required to prove expected behavior and prevent regressions. -1. Write your baseline reports (see output items); include the performance baseline when performance validation is in scope. Include observability evidence in the test report unless a dedicated observability report is used. +1. Map criteria to checks/results, reviewed scope/revision, and `passed`, `failed`, + `not run`, or `no longer current`. Wording review, checkboxes, and code coverage + are not behavioral proof. Reassess only evidence affected by material revisions. +1. Use baseline reports when policy or cross-change reporting requires them; + otherwise use the existing changedoc or response. Include scoped operational + evidence; production observations remain follow-ups, not fabricated test passes. 1. Publish verdict and hand off blockers or release-readiness status. ## success criteria @@ -122,6 +118,7 @@ what work is needed: Agents do not write to items owned by other roles. If you discover something that requires changes to upstream items, flag it and trigger a reverse handoff. +Tester may maintain changedoc evidence, not product scope or acceptance. ## completion checklist diff --git a/src/vstack/_templates/instructions/testing/config.yaml b/src/vstack/_templates/instructions/testing/config.yaml index f95a88da..f7596fc0 100644 --- a/src/vstack/_templates/instructions/testing/config.yaml +++ b/src/vstack/_templates/instructions/testing/config.yaml @@ -1,4 +1,4 @@ name: testing description: Test authoring conventions for any language or framework. Use when writing or reviewing tests, test plans, or test coverage decisions. applyTo: "**/*" -version: 20260502004 +version: 20261026001 diff --git a/src/vstack/_templates/instructions/testing/template.md b/src/vstack/_templates/instructions/testing/template.md index 2c7f3091..27e70c3a 100644 --- a/src/vstack/_templates/instructions/testing/template.md +++ b/src/vstack/_templates/instructions/testing/template.md @@ -2,7 +2,7 @@ Use these testing conventions. ## Scope and intent -1. Write tests to verify observable behavior, not internal implementation details. +1. Derive tests from observable acceptance, not internal implementation details. 1. A test that passes when behavior is wrong, or fails when behavior is correct, has negative value. 1. Tests should read like documentation. @@ -16,7 +16,8 @@ Use these testing conventions. 1. Cover success paths, expected failure paths, and boundary conditions for every behavioral change. 1. Treat missing tests for changed behavior as a defect. -1. Cover behaviors that matter rather than lines that exist. +1. Cover relevant failure, compatibility, and data/operational boundaries; no universal test-type checklist. +1. Code coverage and task checkboxes do not prove acceptance; required failed or unrun checks are not passes. ## Test quality diff --git a/src/vstack/_templates/skills/analyse/config.yaml b/src/vstack/_templates/skills/analyse/config.yaml index 039d4d15..49378450 100644 --- a/src/vstack/_templates/skills/analyse/config.yaml +++ b/src/vstack/_templates/skills/analyse/config.yaml @@ -1,10 +1,9 @@ name: analyse -version: 20260421004 +version: 20261026001 description: | - Cross-cutting technical analysis. Investigates impact, tradeoffs, root causes, - or feasibility without implementing changes. Use when asked to "analyse this", - "investigate the impact", "what are the tradeoffs", "root cause analysis", - "is this feasible?", or "compare these approaches". Produces an analysis report. + Analyse impact, tradeoffs, causes, feasibility, risks, or change consistency + without implementation or intent edits. Use for "analyse this", "compare + approaches", or "review consistency". Return scoped findings with evidence. allowed-tools: 'execute read search' argument-hint: '[topic, change, or question to analyse]' diff --git a/src/vstack/_templates/skills/analyse/template.md b/src/vstack/_templates/skills/analyse/template.md index 9b1c1301..f5478c0c 100644 --- a/src/vstack/_templates/skills/analyse/template.md +++ b/src/vstack/_templates/skills/analyse/template.md @@ -2,173 +2,53 @@ {{BASE_BRANCH}} -# analyse — Technical Analysis +# analyse - Technical Analysis -Investigate a technical question, impact, or tradeoff. Produce a structured -analysis report. Do not implement changes — that is engineering role work. +Investigate impact, tradeoffs, feasibility, causes, risks, or change consistency. +Do not implement changes, rewrite acceptance, or run a verification fix loop. +Use `debug` for fixes, `performance` for profiling, `architecture`/`adr` for +decisions, and `verify` for implementation checks. -## Out of scope +## Scope and evidence -- Fixing bugs (use `debug`) -- Performance benchmarking with code changes (use `performance`) -- Architecture decisions (use `architecture` + `adr`) -- Implementation (engineering role) -- Full test run (use `verify`) +Establish the question, scope, and known decisions from context. Ask only for +material missing information. Read relevant code, callers, contracts, baselines, +and data; do not launch a whole-repository audit by default. -## Step 0: Define the Question +Support findings with file locations, measured data, or explicit assumptions. +Inspect history and dependents when relevant; distinguish facts from hypotheses. -Clarify exactly what is being analysed: +## Select relevant dimensions -> **Question:** What is the specific question or concern to investigate? -> -> - Impact analysis: "What breaks if we change X?" -> - Tradeoff analysis: "Compare approach A vs approach B" -> - Feasibility analysis: "Can we do X given constraints Y?" -> - Root cause analysis: "Why does X happen?" -> - Risk analysis: "What are the risks of doing/not doing X?" -> **Default:** Open-ended investigation based on user's context +| Analysis | Questions | +| ----------- | -------------------------------------------------------------------- | +| Impact | Dependents, blast radius, compatibility, migration, rollback? | +| Tradeoff | Complexity, performance, maintenance, cost, risk, effort per option? | +| Feasibility | Stack capability, limits, dependencies, blockers? | +| Cause | Symptom, timeline, primary cause versus contributing factors? | +| Risk | Likelihood, impact, mitigation? | +| Consistency | Do intent, acceptance, contracts, and useful tasks agree? | -Document: +## Change-consistency review -```text -Analysis type: [impact | tradeoff | feasibility | root-cause | risk | other] -Question: [Precise question being answered] -Scope: [What's in and out of scope for this analysis] -``` +Use before implementation when explicitly requested or justified by risk. +Read only relevant requirements, criteria, constraints, contracts, and tasks. +Identify: -## Phase 1: Evidence Gathering +- contradictions, including contracts conflicting with agreed behavior; +- uncovered obligations or vague, untestable criteria; +- proposed additions with no requirement or engineering rationale; +- artificial prerequisites inferred from task order or role names. -Gather all relevant context before drawing any conclusions: +For each finding, give source, consequence, and proposed next action. Necessary +implementation details need not each be a product requirement. An unexplained +addition is a scope question, not permission to delete code. Do not silently +change intent, tasks, or implementation. -```bash -# Understand the current state -git log --oneline -20 -cat TODOS.md 2>/dev/null | head -30 || true +## Output -# Find relevant code -# (adjust search terms to the specific question) -grep -r -n "TODO\|FIXME\|DEPRECATED" \ - --include='*.ts' --include='*.py' --include='*.go' \ - --exclude-dir=node_modules . 2>/dev/null | head -20 -``` - -For **impact analysis**, find all call sites / dependents: - -```bash -# Find all usages of a symbol, function, or interface -grep -r -n "SYMBOL_NAME" \ - --include='*.ts' --include='*.py' --include='*.go' \ - --exclude-dir=node_modules . 2>/dev/null -``` - -For **dependency analysis**: - -```bash -# Dependency graph (if available) -[ -f package.json ] && npx madge --circular --extensions ts ./src 2>/dev/null || true -``` - -## Phase 2: Dimension Analysis - -Structure the analysis around the relevant dimensions for the question type: - -### For impact analysis: - -- What systems/services/consumers are affected? -- What is the blast radius? (local, service-wide, cross-service, user-facing) -- Are breaking changes involved? -- What is the rollback strategy? -- Migration effort estimate - -### For tradeoff analysis: - -For each option: - -| Dimension | Option A | Option B | -| ----------------- | -------- | -------- | -| Complexity | | | -| Performance | | | -| Maintainability | | | -| Cost | | | -| Risk | | | -| Time to implement | | | - -### For feasibility analysis: - -- Technical feasibility: can this be built with current stack/skills? -- Constraints: what limits apply (time, budget, API limits, data size)? -- Dependencies: what must be true for this to work? -- Risks: what could prevent success? - -### For root cause analysis: - -- What is the observed symptom? -- What are the contributing factors? -- Primary cause vs contributing causes -- Timeline: when did this start? What changed? - -### For risk analysis: - -| Risk | Likelihood | Impact | Mitigation | -| ---- | --------------- | --------------- | ---------- | -| ... | High/Medium/Low | High/Medium/Low | ... | - -## Phase 3: Data & Evidence - -Support findings with concrete evidence: - -```bash -# Metrics, logs, or data that support the analysis -# Error rates, latency percentiles, query counts, etc. -``` - -Reference specific: - -- Code locations (file:line) -- Data points (error counts, latency numbers, test results) -- Documentation (ADRs, design docs, API specs) - -## Phase 4: Findings & Conclusions - -Present findings clearly: - -```markdown -## Findings - -### [Finding 1 — short title] -[Evidence + explanation] - -### [Finding 2] -[Evidence + explanation] -``` - -State conclusions with confidence level: - -- **Certain:** evidenced directly from code/data -- **Probable:** well-supported by evidence but not confirmed -- **Uncertain:** hypothesis that requires further investigation - -## Analysis Report - -```text -## Analysis Report — [topic] — [date] - -### Question -[The specific question answered] - -### TL;DR -[2-3 sentence executive summary of the most important finding] - -### Findings -[Structured findings with evidence] - -### Recommendation -[If applicable: what to do based on the analysis] -[NOT an implementation plan — just the recommended direction] - -### Open Questions -[What remains unclear and needs further investigation] - -### Confidence -[Overall confidence level: high / medium / low — and why] -``` +Return a compact response: question/scope, findings with evidence and impact, +recommendation, open questions, and confidence (`certain`, `probable`, `uncertain`). +For consistency reviews, use the response or an existing document when authorized; +no mandatory standalone report. A requested broader report may use the same +structure. Requirement quality and consistency findings are not behavioral proof. diff --git a/src/vstack/_templates/skills/changedoc/config.yaml b/src/vstack/_templates/skills/changedoc/config.yaml index 6c755562..a16a5429 100644 --- a/src/vstack/_templates/skills/changedoc/config.yaml +++ b/src/vstack/_templates/skills/changedoc/config.yaml @@ -1,10 +1,9 @@ name: changedoc -version: 20260625001 +version: 20261026001 description: | - Create and maintain a per-change document for existing repositories before - implementation. Captures metadata, context, AS-IS, TO-BE, impact, - acceptance criteria, and test scenarios so all agents can execute with less - prompt context and better alignment. + Maintain one change-local specification when durable scope or handoff is needed. + Capture requirements, acceptance, useful tasks, and evidence without duplicate + documents. Clear low-risk work may use existing issue or conversation context. allowed-tools: 'execute read search edit' argument-hint: '[change request, ticket reference, and scope]' diff --git a/src/vstack/_templates/skills/changedoc/template.md b/src/vstack/_templates/skills/changedoc/template.md index 11969ca5..e22ac8b6 100644 --- a/src/vstack/_templates/skills/changedoc/template.md +++ b/src/vstack/_templates/skills/changedoc/template.md @@ -2,11 +2,10 @@ # changedoc - Per-Change Planning Document -Create and maintain a changedoc for repository changes before implementation. -Use this for bug fixes, features, refactors, and similar change requests in -existing repositories. - -For new greenfield projects, start with vision/roadmap/requirements first. +Use one changedoc when scope needs durable agreement or handoff, or when requested. +Small, clear, low-risk work may use an existing issue or conversation with outcome +and verification instead. Risk, ambiguity, and project policy determine escalation, +not change size. For greenfield projects, start with vision/requirements/roadmap. ## File naming convention @@ -16,9 +15,9 @@ Write changedocs to: Use lowercase kebab-case for `<slug>` and concise snake_case for `<title>`. -In vstack repositories, initialize the file from: - -`.vstack/templates/product/artifacts/changes/changedoc.md` +Initialize from `.vstack/templates/product/artifacts/changes/changedoc.md`. +Older customized templates remain valid: supplement the new document, never +overwrite the local template or backfill historical changedocs. ## Required metadata @@ -44,48 +43,42 @@ Rules: 1. AS-IS 1. TO-BE 1. Impact (high level) -1. Acceptance Criteria -1. Test Scenarios - -## Procedure - -## Step 1 - Normalize request into scope - -Capture: - -- requested outcome -- explicit non-goals -- constraints and dependencies - -## Step 2 - Build AS-IS from repository evidence - -Use concrete file and behavior evidence. Avoid assumptions. +1. Requirements (change-local obligations, not duplicated system baselines) +1. Acceptance Criteria (observable completion) +1. Test Scenarios (how to check) +1. Verification (actual evidence and gaps) -## Step 3 - Define TO-BE +Add Execution Tasks only when useful; list real prerequisites, not dependencies +inferred from list order or role names. Multiple changes may share a branch. +Use local references when useful; preserve established references during revisions. -Describe the target behavior and implementation intent clearly enough for -cross-role handoff. - -## Step 4 - Record impact - -Cover at least: - -- architecture and boundaries -- API/data/model implications -- security and privacy implications -- operational implications (logs, metrics, rollout, migration) - -## Step 5 - Define acceptance criteria and test scenarios - -Make criteria observable and testable. -Include happy path, failure path, and regression scenarios. - -## Step 6 - Update status by lifecycle +## Procedure -- `CONCEPT`: initial proposal and discovery -- `BUILD`: approved for implementation -- `IMPLEMENTED`: implementation complete and verified -- `ARCHIVED`: closed and retained for history +1. Read relevant code and decisions; record scope, constraints, non-goals, and AS-IS evidence. +1. Resolve material ambiguity one question at a time after checking known answers. + Record accepted answers here; distinguish user outcomes from technical choices. +1. Define TO-BE, obligations, acceptance, and relevant happy/failure/regression + scenarios without repeating prose. Use verifiable delivery slices when useful. +1. Record architecture, contract/data, security/privacy, and operational impact; + link supporting material only when needed. Update affected shared baselines, + not a parallel specification tree. +1. Before implementation, confirm understood scope, observable acceptance, no + blocking questions, and required approval. Product owns intent; contributors + may maintain tasks/evidence but escalate scope deviations. +1. Record criterion, check/result, reviewed commit or working-tree scope, and + limitation. Use `passed`, `failed`, `not run`, or `no longer current`. + Required failed/unrun checks prevent full verification; approved exceptions + name the limitation and approver, never turn it into a pass. Production + outcomes needing observation remain follow-ups. +1. After material intent/behavior changes, preserve references and reassess only + affected tasks/evidence. Renew approval only for changed scope, risk, or policy. + +Lifecycle states are not ordered thresholds: + +- `CONCEPT`: discovery; implementation not authorized. +- `BUILD`: implementation authorized under project policy. +- `IMPLEMENTED`: agreed scope completed and verified. +- `ARCHIVED`: closed history; never authorizes new implementation. ## Output contract @@ -101,9 +94,6 @@ open_questions: none | <bullet list> ## Escalation -Escalate before implementation when: - -- acceptance criteria are ambiguous -- trust-boundary or security impact is unclear -- migration or rollback implications are unclear -- required stakeholders have not approved transition to `BUILD` +Pause affected implementation for unclear acceptance, trust-boundary risk, +migration/rollback decisions, or missing required approval. Lightweight routing +never bypasses safety gates. Keep text concrete and compact; link rather than copy. diff --git a/src/vstack/_templates/skills/inspect/config.yaml b/src/vstack/_templates/skills/inspect/config.yaml index 997f75f1..68a2f897 100644 --- a/src/vstack/_templates/skills/inspect/config.yaml +++ b/src/vstack/_templates/skills/inspect/config.yaml @@ -1,10 +1,9 @@ name: inspect -version: 20260421018 +version: 20261026001 description: | - Read-only verification audit. Runs baseline plus optional extended checks, - produces severity-ranked findings, and makes no code or commit changes. - Use when asked to "inspect", "assess", "check without fixing", or - "what's wrong with this" before deciding whether to run verify fix loops. + Read-only verification audit against agreed behavior, including missing work + and evidence gaps. Use for "inspect", "assess", or "check without fixing". + Report findings without code edits, commits, or mandatory duplicate reports. allowed-tools: 'execute read search' argument-hint: '[component or service to inspect]' diff --git a/src/vstack/_templates/skills/inspect/template.md b/src/vstack/_templates/skills/inspect/template.md index 1e638f66..5473511c 100644 --- a/src/vstack/_templates/skills/inspect/template.md +++ b/src/vstack/_templates/skills/inspect/template.md @@ -4,91 +4,54 @@ # inspect - Read-Only Verification Audit -Run verification checks and report findings. Do not edit code, do not commit, -and do not fix anything. +Assess and report; do not edit code, fix issues, or commit. Use `verify` for an +authorized fix loop, `architecture` for decisions, `security` for full audits, +and `performance` for profiling. -Use `verify` when a fix loop is required. +## Scope and report placement -## Out of scope +Read agreed intent, relevant contracts, project policy, and the reviewed commit +or working-tree scope. Compare actual in-scope behavior with acceptance, including +required behavior absent from the diff. Do not infer completion from checkboxes. -- Fixing issues (use `verify`) -- Architecture decisions (use `architecture`) -- Full security audit (use `security`) -- Performance profiling (use `performance`) +Use `docs/reports/test-report.md` when project policy or cross-change reporting +requires it. Otherwise report in the response, or update an existing changedoc +only when authorized. No duplicate report or mandatory new file. -## Deliverable and artifact policy +## Checks -- Primary deliverable: `docs/reports/test-report.md` -- Baseline-first default: write final findings directly to `docs/reports/test-report.md` on the feature branch. -- Before merge: confirm blocking findings and final verdict are written to baseline reports. +Discover repository commands and run the smallest checks covering acceptance and +regressions. Preserve command failures and missing-tool evidence; never suppress +errors or treat unavailable checks as passes. -## Step 0: Scope +| Surface | Checks when applicable | +| --------------------- | -------------------------------------------------------------------------------------------------------- | +| Baseline | Lint, types, build/package, unit tests | +| Integration/contracts | Service boundaries, OpenAPI/JSON Schema/Protobuf, compatibility | +| Reliability/data | Smoke, migrations/rollback, timeouts, retries, circuit breakers, concurrency | +| Observability | Structured failure/transition logs, latency/error/saturation metrics, trace propagation, alerts/runbooks | +| Dependencies | Repository vulnerability gate (for example audit tools); route deeper concerns | -```text -Report only. No edits. No commits. -If critical issues are found, recommend `verify`. -``` +Choose by scope and risk, not a universal checklist. Documentation-only work +needs document checks, not runtime tests. Record commands, results, and limits. -## Step 1: Baseline Checks +## Intent-to-behavior assessment -```bash -[ -f package.json ] && (npm run lint 2>/dev/null || true) -[ -f tsconfig.json ] && npx tsc --noEmit 2>/dev/null || true -[ -f pyproject.toml ] && (ruff check . 2>/dev/null || true) -[ -f pyproject.toml ] && (mypy . 2>/dev/null || pyright . 2>/dev/null || true) -[ -f go.mod ] && (go vet ./... 2>/dev/null || true) -``` +Separate missing behavior, contradictions, unexplained additions, and evidence +gaps. Ask for scope decisions on unrelated additions; do not delete them. +Necessary helpers need no separate product requirement. -{{RUN_TESTS}} +For each applicable criterion record: check/result, evidence reference, reviewed +scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. +Code coverage is not acceptance coverage; requirement wording is not runtime proof. +Reassess only evidence affected by material intent or behavior revisions. -## Step 2: Extended Checks (when present) +## Verdict -```bash -# Integration -[ -f package.json ] && npm run test:integration 2>/dev/null || true -[ -f pyproject.toml ] && python -m pytest -m integration -v 2>/dev/null || true -[ -f go.mod ] && go test -run Integration ./... 2>/dev/null || true +Return scope, checks, severity-ranked findings (source, impact, reproduction), +criterion evidence/gaps, residual risks, and next action: +`SHIP-READY`, `USE VERIFY FIX LOOP`, or `NEEDS ARCH/DESIGN REVIEW`. -# Contract -[ -f openapi.yaml ] && npx @redocly/cli lint openapi.yaml 2>/dev/null || true -[ -n "$(find . -name '*.proto' 2>/dev/null | head -1)" ] && buf lint 2>/dev/null || true - -# Lightweight vulnerability gate -[ -f package.json ] && npm audit --audit-level=high 2>/dev/null || true -[ -f pyproject.toml ] && pip-audit 2>/dev/null || true -[ -f go.mod ] && govulncheck ./... 2>/dev/null || true -``` - -### 2.1 Observability & Reliability Checks - -Confirm for changed paths: - -- Structured logs exist for key state transitions and failures. -- Metrics cover latency, error rate, and saturation for impacted services. -- Trace propagation exists across service boundaries where applicable. -- Alerts/runbooks exist for high-severity failure modes. - -## Step 3: Report - -```text -## Inspection Report - [component/repo] - [date] - -### Summary -- tests: [X pass / Y fail / Z skip] -- issues: [N critical / N high / N medium / N low] - -### Critical -1. [issue] - [file:line] - [evidence] - -### High -1. [issue] - [file:line] - [recommended fix] - -### Medium -1. [issue] - [file:line] - [recommended fix] - -### Low -1. [issue] - [notes] - -### Recommendation -[SHIP-READY | USE VERIFY FIX LOOP | NEEDS ARCH/DESIGN REVIEW] -``` +Required failed/unrun checks block full verification. Name any policy-approved +exception and approver without marking the criterion passed. Production outcomes +needing observation remain follow-ups. Sanitize evidence; do not copy sensitive logs. diff --git a/src/vstack/_templates/skills/requirements/config.yaml b/src/vstack/_templates/skills/requirements/config.yaml index b7f81f5c..76903f53 100644 --- a/src/vstack/_templates/skills/requirements/config.yaml +++ b/src/vstack/_templates/skills/requirements/config.yaml @@ -1,11 +1,9 @@ name: requirements -version: 20260421024 +version: 20261026001 description: | - Collaborative requirements gathering and documentation. Clarifies what must be - built, defines success criteria, constraints, and non-functional requirements. - Produces a requirements.md document. Use when asked to "gather requirements", - "write the requirements", "define the spec", or "what are we building?". - Runs before architecture and design work begins. + Clarify requirements, constraints, and observable acceptance in the existing + intent source. Use for "gather requirements", "define the spec", or "what are + we building?". Keep change-local intent separate from shared system baselines. allowed-tools: 'execute read search edit' argument-hint: '[feature or system to document]' diff --git a/src/vstack/_templates/skills/requirements/template.md b/src/vstack/_templates/skills/requirements/template.md index bd8a1df5..afdeb0f9 100644 --- a/src/vstack/_templates/skills/requirements/template.md +++ b/src/vstack/_templates/skills/requirements/template.md @@ -1,166 +1,58 @@ {{SKILL_CONTEXT}} -# requirements — Requirements Gathering & Documentation +# requirements - Requirements Gathering -Clarify and document what must be built before engineering starts. Produce a -`docs/product/requirements.md` that downstream roles (architect, designer, engineer) can -work from. +Define what must be built and observable acceptance before engineering. Product +owns scope; architecture, design, roadmap planning, and implementation belong to +their respective roles. -## Out of scope +## Choose the intent source -- Technical design and architecture decisions (use `architecture`) -- API/service design (use `design`) -- Roadmap and milestone planning (product role artifact) -- Implementation (engineering role) +- System-level intent: `docs/product/requirements.md` on the branch. +- Change-local intent: the existing changedoc, not a separate specification. +- Small, clear, low-risk task: sufficient existing issue or conversation context. -## Deliverable and artifact policy +Update shared baselines only when shared behavior or contracts change. Preserve +project gates and approvals regardless of task size; do not mandate every role. -- Primary deliverable: `docs/product/requirements.md` -- Baseline-first default: write final requirements directly to `docs/product/requirements.md` on the feature branch. -- Before merge: confirm requirements are complete and consistent before merge. +## Clarify from evidence -## Step 0: Context +1. Read relevant vision, requirements, roadmap, code, and recorded decisions first. +1. Identify the highest-impact uncertainty. Ask one focused question only when + it materially affects correctness, scope, risk, or approval; no interview quota. +1. Record accepted answers in the existing intent source, or confirm them in chat. + Do not repeat answered questions. State remaining assumptions and their risks. -Read existing artifacts before asking questions: +## Define requirements -```bash -cat docs/product/vision.md 2>/dev/null || true -cat docs/product/requirements.md 2>/dev/null || true -cat docs/product/roadmap.md 2>/dev/null || true -cat README.md 2>/dev/null | head -40 || true -``` +Capture only relevant dimensions: -Identify what's already known and what needs clarification. +| Dimension | Record | +| ------------------- | ----------------------------------------------------------------------------------- | +| Problem | Who is affected, unmet need, and consequence | +| Functional behavior | Must/should/won't-have outcomes, conditions, boundaries, and failure behavior | +| Quality attributes | Measurable performance/load, availability, security, scaling, or compliance targets | +| Constraints | Required technology, integration, budget, deadline, and team limits | +| Acceptance | Observable completion and how to check it | +| Open questions | Blocking decision, owner, and when needed | -## Step 1: Problem Statement +Use "The system must [behavior] under [condition]" where helpful. Keep outcomes +separate from technical choices unless a constraint requires them. Review +terminology, completeness, testability, and assumptions only for relevant scope. +A wording review is not proof that implementation works. -Clarify the core problem being solved: +Prefer independently verifiable delivery slices when useful; do not force them +on small fixes or tightly coupled migrations. Reference relevant contracts and +data-lifecycle/operational constraints rather than copying them. -> **Question:** Describe what you want to build and why. -> -> - What problem does this solve? -> - Who experiences this problem today? -> - What happens if we don't solve it? +## Output and readiness -Document: +For system baselines, organize findings as Problem, Users, Functional Requirements, +Non-Functional Requirements, Constraints/Assumptions, Acceptance, and Open Questions. +For change-local work, maintain the corresponding existing sections. -```text -## Problem Statement -[One paragraph: root problem, who has it, impact of not solving it] -``` - -## Step 2: Users & Stakeholders - -Who uses or is affected by this? - -| Role | Description | Primary need | -| ----------- | ----------- | ------------ | -| [User type] | | | - -## Step 3: Functional Requirements - -What must the system do? Use the format: "The system must [verb] [object] [condition/constraint]." - -Ask for clarity on ambiguous areas: - -> **Question:** Are there any specific behaviors or edge cases that are critical? - -```markdown -## Functional Requirements - -### Must have (MVP) -- FR-01: The system must [...] -- FR-02: The system must [...] - -### Should have (desirable) -- FR-03: [...] - -### Won't have (explicitly out of scope) -- [State what will NOT be built in this iteration] -``` - -## Step 4: Non-Functional Requirements - -| Category | Requirement | Measurable target | -| ------------ | -------------- | ------------------------------------ | -| Performance | Response time | p99 < 500ms under X rps | -| Availability | Uptime | 99.9% (< 8.7h downtime/year) | -| Security | Auth | All endpoints require authentication | -| Scalability | Load | Handle up to N concurrent users | -| Compliance | Data residency | Data stored in [region] | - -Ask: - -> **Question:** Are there any hard non-functional requirements (performance, security, -> compliance, data residency)? - -## Step 5: Constraints & Assumptions - -Document known constraints: - -```markdown -## Constraints -- Budget: [if relevant] -- Timeline: [hard deadline if any] -- Technology: [must use X, cannot use Y] -- Team: [available skill set] -- Existing systems: [must integrate with X] - -## Assumptions -- [Things assumed true that could invalidate requirements if wrong] -``` - -## Step 6: Success Criteria - -What does "done" look like? How do we know the requirements are met? - -```markdown -## Success Criteria -- [ ] [Measurable outcome 1] -- [ ] [Measurable outcome 2] -- [ ] [Acceptance test: given X, when Y, then Z] -``` - -## Step 7: Open Questions - -List anything that is unclear and needs a decision before work begins: - -```markdown -## Open Questions -- [ ] [Question] — Owner: [who decides] — Deadline: [when needed] -``` - -## Output: requirements.md - -Write all findings to `docs/product/requirements.md`: - -```markdown -# Requirements — [feature/project name] - -**Status:** draft | reviewed | approved -**Date:** YYYY-MM-DD -**Author:** product role - -## Problem Statement -[...] - -## Users & Stakeholders -[table] - -## Functional Requirements -[...] - -## Non-Functional Requirements -[table] - -## Constraints & Assumptions -[...] - -## Success Criteria -[...] - -## Open Questions -[...] -``` - -After writing, summarize what was decided so the architect role can start. +Use stable local references when useful; no global IDs or duplicate prose. +Summarize scope, criteria, and blockers for the relevant owner. Implementation +requires understood scope, observable acceptance, resolved blocking questions, +and approval under project policy. After material revisions, reassess affected +tasks/evidence and renew approval only when scope, risk, or policy requires it. diff --git a/src/vstack/_templates/skills/verify/config.yaml b/src/vstack/_templates/skills/verify/config.yaml index 685cebf0..a43b7080 100644 --- a/src/vstack/_templates/skills/verify/config.yaml +++ b/src/vstack/_templates/skills/verify/config.yaml @@ -1,11 +1,9 @@ name: verify -version: 20260421026 +version: 20261026001 description: | - Verification fix-loop skill. Routes by mode (quick/standard/exhaustive), runs - targeted checks, fixes findings by severity, and re-verifies impacted paths. - Routes report-only requests to inspect and escalates deep security/performance - concerns to specialized skills. Use when asked to "verify", "fix failing checks", - "run QA with fixes", or "re-verify before shipping". + Verify agreed behavior in quick/standard/exhaustive mode, fix authorized gaps, + and rerun affected checks. Use for "verify", "fix failing checks", or "run QA + with fixes". Route report-only work to inspect; stop on blockers or no progress. allowed-tools: 'execute read search edit' argument-hint: '[component or feature to verify]' diff --git a/src/vstack/_templates/skills/verify/template.md b/src/vstack/_templates/skills/verify/template.md index 18f18ed8..9531ed24 100644 --- a/src/vstack/_templates/skills/verify/template.md +++ b/src/vstack/_templates/skills/verify/template.md @@ -4,181 +4,81 @@ # verify - Fix Loop Verification -Run a targeted verification fix loop: +Check agreed behavior, fix authorized gaps, and rerun affected checks. Use +`inspect` for report-only work, `architecture` for decisions, `security` for deep +audits, and `performance` for profiling. Do not add features outside agreed scope. -1. choose scope/mode, -1. run checks, -1. fix issues in priority order, -1. re-run only impacted checks, -1. report ship readiness. +## 1. Select mode and scope -Use `inspect` for read-only auditing. +Use the requested mode, otherwise `standard`: -## Out of scope +| Mode | Depth and fix policy | +| ----------- | ------------------------------------------------------------------------------------------ | +| quick | Focused critical/high regressions; broaden if acceptance needs it | +| standard | Relevant baseline, integration, contract, and reliability checks; fix critical/high/medium | +| exhaustive | Standard plus relevant smoke, dependency, and operational checks; all severities | +| report-only | Route to `inspect`; no fixes | -- Architecture decisions (use `architecture`) -- Full security audit (use `security`) -- Performance benchmarking/profiling (use `performance`) -- New feature implementation outside verification fixes (engineering role) +Read intent, criteria, relevant contracts, project policy, and working-tree +changes. Establish reviewed commit or working-tree scope. Preserve unrelated +edits; ask before conflicting changes. Commit only when authorized. +Small low-risk tasks may use an existing issue/conversation; no mandatory document. -## Deliverable and artifact policy +Readiness requires understood scope, observable acceptance, resolved blockers, +and policy approval. Safety gates apply regardless of mode or task size. -- Primary deliverable: `docs/reports/test-report.md` -- Additional deliverables when applicable: `docs/reports/security-report.md`, `docs/reports/performance-baseline.md` -- Baseline-first default: write final verification outcomes directly to baseline reports on the feature branch. -- Before merge: consolidate final findings, severity, and ship-readiness verdict into baseline reports. +## 2. Check behavior -## Step 0: Route Mode +Compare actual in-scope behavior with acceptance, including required behavior +absent from the diff. Discover existing repository commands and run the smallest +checks covering changed behavior and regressions. Broaden only as needed. -Classify first, then run one mode. +| Surface | Checks when applicable | +| ---------------- | --------------------------------------------------------------------------------------------- | +| Baseline | Lint, types, build/package, unit tests | +| Boundaries | Integration, OpenAPI/JSON Schema/Protobuf, API compatibility | +| Reliability/data | Smoke, migrations/rollback, retries/backoff, timeouts, circuit breakers, concurrency | +| Operations | Failure/transition logs, latency/error/saturation metrics, trace propagation, alerts/runbooks | +| Dependencies | Existing vulnerability gate; route deeper security/performance concerns | -> **Question:** Which verify mode should be used? -> **Options:** -> A) quick - critical/high regressions only -> B) standard - default verification + fix loop -> C) exhaustive - broad verification and full fix sweep -> D) report-only - route to `inspect` -> **Default if no response:** B +Use measurable operational evidence when relevant, not runtime tests for prose. +Preserve failures and missing-tool details; never suppress errors or substitute +an available check for a different required one. -If D, stop and route to `inspect`. +## 3. Triage and fix -## Step 1: Scope and Safety +Separate behavioral gaps, contradictions, unexplained additions, and unavailable +evidence. Severity: critical (build/data/security failure), high (broken contract +or required check), medium (other behavior/flakiness), low (minor cleanup). -Parse user scope: - -- Target: whole repo or specific component/path -- Tier: quick/standard/exhaustive -- Source: full branch diff or explicit path - -Check working tree: - -```bash -git status --porcelain -``` - -If dirty, ask before proceeding because verify may create multiple atomic fix commits. - -Bootstrap test command: - -{{RUN_TESTS}} - -## Step 2: Baseline Checks (all modes) - -Run baseline checks for the selected scope. - -### 2.1 Lint and Type - -```bash -[ -f package.json ] && (npm run lint 2>/dev/null || true) -[ -f tsconfig.json ] && npx tsc --noEmit 2>/dev/null || true -[ -f pyproject.toml ] && (ruff check . 2>/dev/null || true) -[ -f pyproject.toml ] && (mypy . 2>/dev/null || pyright . 2>/dev/null || true) -[ -f go.mod ] && (go vet ./... 2>/dev/null || true) -``` - -### 2.2 Unit Tests - -{{RUN_TESTS}} - -## Step 3: Conditional Checks by Mode - -### quick - -- Run only failing or high-risk checks related to changed code -- Skip broad integration/contract/smoke unless directly impacted - -### standard - -Run these when present: - -```bash -# Integration -[ -f package.json ] && npm run test:integration 2>/dev/null || true -[ -f pyproject.toml ] && python -m pytest -m integration -v 2>/dev/null || true -[ -f go.mod ] && go test -run Integration ./... 2>/dev/null || true - -# Contract -[ -f openapi.yaml ] && npx @redocly/cli lint openapi.yaml 2>/dev/null || true -[ -n "$(find . -name '*.proto' 2>/dev/null | head -1)" ] && buf lint 2>/dev/null || true -``` - -Also verify observability on impacted paths: - -- Structured logs for critical transitions and errors -- Metrics for latency/error/saturation -- Trace propagation across service boundaries -- Alerts or runbooks for critical failure modes - -### exhaustive - -Run standard checks plus: - -```bash -# Optional smoke checks if scripts exist -find . -name '*.smoke.*' -o -name '*smoke-test*' -o -name 'smoke.sh' 2>/dev/null | head -5 - -# Dependency vulnerability gate (lightweight only; full audit belongs to security) -[ -f package.json ] && npm audit --audit-level=high 2>/dev/null || true -[ -f pyproject.toml ] && pip-audit 2>/dev/null || true -[ -f go.mod ] && govulncheck ./... 2>/dev/null || true -``` - -For exhaustive mode, require observability evidence (logs/metrics/traces/alerts) in the final report. - -If deep security/performance concerns appear, stop and route to `security` or `performance`. - -## Step 4: Triage - -Classify findings: - -| Severity | Examples | -| -------- | ------------------------------------------------------------------- | -| critical | test crashes, build breaks, data integrity/security regressions | -| high | contract violations, broken error handling, missing required checks | -| medium | flaky tests, non-critical behavior gaps | -| low | style and minor cleanups | - -Fix policy: - -- quick: critical + high -- standard: critical + high + medium -- exhaustive: all severities - -## Step 5: Fix and Re-verify Loop - -For each fixable issue in severity order: +Within the mode's fix policy: 1. Reproduce and confirm root cause. -1. Apply minimal fix. -1. Commit atomically (`fix: ...`). -1. Re-run only impacted checks first. -1. If needed, run the relevant broader check suite. - -If an issue implies architecture or design mismatch, stop and escalate. - -## Step 6: Final Report - -```text -## Verification Report - [component/repo] - [date] - -selected_mode: [quick|standard|exhaustive] -scope: [path/component/full] - -### Summary -- tests: [X pass / Y fail / Z skip] -- issues found: [N critical / N high / N medium / N low] -- fixes applied: [N] -- deferred: [N] - -### Fixed Issues -1. [issue] - [commit SHA] - -### Deferred Issues -1. [issue] - [why deferred] - [owner] - -### Routed Follow-ups (if any) -- [security|performance|architecture|design] - [reason] - -### Ship Readiness -[READY TO SHIP | NEEDS FIXES | BLOCKED] -``` +1. Apply the smallest authorized fix; preserve acceptance and role ownership. +1. Rerun affected checks, then broader checks if needed. +1. Update useful existing tasks, not an append-only remediation history. + +Unexplained additions require a scope decision, not automatic deletion; necessary +helpers need no separate requirement. Escalate changed intent/contracts to their +owner. After material revisions, preserve criterion references and reassess only +affected tasks/evidence. Renew approval only for scope, risk, or policy changes. + +Stop and report blockers when required evidence cannot be obtained, scope/policy +decisions are needed, or attempts repeat without new evidence. Honor existing +iteration budgets; do not loop indefinitely or weaken criteria to claim success. + +## 4. Record evidence and verdict + +Use `docs/reports/test-report.md` (and scoped security/performance reports) when +policy or cross-change reporting requires it. Otherwise keep evidence in the +existing changedoc or response; no duplicate reports. + +Report mode/scope, checks/results, fixes, deferred findings with owners, and +residual risks. Map applicable criteria to check/result, evidence reference, +reviewed scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. +Code coverage and task checkboxes are not acceptance evidence. + +Verdict: `READY TO SHIP`, `NEEDS FIXES`, or `BLOCKED`. Required failed/unrun checks +prevent full verification; name policy-approved exceptions and approvers without +reporting a pass. Production outcomes needing observation remain follow-ups. +Sanitize evidence references; do not persist secrets or sensitive logs. diff --git a/tests/_fixtures/golden/agents/planner.agent.md b/tests/_fixtures/golden/agents/planner.agent.md index b47ccfc0..4bf856cc 100644 --- a/tests/_fixtures/golden/agents/planner.agent.md +++ b/tests/_fixtures/golden/agents/planner.agent.md @@ -1,7 +1,7 @@ --- description: >- - vstack orchestration coordinator. Reads workflow stages from project config, invokes role subagents - in sequence, applies gate and human-approval policy, and reports clear progression status. + vstack coordinator. Routes focused work to its owner or orchestrates configured stage dependencies, + gates, and approvals. Reports progress without doing role work. name: planner argument-hint: '[run workflow | orchestrate stages | gate progression | coordinator mode]' tools: @@ -23,17 +23,14 @@ target: vscode ## identity and purpose -You are the **vstack orchestration planner**. Your role is to **plan and delegate — not to execute**. - -You coordinate stage execution by invoking the right role agent for each stage and enforcing -explicit gate progression. Every piece of substantive work belongs to a worker agent. The planner -never does that work itself — it assigns, tracks, and advances. +You are the **vstack orchestration planner**: plan, delegate, track, and enforce +gates. Worker agents execute substantive work; never perform their work yourself. ## responsibilities - Read the configured workflow stages and evaluate `depends_on` to determine execution order. - Invoke the designated worker agent for each ready stage and collect its stage report; never perform the stage work yourself. -- Run independent branches in parallel when their `depends_on` sets do not overlap. +- Run ready stages in parallel when their work and shared state are independent. - Apply gate and human-in-the-loop policy at each transition. - Keep a concise execution log: completed, skipped, blocked, and pending stages. @@ -47,10 +44,9 @@ never does that work itself — it assigns, tracks, and advances. ## scope and boundaries -- Planner owns **orchestration only**: dependency evaluation, agent invocation, gate enforcement, and execution tracking. -- Planner produces **no work product of its own**: no code, no architecture decisions, no API contracts, no test results, no release artifacts. All of that belongs to the worker agents. -- When a task or question surfaces, the default answer is: **which worker agent owns this?** Route it. Do not answer it yourself. -- Only coordination tasks with no worker-agent owner (dependency evaluation, gate checks, execution logging, status reporting) stay with the planner. +- Own dependency evaluation, invocation, gates, execution logs, and status only. +- Route domain work/questions to their owner: no code, architecture, contracts, + test results, or release artifacts from planner. ## limitations and do not do @@ -87,11 +83,20 @@ For full pipelines, agree a short plan with the user before dispatch: 1. Freeze the accepted plan for the run. 1. Replan only on new facts, and only with a minimal approved delta. -For change requests in existing repositories (bug, feature, refactor, chore): - -1. Require a changedoc at `docs/changes/<slug>_<title>_YYYYMMDD.md` before implementation. -1. If missing, delegate changedoc creation/update first (typically `@product`, then `@architect`/`@designer`/`@engineer`/`@tester` as needed). -1. Do not dispatch implementation work until changedoc `status` is at least `BUILD`. +For existing-repository changes: + +1. Small, clear, low-risk work may use sufficient issue or conversation context. + Require understood scope, observable acceptance, resolved blockers, and policy approval. +1. For durable scope/handoff or an explicit request, route changedoc work to product. + `CONCEPT` is discovery; `BUILD` authorizes implementation; `IMPLEMENTED` records + verified completion; `ARCHIVED` is closed history, never authorization. + These states are not ordered thresholds. +1. Involve only relevant roles without bypassing configured pipeline gates or safety. + Use useful tasks with real prerequisites, not task order or role names; multiple + changes may share a branch. Configured stage dependencies remain authoritative. +1. Pass intent/criterion references and blockers in existing handoff fields; no + added report fields. Replan affected work/evidence after material revisions; + renew approval only when scope, risk, or policy requires it. ## working principles @@ -223,12 +228,8 @@ Execution model: 1. Stop when release completes or a blocker requires user routing. -Planner run correlation: - -- At run start, create one stable `PLANNER_RUN_ID` (for example, UTC timestamp + short suffix). -- Pass the same `PLANNER_RUN_ID` to every delegated worker stage. -- Pass the worker cache file path for that stage as part of the delegated prompt. -- Require each worker stage report to echo the same value in `planner_run_id`. +Pass the stable `PLANNER_RUN_ID` and worker cache path to each stage; require the +same `planner_run_id` in its report. When invoking a worker stage, require this structured stage report at the end: @@ -286,9 +287,9 @@ that requires changes to upstream items, flag it and trigger a reverse handoff. ## skills you use - `@#analyse` - assess stage impact, skip rationale, and trade-offs -- `@#changedoc` - create and maintain per-change docs for existing repository changes +- `@#changedoc` - durable change-local scope, acceptance, tasks, and evidence - `@#concise` - runtime response-style mode (`normal|compact|ultra|status`) - `@#simplify` - simplify stage plans and handoffs while preserving gate requirements <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"planner","artifact_type":"agent","artifact_version":"20260514001","generator":"vstack","vstack_version":"3.6.0"} --> +<!-- VSTACK-META: {"artifact_name":"planner","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"<vstack-version>"} --> diff --git a/tests/_fixtures/golden/agents/product.agent.md b/tests/_fixtures/golden/agents/product.agent.md index 3b135237..defd1fef 100644 --- a/tests/_fixtures/golden/agents/product.agent.md +++ b/tests/_fixtures/golden/agents/product.agent.md @@ -1,8 +1,7 @@ --- description: >- - Senior product manager. Defines vision, requirements, and roadmap for new products, new features, - and major scope changes. Baseline-first on branch: update product items directly and orchestrate - role-owned baseline updates in architecture and design. Baseline-first on branch. + Senior product manager. Owns vision, scope, requirements, and acceptance. Keeps change-local intent + proportional and shared baselines current; coordinates relevant owners and required approvals. name: product argument-hint: '[vision | requirements | scope review | acceptance review | release readiness check]' tools: @@ -33,7 +32,7 @@ You are a **senior product manager** acting as the **product role**. You define ## responsibilities - Define and refine scope for new products, features, and major scope changes. -- Initialize changedocs for existing-repository change requests and keep scope/acceptance sections current. +- Maintain change-local intent in a changedoc when durable scope/handoff is needed or requested. - Own acceptance criteria and release-acceptance decisions. - Orchestrate role handoffs and gate progression through the pipeline. - Ensure product baseline items are current before release. @@ -52,11 +51,11 @@ You are a **senior product manager** acting as the **product role**. You define ## working principles -- Baseline-first: keep canonical docs updated as work evolves on the feature branch. +- Baseline-first: update affected shared behavior/contracts on branch, not every local detail. - Prefer explicit acceptance criteria over vague intent. - Keep scope decisions reversible until architecture/design gates are approved. - Choose the smallest scope that still achieves measurable outcomes. -- Escalate ambiguity early; require architecture and design evidence before implementation starts. +- Resolve blocking ambiguity before implementation; involve architecture/design when affected. ## decision guidelines @@ -77,7 +76,7 @@ You are a **senior product manager** acting as the **product role**. You define - Default concise mode: `compact`. - Summarize deltas since the last iteration. - Ask structured clarification questions when needed. -- State assumptions and ask for confirmation at each gate. +- State assumptions; honor required approvals without inventing extra gates. ## agent-skill boundary @@ -97,7 +96,7 @@ You are a **senior product manager** acting as the **product role**. You define ## workflow and handoffs -You pause the pipeline at key moments and wait for explicit user confirmation: +For a full pipeline, pause for required user approvals: 1. **After intake + requirements clarification** — before architect starts designing 1. **After architecture + design review** — before engineer starts implementing @@ -141,14 +140,21 @@ Use `.vstack/memories/session/<RUN_ID>/` only to avoid replaying the same short- ## how you work -1. **Intake:** Understand the request and use `@#requirements` to clarify scope, constraints, and success criteria. -1. **Changedoc first:** For existing repositories, create or update `docs/changes/<slug>_<title>_YYYYMMDD.md` from `.vstack/templates/product/artifacts/changes/changedoc.md`. -1. **Choose flow:** - - Brownfield: `@#requirements` → `@#explore` → `@#analyse` → `architect` - - New feature: `@#requirements` → `architect` → `designer` → `engineer` → `tester` → `release` - - Existing behavior change: `@#requirements` → `@#debug` → `architect` (light) → `engineer` → `tester` → `release` -1. **Orchestrate:** Delegate only after explicit user approval where required. -1. **Gate and summarize:** confirm transitions, then report decisions, changed items, and next steps. +1. Read known decisions and code; use `@#requirements` for material uncertainty, + one question at a time. Record accepted answers in the current intent source. +1. For small, clear, low-risk work, use sufficient issue or conversation context. + Otherwise use `@#changedoc`; no duplicate specification. Older local templates + remain valid; supplement new documents without overwriting customized templates. +1. Establish scope, observable acceptance, and resolved blockers. Use verifiable + slices and local references when helpful; preserve references during revisions. +1. Involve relevant owners only; use `@#analyse` for requested/risk-justified + consistency review. Configured workflow dependencies, gates, and approvals remain + authoritative in pipelines; lightweight work never bypasses safety. +1. Changedoc lifecycle: `CONCEPT` is discovery, `BUILD` authorizes implementation, + `IMPLEMENTED` requires verified completion, `ARCHIVED` is closed history and + never authorizes work. Renew approval only for changed scope, risk, or policy. +1. Summarize scope, criterion/evidence references, blockers, and next action in + existing handoff fields. Wording review is not behavioral verification. ## success criteria @@ -201,7 +207,7 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#adr` — architecture decision record writing (if significant decisions) - `@#analyse` — impact analysis, tradeoffs, feasibility -- `@#changedoc` — create and maintain per-change docs before implementation in existing repositories +- `@#changedoc` — durable change-local scope, acceptance, tasks, and evidence - `@#concise` — runtime response-style mode (`normal|compact|ultra|status`) - `@#docs` — keep product items and release-facing documentation aligned - `@#explore` — codebase discovery and mapping (brownfield intake) @@ -213,4 +219,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#vision` — vision document writing and review <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20260514001","generator":"vstack","vstack_version":"3.6.0"} --> +<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"<vstack-version>"} --> diff --git a/tests/_fixtures/golden/instructions/testing.instructions.md b/tests/_fixtures/golden/instructions/testing.instructions.md index 7664eb3b..216fbeee 100644 --- a/tests/_fixtures/golden/instructions/testing.instructions.md +++ b/tests/_fixtures/golden/instructions/testing.instructions.md @@ -7,7 +7,7 @@ Use these testing conventions. ## Scope and intent -1. Write tests to verify observable behavior, not internal implementation details. +1. Derive tests from observable acceptance, not internal implementation details. 1. A test that passes when behavior is wrong, or fails when behavior is correct, has negative value. 1. Tests should read like documentation. @@ -21,7 +21,8 @@ Use these testing conventions. 1. Cover success paths, expected failure paths, and boundary conditions for every behavioral change. 1. Treat missing tests for changed behavior as a defect. -1. Cover behaviors that matter rather than lines that exist. +1. Cover relevant failure, compatibility, and data/operational boundaries; no universal test-type checklist. +1. Code coverage and task checkboxes do not prove acceptance; required failed or unrun checks are not passes. ## Test quality @@ -43,4 +44,4 @@ Use these testing conventions. 1. Treat flaky tests as bugs. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"testing","artifact_type":"instruction","artifact_version":"20260502004","generator":"vstack","vstack_version":"<vstack-version>"} --> +<!-- VSTACK-META: {"artifact_name":"testing","artifact_type":"instruction","artifact_version":"20261026001","generator":"vstack","vstack_version":"<vstack-version>"} --> diff --git a/tests/_fixtures/golden/skills/verify.SKILL.md b/tests/_fixtures/golden/skills/verify.SKILL.md index a2e0e3b0..318ce10d 100644 --- a/tests/_fixtures/golden/skills/verify.SKILL.md +++ b/tests/_fixtures/golden/skills/verify.SKILL.md @@ -1,6 +1,6 @@ --- name: verify -description: 'Verification fix-loop skill. Routes by mode (quick/standard/exhaustive), runs targeted checks, fixes findings by severity, and re-verifies impacted paths. Routes report-only requests to inspect and escalates deep security/performance concerns to specialized skills. Use when asked to "verify", "fix failing checks", "run QA with fixes", or "re-verify before shipping".' +description: 'Verify agreed behavior in quick/standard/exhaustive mode, fix authorized gaps, and rerun affected checks. Use for "verify", "fix failing checks", or "run QA with fixes". Route report-only work to inspect; stop on blockers or no progress.' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access and terminal command execution when needed.' metadata: @@ -44,226 +44,84 @@ echo "Base branch: $BASE" # verify - Fix Loop Verification -Run a targeted verification fix loop: +Check agreed behavior, fix authorized gaps, and rerun affected checks. Use +`inspect` for report-only work, `architecture` for decisions, `security` for deep +audits, and `performance` for profiling. Do not add features outside agreed scope. -1. choose scope/mode, -1. run checks, -1. fix issues in priority order, -1. re-run only impacted checks, -1. report ship readiness. +## 1. Select mode and scope -Use `inspect` for read-only auditing. +Use the requested mode, otherwise `standard`: -## Out of scope +| Mode | Depth and fix policy | +| ----------- | ------------------------------------------------------------------------------------------ | +| quick | Focused critical/high regressions; broaden if acceptance needs it | +| standard | Relevant baseline, integration, contract, and reliability checks; fix critical/high/medium | +| exhaustive | Standard plus relevant smoke, dependency, and operational checks; all severities | +| report-only | Route to `inspect`; no fixes | -- Architecture decisions (use `architecture`) -- Full security audit (use `security`) -- Performance benchmarking/profiling (use `performance`) -- New feature implementation outside verification fixes (engineering role) +Read intent, criteria, relevant contracts, project policy, and working-tree +changes. Establish reviewed commit or working-tree scope. Preserve unrelated +edits; ask before conflicting changes. Commit only when authorized. +Small low-risk tasks may use an existing issue/conversation; no mandatory document. -## Deliverable and artifact policy +Readiness requires understood scope, observable acceptance, resolved blockers, +and policy approval. Safety gates apply regardless of mode or task size. -- Primary deliverable: `docs/reports/test-report.md` -- Additional deliverables when applicable: `docs/reports/security-report.md`, `docs/reports/performance-baseline.md` -- Baseline-first default: write final verification outcomes directly to baseline reports on the feature branch. -- Before merge: consolidate final findings, severity, and ship-readiness verdict into baseline reports. +## 2. Check behavior -## Step 0: Route Mode +Compare actual in-scope behavior with acceptance, including required behavior +absent from the diff. Discover existing repository commands and run the smallest +checks covering changed behavior and regressions. Broaden only as needed. -Classify first, then run one mode. +| Surface | Checks when applicable | +| ---------------- | --------------------------------------------------------------------------------------------- | +| Baseline | Lint, types, build/package, unit tests | +| Boundaries | Integration, OpenAPI/JSON Schema/Protobuf, API compatibility | +| Reliability/data | Smoke, migrations/rollback, retries/backoff, timeouts, circuit breakers, concurrency | +| Operations | Failure/transition logs, latency/error/saturation metrics, trace propagation, alerts/runbooks | +| Dependencies | Existing vulnerability gate; route deeper security/performance concerns | -> **Question:** Which verify mode should be used? -> **Options:** -> A) quick - critical/high regressions only -> B) standard - default verification + fix loop -> C) exhaustive - broad verification and full fix sweep -> D) report-only - route to `inspect` -> **Default if no response:** B +Use measurable operational evidence when relevant, not runtime tests for prose. +Preserve failures and missing-tool details; never suppress errors or substitute +an available check for a different required one. -If D, stop and route to `inspect`. +## 3. Triage and fix -## Step 1: Scope and Safety +Separate behavioral gaps, contradictions, unexplained additions, and unavailable +evidence. Severity: critical (build/data/security failure), high (broken contract +or required check), medium (other behavior/flakiness), low (minor cleanup). -Parse user scope: - -- Target: whole repo or specific component/path -- Tier: quick/standard/exhaustive -- Source: full branch diff or explicit path - -Check working tree: - -```bash -git status --porcelain -``` - -If dirty, ask before proceeding because verify may create multiple atomic fix commits. - -Bootstrap test command: - -```bash -# Detect test runner and run tests -if [ -f package.json ]; then - if grep -q '"vitest"' package.json 2>/dev/null; then - npx vitest run - elif grep -q '"jest"' package.json 2>/dev/null; then - npx jest - elif grep -q '"bun"' package.json 2>/dev/null; then - bun test - else - npm test - fi -elif [ -f pyproject.toml ] || [ -f setup.py ]; then - python -m pytest -v -elif [ -f go.mod ]; then - go test ./... -elif [ -f Cargo.toml ]; then - cargo test -else - echo "No recognized test framework detected." -fi -``` - -## Step 2: Baseline Checks (all modes) - -Run baseline checks for the selected scope. - -### 2.1 Lint and Type - -```bash -[ -f package.json ] && (npm run lint 2>/dev/null || true) -[ -f tsconfig.json ] && npx tsc --noEmit 2>/dev/null || true -[ -f pyproject.toml ] && (ruff check . 2>/dev/null || true) -[ -f pyproject.toml ] && (mypy . 2>/dev/null || pyright . 2>/dev/null || true) -[ -f go.mod ] && (go vet ./... 2>/dev/null || true) -``` - -### 2.2 Unit Tests - -```bash -# Detect test runner and run tests -if [ -f package.json ]; then - if grep -q '"vitest"' package.json 2>/dev/null; then - npx vitest run - elif grep -q '"jest"' package.json 2>/dev/null; then - npx jest - elif grep -q '"bun"' package.json 2>/dev/null; then - bun test - else - npm test - fi -elif [ -f pyproject.toml ] || [ -f setup.py ]; then - python -m pytest -v -elif [ -f go.mod ]; then - go test ./... -elif [ -f Cargo.toml ]; then - cargo test -else - echo "No recognized test framework detected." -fi -``` - -## Step 3: Conditional Checks by Mode - -### quick - -- Run only failing or high-risk checks related to changed code -- Skip broad integration/contract/smoke unless directly impacted - -### standard - -Run these when present: - -```bash -# Integration -[ -f package.json ] && npm run test:integration 2>/dev/null || true -[ -f pyproject.toml ] && python -m pytest -m integration -v 2>/dev/null || true -[ -f go.mod ] && go test -run Integration ./... 2>/dev/null || true - -# Contract -[ -f openapi.yaml ] && npx @redocly/cli lint openapi.yaml 2>/dev/null || true -[ -n "$(find . -name '*.proto' 2>/dev/null | head -1)" ] && buf lint 2>/dev/null || true -``` - -Also verify observability on impacted paths: - -- Structured logs for critical transitions and errors -- Metrics for latency/error/saturation -- Trace propagation across service boundaries -- Alerts or runbooks for critical failure modes - -### exhaustive - -Run standard checks plus: - -```bash -# Optional smoke checks if scripts exist -find . -name '*.smoke.*' -o -name '*smoke-test*' -o -name 'smoke.sh' 2>/dev/null | head -5 - -# Dependency vulnerability gate (lightweight only; full audit belongs to security) -[ -f package.json ] && npm audit --audit-level=high 2>/dev/null || true -[ -f pyproject.toml ] && pip-audit 2>/dev/null || true -[ -f go.mod ] && govulncheck ./... 2>/dev/null || true -``` - -For exhaustive mode, require observability evidence (logs/metrics/traces/alerts) in the final report. - -If deep security/performance concerns appear, stop and route to `security` or `performance`. - -## Step 4: Triage - -Classify findings: - -| Severity | Examples | -| -------- | ------------------------------------------------------------------- | -| critical | test crashes, build breaks, data integrity/security regressions | -| high | contract violations, broken error handling, missing required checks | -| medium | flaky tests, non-critical behavior gaps | -| low | style and minor cleanups | - -Fix policy: - -- quick: critical + high -- standard: critical + high + medium -- exhaustive: all severities - -## Step 5: Fix and Re-verify Loop - -For each fixable issue in severity order: +Within the mode's fix policy: 1. Reproduce and confirm root cause. -1. Apply minimal fix. -1. Commit atomically (`fix: ...`). -1. Re-run only impacted checks first. -1. If needed, run the relevant broader check suite. - -If an issue implies architecture or design mismatch, stop and escalate. +1. Apply the smallest authorized fix; preserve acceptance and role ownership. +1. Rerun affected checks, then broader checks if needed. +1. Update useful existing tasks, not an append-only remediation history. -## Step 6: Final Report +Unexplained additions require a scope decision, not automatic deletion; necessary +helpers need no separate requirement. Escalate changed intent/contracts to their +owner. After material revisions, preserve criterion references and reassess only +affected tasks/evidence. Renew approval only for scope, risk, or policy changes. -```text -## Verification Report - [component/repo] - [date] +Stop and report blockers when required evidence cannot be obtained, scope/policy +decisions are needed, or attempts repeat without new evidence. Honor existing +iteration budgets; do not loop indefinitely or weaken criteria to claim success. -selected_mode: [quick|standard|exhaustive] -scope: [path/component/full] +## 4. Record evidence and verdict -### Summary -- tests: [X pass / Y fail / Z skip] -- issues found: [N critical / N high / N medium / N low] -- fixes applied: [N] -- deferred: [N] +Use `docs/reports/test-report.md` (and scoped security/performance reports) when +policy or cross-change reporting requires it. Otherwise keep evidence in the +existing changedoc or response; no duplicate reports. -### Fixed Issues -1. [issue] - [commit SHA] +Report mode/scope, checks/results, fixes, deferred findings with owners, and +residual risks. Map applicable criteria to check/result, evidence reference, +reviewed scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. +Code coverage and task checkboxes are not acceptance evidence. -### Deferred Issues -1. [issue] - [why deferred] - [owner] - -### Routed Follow-ups (if any) -- [security|performance|architecture|design] - [reason] - -### Ship Readiness -[READY TO SHIP | NEEDS FIXES | BLOCKED] -``` +Verdict: `READY TO SHIP`, `NEEDS FIXES`, or `BLOCKED`. Required failed/unrun checks +prevent full verification; name policy-approved exceptions and approvers without +reporting a pass. Production outcomes needing observation remain follow-ups. +Sanitize evidence references; do not persist secrets or sensitive logs. <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"verify","artifact_type":"skill","artifact_version":"20260421026","generator":"vstack","vstack_version":"<vstack-version>"} --> +<!-- VSTACK-META: {"artifact_name":"verify","artifact_type":"skill","artifact_version":"20261026001","generator":"vstack","vstack_version":"<vstack-version>"} --> diff --git a/tests/vstack/agents/test_template_structure.py b/tests/vstack/agents/test_template_structure.py index 46e1d998..d3d9e2cc 100644 --- a/tests/vstack/agents/test_template_structure.py +++ b/tests/vstack/agents/test_template_structure.py @@ -4,6 +4,8 @@ from pathlib import Path +import pytest + TEMPLATES_ROOT = Path(__file__).resolve().parents[3] / "src" / "vstack" / "_templates" / "agents" ROLES = ["product", "architect", "designer", "engineer", "tester", "release", "planner"] REQUIRED_HEADINGS_IN_ORDER = [ @@ -44,3 +46,70 @@ def test_all_role_templates_follow_canonical_section_order() -> None: positions.append(headings.index(heading)) assert positions == sorted(positions), f"{role} canonical headings out of order" + + +@pytest.mark.parametrize("role", ["product", "planner"]) +def test_rendered_intake_allows_focused_work_without_weakening_lifecycle( + installed_target: Path, role: str +) -> None: + """Focused routing preserves authorization and rejects archived-state ordering.""" + text = " ".join( + (installed_target / ".github" / "agents" / f"{role}.agent.md") + .read_text(encoding="utf-8") + .split() + ) + assert "low-risk work" in text + assert "conversation context" in text + assert "observable acceptance" in text + for status in ("CONCEPT", "BUILD", "IMPLEMENTED", "ARCHIVED"): + assert f"`{status}`" in text + assert "at least `BUILD`" not in text + assert "never authoriz" in text + assert "gates" in text and "approval" in text + + +@pytest.mark.parametrize("role", ROLES) +def test_rendered_roles_keep_shared_stage_report_contract( + installed_target: Path, role: str +) -> None: + """Evidence references use existing fields, not an expanded report schema.""" + contract = (TEMPLATES_ROOT / "_partials" / "stage-report-contract.md").read_text( + encoding="utf-8" + ) + rendered = (installed_target / ".github" / "agents" / f"{role}.agent.md").read_text( + encoding="utf-8" + ) + assert contract.strip() in rendered + assert "{{" not in rendered + + +def test_rendered_contributors_preserve_scope_ownership(installed_target: Path) -> None: + """Engineer/tester can record evidence without rewriting product acceptance.""" + for role in ("engineer", "tester"): + text = (installed_target / ".github" / "agents" / f"{role}.agent.md").read_text( + encoding="utf-8" + ) + assert "not product scope or acceptance" in text + + +@pytest.mark.parametrize( + ("role", "obligations"), + [ + ("architect", ("constraints", "acceptance", "migration risks")), + ("designer", ("acceptance", "error/compatibility", "data-lifecycle")), + ("engineer", ("verifiable slices", "real prerequisites", "failed/unrun checks")), + ("tester", ("absent from the diff", "no longer current", "otherwise use")), + ("release", ("criterion/check/result", "evidence freshness", "exceptions")), + ], +) +def test_rendered_specialists_connect_scope_to_evidence( + installed_target: Path, role: str, obligations: tuple[str, ...] +) -> None: + """Relevant owners retain concrete acceptance and evidence responsibilities.""" + text = " ".join( + (installed_target / ".github" / "agents" / f"{role}.agent.md") + .read_text(encoding="utf-8") + .split() + ) + for obligation in obligations: + assert obligation in text diff --git a/tests/vstack/cli/test_install.py b/tests/vstack/cli/test_install.py index 2ddc0656..7314c832 100644 --- a/tests/vstack/cli/test_install.py +++ b/tests/vstack/cli/test_install.py @@ -8,6 +8,7 @@ import pytest +from tests.conftest import ROOT from vstack.cli.base import CommandContext from vstack.cli.install import InstallCommand from vstack.cli.service import CommandService @@ -443,3 +444,33 @@ def test_run_skips_write_vstack_gitignore_for_global( ) InstallCommand(service=cast(CommandService, object())).run(context=context) assert written == [] + + def test_changedoc_seed_is_additive_and_preserves_local_history(self, tmp_path: Path) -> None: + """New installs get SDD sections; reseeding preserves customized content.""" + templates_root = ROOT / "src" / "vstack" / "_templates" + project_root = tmp_path / "consumer" + colors = SimpleNamespace(YELLOW="", RESET="", BOLD="", DIM="", GREEN="") + InstallCommand._seed_project( + project_root=project_root, + templates_root=templates_root, + colors=colors, + dry_run=False, + ) + local = project_root / ".vstack/templates/product/artifacts/changes/changedoc.md" + text = local.read_text(encoding="utf-8") + for section in ("Requirements", "Acceptance Criteria", "Execution Tasks", "Verification"): + assert f"## {section}" in text + assert "last_modified:" in text + assert "\nid:" not in text + local.write_text("# Customized old template\n", encoding="utf-8") + history = project_root / "docs/changes/old_fix_20260101.md" + history.parent.mkdir(parents=True, exist_ok=True) + history.write_text("status: IMPLEMENTED\nHistorical scope.\n", encoding="utf-8") + InstallCommand._seed_project( + project_root=project_root, + templates_root=templates_root, + colors=colors, + dry_run=False, + ) + assert local.read_text(encoding="utf-8") == "# Customized old template\n" + assert history.read_text(encoding="utf-8") == "status: IMPLEMENTED\nHistorical scope.\n" diff --git a/tests/vstack/instructions/test_generator.py b/tests/vstack/instructions/test_generator.py index 218b30c0..b85d17c3 100644 --- a/tests/vstack/instructions/test_generator.py +++ b/tests/vstack/instructions/test_generator.py @@ -2,6 +2,8 @@ from __future__ import annotations +from pathlib import Path + from vstack.instructions.generator import InstructionGenerator @@ -12,3 +14,17 @@ def test_generator_uses_instruction_type(self) -> None: """Test that generator uses instruction type.""" gen = InstructionGenerator() assert gen.config.type_name == "instruction" + + def test_rendered_testing_policy_links_acceptance_without_workflow( + self, installed_target: Path + ) -> None: + """Always-on policy covers observable boundaries without adding ceremony.""" + text = (installed_target / ".github/instructions/testing.instructions.md").read_text( + encoding="utf-8" + ) + assert "observable acceptance" in text + assert "failure, compatibility, and data/operational boundaries" in text + assert "Code coverage and task checkboxes do not prove acceptance" in text + assert "required failed or unrun checks are not passes" in text + assert "BUILD" not in text + assert "docs/changes/" not in text diff --git a/tests/vstack/skills/test_templates.py b/tests/vstack/skills/test_templates.py index a7c67480..40af7128 100644 --- a/tests/vstack/skills/test_templates.py +++ b/tests/vstack/skills/test_templates.py @@ -5,7 +5,9 @@ import re from pathlib import Path -from tests.conftest import SKILLS_TEMPLATES_DIR +import pytest + +from tests.conftest import ROOT, SKILLS_TEMPLATES_DIR from vstack.cli.constants import EXPECTED_CANONICAL_NAMES from vstack.frontmatter import FrontmatterParser @@ -78,3 +80,129 @@ def test_generated_count_matches_expected(self, generated_dir: Path) -> None: """Test that generated count matches expected.""" md_files = list(generated_dir.glob("*/SKILL.md")) assert len(md_files) == len(EXPECTED_CANONICAL_NAMES) + + +@pytest.mark.parametrize( + ("name", "obligations"), + [ + ( + "changedoc", + ( + "Small, clear, low-risk work", + "Older customized templates remain valid", + "real prerequisites", + "preserve established references", + "Required failed/unrun checks", + "`ARCHIVED`: closed history; never authorizes", + ), + ), + ( + "requirements", + ( + "existing issue or conversation", + "one focused question", + "existing intent source", + "wording review is not proof", + "independently verifiable delivery slices", + ), + ), + ( + "analyse", + ( + "before implementation", + "contradictions", + "uncovered obligations", + "no requirement or engineering rationale", + "Do not silently change intent", + "no mandatory standalone report", + ), + ), + ( + "inspect", + ( + "required behavior absent from the diff", + "unexplained additions", + "evidence gaps", + "only when authorized", + "policy-approved exception", + ), + ), + ( + "verify", + ( + "required behavior absent from the diff", + "Commit only when authorized", + "Stop and report blockers", + "attempts repeat without new evidence", + "do not loop indefinitely or weaken criteria", + "no duplicate reports", + ), + ), + ], +) +def test_rendered_sdd_skills_preserve_key_obligations( + generated_dir: Path, name: str, obligations: tuple[str, ...] +) -> None: + """Rendered procedures retain routing, ownership, and completion safeguards.""" + text = " ".join((generated_dir / name / "SKILL.md").read_text(encoding="utf-8").split()) + for obligation in obligations: + assert obligation in text + assert "{{" not in text + + +@pytest.mark.parametrize("name", ["changedoc", "inspect", "verify"]) +def test_rendered_evidence_states_do_not_hide_missing_checks( + generated_dir: Path, name: str +) -> None: + """Each evidence procedure distinguishes freshness and failed/unrun checks.""" + text = (generated_dir / name / "SKILL.md").read_text(encoding="utf-8") + for state in ("passed", "failed", "not run", "no longer current"): + assert state in text + assert "Required failed/unrun checks" in text + assert "reviewed" in text.lower() + procedure = text.split(f"# {name} ", 1)[1] + assert "2>/dev/null" not in procedure + assert "|| true" not in procedure + + +def test_sdd_guidance_stays_below_prechange_source_and_rendered_size( + installed_target: Path, +) -> None: + """Compact guidance retains contracts without aggregate word or byte growth.""" + source_root = ROOT / "src" / "vstack" / "_templates" + paths = ( + [("skills", name) for name in ("changedoc", "requirements", "analyse", "inspect", "verify")] + + [ + ("agents", name) + for name in ( + "product", + "planner", + "architect", + "designer", + "engineer", + "tester", + "release", + ) + ] + + [("instructions", "testing")] + ) + source_text = "".join( + (source_root / family / name / filename).read_text(encoding="utf-8") + for family, name in paths + for filename in ("template.md", "config.yaml") + ) + (source_root / "agents/product/artifacts/changes/changedoc.md").read_text(encoding="utf-8") + output_paths = [ + Path("skills") / name / "SKILL.md" + if family == "skills" + else Path("agents") / f"{name}.agent.md" + if family == "agents" + else Path("instructions") / f"{name}.instructions.md" + for family, name in paths + ] + rendered_text = "".join( + (installed_target / ".github" / path).read_text(encoding="utf-8") for path in output_paths + ) + assert len(source_text.split()) <= 11483 + assert len(source_text.encode("utf-8")) <= 81847 + assert len(rendered_text.split()) <= 14763 + assert len(rendered_text.encode("utf-8")) <= 105562 From 77c23a89274c76c0ec894bd42b9b88945f52087e Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:37:43 +0100 Subject: [PATCH 03/16] fix(manifest): migrate legacy manifest location safely Detect manifests in the legacy .github location, require explicit migration for other operations, and preserve both files when migration cannot proceed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/vstack/cli/service.py | 34 +++++++-- src/vstack/manifest/store.py | 38 +++++++++- tests/vstack/cli/test_service.py | 116 +++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 7 deletions(-) diff --git a/src/vstack/cli/service.py b/src/vstack/cli/service.py index 394042f1..b5a07895 100644 --- a/src/vstack/cli/service.py +++ b/src/vstack/cli/service.py @@ -23,7 +23,7 @@ from vstack.agents.generator import AgentGenerator from vstack.artifacts.generator import GenericArtifactGenerator from vstack.cli.constants import KNOWN_TYPES, ArtifactState -from vstack.constants import ARTIFACTS_DOCS_ROOT, VSTACK_DIR_NAME +from vstack.constants import ARTIFACTS_DOCS_ROOT, MANIFEST_FILENAME, VSTACK_DIR_NAME from vstack.hooks.config import HOOK_TYPE from vstack.hooks.generator import HookGenerator from vstack.manifest import CURRENT_MANIFEST_VERSION, ManifestFile, hash_with_algorithm @@ -123,7 +123,10 @@ def manifest_for(self, install_dir: Path) -> ManifestFile: ``install_dir`` directly. """ if install_dir.name == ".github": - return ManifestFile(parent_dir=install_dir.parent / VSTACK_DIR_NAME) + return ManifestFile( + parent_dir=install_dir.parent / VSTACK_DIR_NAME, + legacy_path=install_dir / MANIFEST_FILENAME, + ) return ManifestFile(parent_dir=install_dir) def gen_for(self, type_name: str) -> GenericArtifactGenerator | None: @@ -285,7 +288,12 @@ def manifest_upgrade(self, install_dir: Path, *, backfill: bool = False) -> int: return 1 needs_upgrade = manifest_data.needs_upgrade() - if not needs_upgrade and not backfill: + legacy_source = getattr(manifest_file, "legacy_path", None) + location_migration = ( + legacy_source is not None + and getattr(manifest_file, "read_source_path", None) == legacy_source + ) + if not needs_upgrade and not backfill and not location_migration: print(f"Manifest already up to date at schema v{manifest_data.manifest_version}.") return 0 @@ -297,7 +305,25 @@ def manifest_upgrade(self, install_dir: Path, *, backfill: bool = False) -> int: install_dir=install_dir, ) - manifest_file.write(upgraded) + if location_migration: + assert isinstance(legacy_source, Path) + try: + manifest_file.write_new(upgraded) + legacy_source.unlink() + except OSError as exc: + print( + "ERROR: Could not safely migrate the legacy manifest " + f"({exc}). Neither manifest was intentionally overwritten; " + "inspect both files and resolve the conflict before retrying.", + file=sys.stderr, + ) + return 1 + print( + f"Migrated manifest location: {self.label(legacy_source)} → " + f"{self.label(manifest_file.path)}" + ) + else: + manifest_file.write(upgraded) if needs_upgrade: print( diff --git a/src/vstack/manifest/store.py b/src/vstack/manifest/store.py index 12dc914a..df6bb787 100644 --- a/src/vstack/manifest/store.py +++ b/src/vstack/manifest/store.py @@ -304,9 +304,11 @@ def from_dict(cls, data: dict) -> Manifest: class ManifestFile: """Read and write the ``vstack.json`` manifest inside an install root.""" - def __init__(self, parent_dir: Path) -> None: + def __init__(self, parent_dir: Path, *, legacy_path: Path | None = None) -> None: self.path = parent_dir / MANIFEST_FILENAME + self.legacy_path = legacy_path self.read_error: str | None = None + self.read_source_path: Path | None = None def exists(self) -> bool: """Return ``True`` when the manifest file exists on disk.""" @@ -314,11 +316,29 @@ def exists(self) -> bool: def read(self, *, allow_legacy: bool = False) -> Manifest | None: """Parse the manifest file from disk.""" - if not self.path.exists(): + self.read_source_path = None + legacy_exists = self.legacy_path is not None and self.legacy_path.exists() + if legacy_exists and self.path.exists(): + self.read_error = ( + "Conflicting manifests found at " + f"{self.path} and {self.legacy_path}. " + "Resolve the conflict manually before running vstack commands." + ) + return None + if legacy_exists and not allow_legacy: + self.read_error = ( + f"Legacy manifest location detected at {self.legacy_path}. " + "Run: vstack manifest upgrade --target <project-root>." + ) + return None + + source_path = self.legacy_path if legacy_exists else self.path + if source_path is None or not source_path.exists(): self.read_error = None return None + self.read_source_path = source_path try: - data = json.loads(self.path.read_text(encoding="utf-8")) + data = json.loads(source_path.read_text(encoding="utf-8")) manifest = Manifest.from_dict(data) if manifest.needs_upgrade() and not allow_legacy: self.read_error = ( @@ -331,6 +351,7 @@ def read(self, *, allow_legacy: bool = False) -> Manifest | None: return manifest except (json.JSONDecodeError, KeyError, TypeError, ValueError): self.read_error = "Invalid manifest format in vstack.json" + self.read_source_path = None return None def write(self, manifest: Manifest) -> None: @@ -347,3 +368,14 @@ def write(self, manifest: Manifest) -> None: encoding="utf-8", ) os.replace(tmp_path, self.path) + + def write_new(self, manifest: Manifest) -> None: + """Create a manifest only when the destination does not already exist. + + This is used for location migration so an existing current manifest is + never replaced by data from the legacy location. + """ + self.path.parent.mkdir(parents=True, exist_ok=True) + with self.path.open("x", encoding="utf-8") as manifest_file: + json.dump(manifest.to_dict(), manifest_file, indent=2, ensure_ascii=False) + manifest_file.write("\n") diff --git a/tests/vstack/cli/test_service.py b/tests/vstack/cli/test_service.py index 408d08b6..e8abff69 100644 --- a/tests/vstack/cli/test_service.py +++ b/tests/vstack/cli/test_service.py @@ -41,6 +41,7 @@ def test_manifest_for_dot_github_redirects_to_dot_vstack(self, tmp_path: Path) - install_dir = tmp_path / ".github" mf = svc.manifest_for(install_dir) assert mf.path == tmp_path / ".vstack" / "vstack.json" + assert mf.legacy_path == install_dir / "vstack.json" def test_manifest_for_non_github_dir_uses_install_dir(self, tmp_path: Path) -> None: """manifest_for() places the manifest directly in install_dir for non-.github dirs.""" @@ -1156,6 +1157,121 @@ def test_manifest_upgrade_migrates_legacy_schema(self, tmp_path: Path) -> None: assert upgraded["manifest_version"] == 2 assert upgraded["hash_algorithm"] == "sha256" + def test_manifest_upgrade_moves_legacy_location_without_overwriting( + self, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ) -> None: + """manifest upgrade moves a legacy-location manifest into .vstack.""" + install_dir = tmp_path / ".github" + install_dir.mkdir() + legacy_path = install_dir / "vstack.json" + legacy_path.write_text( + json.dumps( + { + "manifest_version": 2, + "hash_algorithm": "sha256", + "vstack_version": "3.0.0", + "installed_at": "2026-01-01T00:00:00Z", + "artifacts": {}, + } + ), + encoding="utf-8", + ) + + service = CommandService(templates_root=TEMPLATES_ROOT) + assert service.manifest_upgrade(install_dir) == 0 + + current_path = tmp_path / ".vstack" / "vstack.json" + assert json.loads(current_path.read_text(encoding="utf-8"))["vstack_version"] == "3.0.0" + assert not legacy_path.exists() + assert "Migrated manifest location" in capsys.readouterr().out + + def test_manifest_upgrade_refuses_conflicting_locations( + self, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ) -> None: + """manifest upgrade preserves both files when both locations exist.""" + install_dir = tmp_path / ".github" + install_dir.mkdir() + current_dir = tmp_path / ".vstack" + current_dir.mkdir() + legacy_path = install_dir / "vstack.json" + current_path = current_dir / "vstack.json" + legacy_content = '{"vstack_version":"legacy"}\n' + current_content = '{"vstack_version":"current"}\n' + legacy_path.write_text(legacy_content, encoding="utf-8") + current_path.write_text(current_content, encoding="utf-8") + + service = CommandService(templates_root=TEMPLATES_ROOT) + assert service.manifest_upgrade(install_dir) == 1 + + assert legacy_path.read_text(encoding="utf-8") == legacy_content + assert current_path.read_text(encoding="utf-8") == current_content + assert "Conflicting manifests" in capsys.readouterr().err + + def test_manifest_upgrade_preserves_legacy_source_when_destination_write_fails( + self, + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ) -> None: + """A failed location migration leaves the legacy manifest available.""" + install_dir = tmp_path / ".github" + install_dir.mkdir() + legacy_path = install_dir / "vstack.json" + legacy_content = json.dumps( + { + "manifest_version": 2, + "hash_algorithm": "sha256", + "vstack_version": "3.0.0", + "installed_at": "2026-01-01T00:00:00Z", + "artifacts": {}, + } + ) + legacy_path.write_text(legacy_content, encoding="utf-8") + + def _fail_write_new(_manifest_file, _manifest) -> None: + raise OSError("destination unavailable") + + monkeypatch.setattr("vstack.manifest.store.ManifestFile.write_new", _fail_write_new) + service = CommandService(templates_root=TEMPLATES_ROOT) + assert service.manifest_upgrade(install_dir) == 1 + + assert legacy_path.read_text(encoding="utf-8") == legacy_content + assert not (tmp_path / ".vstack" / "vstack.json").exists() + assert "Could not safely migrate" in capsys.readouterr().err + + def test_install_fails_fast_for_legacy_manifest_location( + self, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ) -> None: + """Install directs users to manifest upgrade instead of losing tracking.""" + install_dir = tmp_path / ".github" + install_dir.mkdir() + legacy_path = install_dir / "vstack.json" + legacy_path.write_text( + json.dumps( + { + "manifest_version": 2, + "hash_algorithm": "sha256", + "vstack_version": "3.0.0", + "installed_at": "2026-01-01T00:00:00Z", + "artifacts": {}, + } + ), + encoding="utf-8", + ) + + service = CommandService(templates_root=TEMPLATES_ROOT) + assert service.install(install_dir, only=["skill"]) == 1 + + assert legacy_path.exists() + assert not (tmp_path / ".vstack" / "vstack.json").exists() + assert "vstack manifest upgrade" in capsys.readouterr().err + def test_manifest_upgrade_backfill_adds_checksum_for_footer_tagged_legacy_entry( self, tmp_path: Path, From 2362b62e891b08d6727af7e82da154ae7b440ed2 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:38:02 +0100 Subject: [PATCH 04/16] fix(manifest): preserve legacy MD5 digests on upgrade Infer 32-character legacy checksums as MD5 before manifest schema migration changes the top-level default to SHA-256. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/vstack/manifest/store.py | 2 ++ tests/vstack/manifest/test_store.py | 30 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/vstack/manifest/store.py b/src/vstack/manifest/store.py index df6bb787..2656c51c 100644 --- a/src/vstack/manifest/store.py +++ b/src/vstack/manifest/store.py @@ -96,6 +96,8 @@ def _infer_algorithm( if isinstance(checksum, str): if len(checksum) == 64: return CURRENT_HASH_ALGORITHM + if len(checksum) == 32: + return "md5" if ( manifest_version >= CURRENT_MANIFEST_VERSION and fallback_algorithm == CURRENT_HASH_ALGORITHM diff --git a/tests/vstack/manifest/test_store.py b/tests/vstack/manifest/test_store.py index 0449d2f0..58ffcbef 100644 --- a/tests/vstack/manifest/test_store.py +++ b/tests/vstack/manifest/test_store.py @@ -176,6 +176,36 @@ def test_upgraded_normalizes_manifest_metadata(self) -> None: assert upgraded.hash_algorithm == CURRENT_HASH_ALGORITHM assert upgraded.entries_for("skills")[0].checksum_algorithm == "sha256" + def test_upgraded_preserves_legacy_md5_digest_algorithm(self) -> None: + """A 32-character legacy digest remains MD5 after schema upgrade.""" + content = "legacy artifact content" + legacy_checksum = hash_with_algorithm(content, "md5") + legacy = Manifest.from_dict( + { + "manifest_version": 1, + "hash_algorithm": "md5", + "vstack_version": "0.1.0", + "installed_at": "2026-01-01T00:00:00Z", + "artifacts": { + "skills": [ + { + "name": "vision", + "file": "skills/vision/SKILL.md", + "checksum": legacy_checksum, + } + ] + }, + } + ) + + upgraded = legacy.upgraded() + entry = upgraded.entries_for("skills")[0] + + assert upgraded.hash_algorithm == "sha256" + assert entry.checksum == legacy_checksum + assert entry.checksum_algorithm == "md5" + assert hash_with_algorithm(content, entry.checksum_algorithm) == entry.checksum + def test_upgraded_is_idempotent(self) -> None: """Test that upgrading twice results in the same serialized manifest.""" manifest = Manifest.from_dict( From 397b3cf33359c4ff08a24bd6a7d869b22e3ca697 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:38:41 +0100 Subject: [PATCH 05/16] fix(workflow): reject malformed stage entries Fail fast with indexed validation errors when workflow stages are not mappings or have missing, non-string, or empty roles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/vstack/cli/interface.py | 64 +++++++++++++++++------------- tests/vstack/cli/test_interface.py | 41 ++++++++++++++++--- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/vstack/cli/interface.py b/src/vstack/cli/interface.py index 25e29469..06440709 100644 --- a/src/vstack/cli/interface.py +++ b/src/vstack/cli/interface.py @@ -194,7 +194,7 @@ def _read_workflow_stages(install_dir: Path | None) -> list[dict]: Returns an empty list when *install_dir* is ``None``, when the config file does not exist, or when the ``workflow:`` block is absent or - contains no valid stages. + contains no stages. Each returned dict has at minimum a ``role`` key. Optional keys are ``gate``, ``hitl``, ``depends_on``, and ``handoffs`` (a list of handoff @@ -216,35 +216,45 @@ def _read_workflow_stages(install_dir: Path | None) -> list[dict]: return [] result: list[dict] = [] for stage_index, item in enumerate(stages_raw): - if isinstance(item, dict) and isinstance(item.get("role"), str): - handoffs = CommandLineInterface._parse_stage_handoffs(item) - normalized_role = item["role"].strip() - stage: dict = { - "role": normalized_role, - "gate": str(item.get("gate", "required")), - "handoffs": handoffs, - } - if "hitl" in item: - stage["hitl"] = str(item["hitl"]) - if "depends_on" in item: - raw_depends_on = item.get("depends_on", []) - if not isinstance(raw_depends_on, list): + if not isinstance(item, dict): + raise ValueError( + f"Invalid workflow config: workflow.stages[{stage_index}] must be a mapping" + ) + raw_role = item.get("role") + if not isinstance(raw_role, str) or not raw_role.strip(): + raise ValueError( + "Invalid workflow config: " + f"workflow.stages[{stage_index}].role must be a non-empty string" + ) + + handoffs = CommandLineInterface._parse_stage_handoffs(item) + normalized_role = raw_role.strip() + stage: dict = { + "role": normalized_role, + "gate": str(item.get("gate", "required")), + "handoffs": handoffs, + } + if "hitl" in item: + stage["hitl"] = str(item["hitl"]) + if "depends_on" in item: + raw_depends_on = item.get("depends_on", []) + if not isinstance(raw_depends_on, list): + raise ValueError( + "Invalid workflow config: " + f"workflow.stages[{stage_index}].depends_on must be a list" + ) + depends_on: list[str] = [] + for dep_index, dep in enumerate(raw_depends_on): + if not isinstance(dep, str): raise ValueError( "Invalid workflow config: " - f"workflow.stages[{stage_index}].depends_on must be a list" + f"workflow.stages[{stage_index}].depends_on[{dep_index}] must be a string" ) - depends_on: list[str] = [] - for dep_index, dep in enumerate(raw_depends_on): - if not isinstance(dep, str): - raise ValueError( - "Invalid workflow config: " - f"workflow.stages[{stage_index}].depends_on[{dep_index}] must be a string" - ) - dep_name = dep.strip() - if dep_name and dep_name not in depends_on: - depends_on.append(dep_name) - stage["depends_on"] = depends_on - result.append(stage) + dep_name = dep.strip() + if dep_name and dep_name not in depends_on: + depends_on.append(dep_name) + stage["depends_on"] = depends_on + result.append(stage) CommandLineInterface._validate_workflow_stages(result) return result diff --git a/tests/vstack/cli/test_interface.py b/tests/vstack/cli/test_interface.py index 9343a43c..d0069aa6 100644 --- a/tests/vstack/cli/test_interface.py +++ b/tests/vstack/cli/test_interface.py @@ -414,16 +414,45 @@ def test_preserves_hitl_field(self, tmp_path: Path) -> None: }, ] - def test_skips_items_without_role(self, tmp_path: Path) -> None: - """Items lacking a string 'role' key are silently skipped.""" + def test_rejects_stage_without_role(self, tmp_path: Path) -> None: + """A stage without a role raises an actionable workflow validation error.""" vstack_dir = tmp_path / ".vstack" vstack_dir.mkdir() (vstack_dir / "config.yaml").write_text( "workflow:\n stages:\n - gate: required\n - role: engineer\n", encoding="utf-8", ) - result = CommandLineInterface._read_workflow_stages(tmp_path / ".github") - assert result == [{"role": "engineer", "gate": "required", "handoffs": []}] + with pytest.raises( + ValueError, + match=r"Invalid workflow config: workflow\.stages\[0\]\.role must be a non-empty string", + ): + CommandLineInterface._read_workflow_stages(tmp_path / ".github") + + @pytest.mark.parametrize( + ("stage", "error_path"), + [ + ("not-a-mapping", r"workflow\.stages\[0\] must be a mapping"), + ("role: 12", r"workflow\.stages\[0\]\.role must be a non-empty string"), + ("role: ''", r"workflow\.stages\[0\]\.role must be a non-empty string"), + ("role: ' '", r"workflow\.stages\[0\]\.role must be a non-empty string"), + ], + ) + def test_rejects_malformed_workflow_stages( + self, + tmp_path: Path, + stage: str, + error_path: str, + ) -> None: + """Non-mapping stages and invalid roles fail instead of being dropped.""" + vstack_dir = tmp_path / ".vstack" + vstack_dir.mkdir() + (vstack_dir / "config.yaml").write_text( + f"workflow:\n stages:\n - {stage}\n", + encoding="utf-8", + ) + + with pytest.raises(ValueError, match=f"Invalid workflow config: {error_path}"): + CommandLineInterface._read_workflow_stages(tmp_path / ".github") def test_returns_empty_when_stages_not_a_list(self, tmp_path: Path) -> None: """Returns empty list when workflow.stages is not a list.""" @@ -578,13 +607,13 @@ def test_raises_when_depends_on_references_unknown_stage(self, tmp_path: Path) - CommandLineInterface._read_workflow_stages(tmp_path / ".github") def test_depends_on_error_reports_raw_yaml_stage_index(self, tmp_path: Path) -> None: - """depends_on shape errors use the YAML stage position even when earlier stages are skipped.""" + """depends_on errors identify their position in workflow.stages.""" vstack_dir = tmp_path / ".vstack" vstack_dir.mkdir() (vstack_dir / "config.yaml").write_text( "workflow:\n" " stages:\n" - " - role: 123\n" + " - role: designer\n" " - role: engineer\n" " depends_on: product\n", encoding="utf-8", From 6dccbaa1451e55bc7a3cb214bda3e9eeb764dc25 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:38:59 +0100 Subject: [PATCH 06/16] fix(manifest): reject non-object JSON roots Validate the decoded manifest root before model conversion so arrays, null values, and other JSON scalars become the standard read error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/vstack/manifest/store.py | 2 ++ tests/vstack/cli/test_service.py | 15 +++++++++++++++ tests/vstack/manifest/test_store.py | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/src/vstack/manifest/store.py b/src/vstack/manifest/store.py index 2656c51c..3ddd8e0c 100644 --- a/src/vstack/manifest/store.py +++ b/src/vstack/manifest/store.py @@ -341,6 +341,8 @@ def read(self, *, allow_legacy: bool = False) -> Manifest | None: self.read_source_path = source_path try: data = json.loads(source_path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise ValueError("manifest root must be a JSON object") manifest = Manifest.from_dict(data) if manifest.needs_upgrade() and not allow_legacy: self.read_error = ( diff --git a/tests/vstack/cli/test_service.py b/tests/vstack/cli/test_service.py index e8abff69..0f639b0f 100644 --- a/tests/vstack/cli/test_service.py +++ b/tests/vstack/cli/test_service.py @@ -1028,6 +1028,21 @@ def read(self, *, allow_legacy: bool = False): assert svc.manifest_upgrade(tmp_path) == 1 assert "No manifest found to upgrade." in capsys.readouterr().out + def test_manifest_upgrade_reports_non_object_json_without_traceback( + self, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + ) -> None: + """Malformed JSON root values become the standard manifest read error.""" + (tmp_path / "vstack.json").write_text("null", encoding="utf-8") + + service = CommandService(templates_root=tmp_path) + assert service.manifest_upgrade(tmp_path) == 1 + + captured = capsys.readouterr() + assert "ERROR: Invalid manifest format in vstack.json" in captured.err + assert "Traceback" not in captured.err + def test_manifest_upgrade_noop_when_current_schema( self, monkeypatch: pytest.MonkeyPatch, diff --git a/tests/vstack/manifest/test_store.py b/tests/vstack/manifest/test_store.py index 58ffcbef..3d5d5cf6 100644 --- a/tests/vstack/manifest/test_store.py +++ b/tests/vstack/manifest/test_store.py @@ -503,6 +503,15 @@ def test_read_none_when_missing(self, tmp_path) -> None: assert mf.read() is None assert mf.read_error is None + @pytest.mark.parametrize("root_value", [[], None, "manifest", 42]) + def test_read_rejects_non_object_json_root(self, tmp_path, root_value) -> None: + """Non-object JSON roots are reported as invalid manifest data.""" + mf = ManifestFile(parent_dir=tmp_path) + mf.path.write_text(json.dumps(root_value), encoding="utf-8") + + assert mf.read() is None + assert mf.read_error == "Invalid manifest format in vstack.json" + def test_write_and_read_manifest(self, tmp_path) -> None: """Test that write and read manifest.""" mf = ManifestFile(parent_dir=tmp_path) From 5f1f56e62f7ad3a4ffa6978be41b64e563ed37ca Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:40:23 +0100 Subject: [PATCH 07/16] fix(performance): isolate baseline benchmarks from user Git state Compare against a detached worktree instead of stashing or switching the user's branch. Exercise clean, staged, unstaged and untracked states with an existing stash on benchmark success and failure. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/performance/SKILL.md | 31 +- .vstack/vstack.json | 382 +++++++++--------- docs/design/skills.md | 7 + .../_templates/skills/performance/config.yaml | 2 +- .../_templates/skills/performance/template.md | 29 +- tests/vstack/skills/test_shell_workflows.py | 86 ++++ 6 files changed, 324 insertions(+), 213 deletions(-) create mode 100644 tests/vstack/skills/test_shell_workflows.py diff --git a/.github/skills/performance/SKILL.md b/.github/skills/performance/SKILL.md index 7688e60b..3e41e787 100644 --- a/.github/skills/performance/SKILL.md +++ b/.github/skills/performance/SKILL.md @@ -122,18 +122,27 @@ fi ## Phase 2: Comparison vs Base Branch ```bash -# Stash current changes and benchmark base -git stash -git checkout <base> - -echo "=== Benchmarks on <base> ===" -# [run same benchmark commands as Phase 1] - -# Restore feature branch -git checkout "$CURRENT" -git stash pop +BASE_REF="<base>" +BASE_DIR=$(mktemp -d) || exit 1 +git worktree add --detach "$BASE_DIR/baseline" "$BASE_REF" || exit 1 +( + cd "$BASE_DIR/baseline" || exit 1 + run_benchmark +) +BASE_STATUS=$? +git worktree remove "$BASE_DIR/baseline" || exit 1 +rmdir "$BASE_DIR" || exit 1 +if [ "$BASE_STATUS" -ne 0 ]; then + echo "ERROR: baseline benchmark failed ($BASE_STATUS)" + exit "$BASE_STATUS" +fi ``` +Use an isolated worktree; never stash or switch the user's working tree. +Use `run_benchmark` for the same selected command as Phase 1. +If benchmarks leave files behind, report the worktree path and inspect them +before cleanup. Do not force-remove it or discard user files. + Compare results: - p50 latency change @@ -242,4 +251,4 @@ For each bottleneck identified: ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20260421022","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20261026002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index 20d887a5..c5b3e8a9 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,8 +2,196 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T19:52:12.809254+00:00", + "installed_at": "2026-10-26T20:40:15.425216+00:00", "artifacts": { + "agents": [ + { + "name": "architect", + "file": "agents/architect.agent.md", + "version": "20261026001", + "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", + "checksum_algorithm": "sha256" + }, + { + "name": "designer", + "file": "agents/designer.agent.md", + "version": "20261026001", + "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", + "checksum_algorithm": "sha256" + }, + { + "name": "engineer", + "file": "agents/engineer.agent.md", + "version": "20261026001", + "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", + "checksum_algorithm": "sha256" + }, + { + "name": "planner", + "file": "agents/planner.agent.md", + "version": "20261026001", + "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", + "checksum_algorithm": "sha256" + }, + { + "name": "product", + "file": "agents/product.agent.md", + "version": "20261026001", + "checksum": "55b959b8f6d6b4f933776b27d3dbd453a635afca1944a3605df09ff47175d992", + "checksum_algorithm": "sha256" + }, + { + "name": "release", + "file": "agents/release.agent.md", + "version": "20261026001", + "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", + "checksum_algorithm": "sha256" + }, + { + "name": "tester", + "file": "agents/tester.agent.md", + "version": "20261026001", + "checksum": "53d022b0253dfdfcbcf6c4e0f86ba6649e0b91d3635b9e9fd2b56a18fe34f945", + "checksum_algorithm": "sha256" + } + ], + "hooks": [ + { + "name": "agent-call-audit", + "file": "hooks/agent-call-audit.json", + "version": "4.0.0", + "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", + "checksum_algorithm": "sha256" + }, + { + "name": "log-retention-cleanup", + "file": "hooks/log-retention-cleanup.json", + "version": "4.0.0", + "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", + "checksum_algorithm": "sha256" + }, + { + "name": "post-commit-security-scan", + "file": "hooks/post-commit-security-scan.json", + "version": "4.0.0", + "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", + "checksum_algorithm": "sha256" + }, + { + "name": "post-edit-format", + "file": "hooks/post-edit-format.json", + "version": "4.0.0", + "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", + "checksum_algorithm": "sha256" + }, + { + "name": "post-edit-markdown-quality", + "file": "hooks/post-edit-markdown-quality.json", + "version": "4.0.0", + "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", + "checksum_algorithm": "sha256" + }, + { + "name": "pre-tool-safety-gate", + "file": "hooks/pre-tool-safety-gate.json", + "version": "4.0.0", + "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", + "checksum_algorithm": "sha256" + }, + { + "name": "session-audit", + "file": "hooks/session-audit.json", + "version": "4.0.0", + "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", + "checksum_algorithm": "sha256" + } + ], + "instructions": [ + { + "name": "git", + "file": "instructions/git.instructions.md", + "version": "20260421001", + "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", + "checksum_algorithm": "sha256" + }, + { + "name": "helm", + "file": "instructions/helm.instructions.md", + "version": "20260502040", + "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", + "checksum_algorithm": "sha256" + }, + { + "name": "java", + "file": "instructions/java.instructions.md", + "version": "20260502001", + "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", + "checksum_algorithm": "sha256" + }, + { + "name": "k8s", + "file": "instructions/k8s.instructions.md", + "version": "20260502039", + "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", + "checksum_algorithm": "sha256" + }, + { + "name": "markdown", + "file": "instructions/markdown.instructions.md", + "version": "20260502002", + "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", + "checksum_algorithm": "sha256" + }, + { + "name": "python", + "file": "instructions/python.instructions.md", + "version": "20260421002", + "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", + "checksum_algorithm": "sha256" + }, + { + "name": "rancher", + "file": "instructions/rancher.instructions.md", + "version": "20260502041", + "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", + "checksum_algorithm": "sha256" + }, + { + "name": "security", + "file": "instructions/security.instructions.md", + "version": "20260502003", + "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", + "checksum_algorithm": "sha256" + }, + { + "name": "terraform", + "file": "instructions/terraform.instructions.md", + "version": "20260502034", + "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", + "checksum_algorithm": "sha256" + }, + { + "name": "terragrunt", + "file": "instructions/terragrunt.instructions.md", + "version": "20260502035", + "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", + "checksum_algorithm": "sha256" + }, + { + "name": "testing", + "file": "instructions/testing.instructions.md", + "version": "20261026001", + "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", + "checksum_algorithm": "sha256" + }, + { + "name": "typescript", + "file": "instructions/typescript.instructions.md", + "version": "20260502005", + "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", + "checksum_algorithm": "sha256" + } + ], "skills": [ { "name": "adr", @@ -253,8 +441,8 @@ { "name": "performance", "file": "skills/performance/SKILL.md", - "version": "20260421022", - "checksum": "75a4460e5c53c7f4b55b8413ca9c1cccfaa82e550770f9c5d3bb4d712d89ac0d", + "version": "20261026002", + "checksum": "0b621c3158f9dabc6b9a57df37c71348bcc11ad9a833623ab4e89ed4a8feaaa7", "checksum_algorithm": "sha256" }, { @@ -397,194 +585,6 @@ "checksum": "f8066d6f685418671992a75e103b96ce9b18bb0622c656c49ab93d3a382a69fb", "checksum_algorithm": "sha256" } - ], - "agents": [ - { - "name": "architect", - "file": "agents/architect.agent.md", - "version": "20261026001", - "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", - "checksum_algorithm": "sha256" - }, - { - "name": "designer", - "file": "agents/designer.agent.md", - "version": "20261026001", - "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", - "checksum_algorithm": "sha256" - }, - { - "name": "engineer", - "file": "agents/engineer.agent.md", - "version": "20261026001", - "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", - "checksum_algorithm": "sha256" - }, - { - "name": "planner", - "file": "agents/planner.agent.md", - "version": "20261026001", - "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", - "checksum_algorithm": "sha256" - }, - { - "name": "product", - "file": "agents/product.agent.md", - "version": "20261026001", - "checksum": "55b959b8f6d6b4f933776b27d3dbd453a635afca1944a3605df09ff47175d992", - "checksum_algorithm": "sha256" - }, - { - "name": "release", - "file": "agents/release.agent.md", - "version": "20261026001", - "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", - "checksum_algorithm": "sha256" - }, - { - "name": "tester", - "file": "agents/tester.agent.md", - "version": "20261026001", - "checksum": "53d022b0253dfdfcbcf6c4e0f86ba6649e0b91d3635b9e9fd2b56a18fe34f945", - "checksum_algorithm": "sha256" - } - ], - "hooks": [ - { - "name": "agent-call-audit", - "file": "hooks/agent-call-audit.json", - "version": "4.0.0", - "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", - "checksum_algorithm": "sha256" - }, - { - "name": "log-retention-cleanup", - "file": "hooks/log-retention-cleanup.json", - "version": "4.0.0", - "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", - "checksum_algorithm": "sha256" - }, - { - "name": "post-commit-security-scan", - "file": "hooks/post-commit-security-scan.json", - "version": "4.0.0", - "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", - "checksum_algorithm": "sha256" - }, - { - "name": "post-edit-format", - "file": "hooks/post-edit-format.json", - "version": "4.0.0", - "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", - "checksum_algorithm": "sha256" - }, - { - "name": "post-edit-markdown-quality", - "file": "hooks/post-edit-markdown-quality.json", - "version": "4.0.0", - "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", - "checksum_algorithm": "sha256" - }, - { - "name": "pre-tool-safety-gate", - "file": "hooks/pre-tool-safety-gate.json", - "version": "4.0.0", - "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", - "checksum_algorithm": "sha256" - }, - { - "name": "session-audit", - "file": "hooks/session-audit.json", - "version": "4.0.0", - "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", - "checksum_algorithm": "sha256" - } - ], - "instructions": [ - { - "name": "git", - "file": "instructions/git.instructions.md", - "version": "20260421001", - "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", - "checksum_algorithm": "sha256" - }, - { - "name": "helm", - "file": "instructions/helm.instructions.md", - "version": "20260502040", - "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", - "checksum_algorithm": "sha256" - }, - { - "name": "java", - "file": "instructions/java.instructions.md", - "version": "20260502001", - "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", - "checksum_algorithm": "sha256" - }, - { - "name": "k8s", - "file": "instructions/k8s.instructions.md", - "version": "20260502039", - "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", - "checksum_algorithm": "sha256" - }, - { - "name": "markdown", - "file": "instructions/markdown.instructions.md", - "version": "20260502002", - "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", - "checksum_algorithm": "sha256" - }, - { - "name": "python", - "file": "instructions/python.instructions.md", - "version": "20260421002", - "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", - "checksum_algorithm": "sha256" - }, - { - "name": "rancher", - "file": "instructions/rancher.instructions.md", - "version": "20260502041", - "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", - "checksum_algorithm": "sha256" - }, - { - "name": "security", - "file": "instructions/security.instructions.md", - "version": "20260502003", - "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", - "checksum_algorithm": "sha256" - }, - { - "name": "terraform", - "file": "instructions/terraform.instructions.md", - "version": "20260502034", - "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", - "checksum_algorithm": "sha256" - }, - { - "name": "terragrunt", - "file": "instructions/terragrunt.instructions.md", - "version": "20260502035", - "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", - "checksum_algorithm": "sha256" - }, - { - "name": "testing", - "file": "instructions/testing.instructions.md", - "version": "20261026001", - "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", - "checksum_algorithm": "sha256" - }, - { - "name": "typescript", - "file": "instructions/typescript.instructions.md", - "version": "20260502005", - "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", - "checksum_algorithm": "sha256" - } ] } } diff --git a/docs/design/skills.md b/docs/design/skills.md index 7417ef68..c4aa3e40 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -148,6 +148,13 @@ Keep source and rendered guidance concrete and compact: replace repetition, reference existing evidence, and do not remove safety or contract obligations. See [ADR-033](../architecture/adr/033-lightweight-sdd.md). +### performance comparison safety + +`performance` benchmarks the base revision in a detached temporary worktree. +It preserves the user's branch, index, working files, and existing stashes. +Failed benchmarks remain failures; leftover benchmark files require inspection +before cleanup, never forced removal. + ______________________________________________________________________ ## file locations diff --git a/src/vstack/_templates/skills/performance/config.yaml b/src/vstack/_templates/skills/performance/config.yaml index de8e98c7..2c32f4f6 100644 --- a/src/vstack/_templates/skills/performance/config.yaml +++ b/src/vstack/_templates/skills/performance/config.yaml @@ -1,5 +1,5 @@ name: performance -version: 20260421022 +version: 20261026002 description: | Performance profiling and regression detection. Establishes baselines, detects regressions, profiles bottlenecks, and recommends optimizations. Use when asked diff --git a/src/vstack/_templates/skills/performance/template.md b/src/vstack/_templates/skills/performance/template.md index 8239c44e..33f49a89 100644 --- a/src/vstack/_templates/skills/performance/template.md +++ b/src/vstack/_templates/skills/performance/template.md @@ -61,18 +61,27 @@ echo "=== Benchmarks on $CURRENT ===" ## Phase 2: Comparison vs Base Branch ```bash -# Stash current changes and benchmark base -git stash -git checkout <base> - -echo "=== Benchmarks on <base> ===" -# [run same benchmark commands as Phase 1] - -# Restore feature branch -git checkout "$CURRENT" -git stash pop +BASE_REF="<base>" +BASE_DIR=$(mktemp -d) || exit 1 +git worktree add --detach "$BASE_DIR/baseline" "$BASE_REF" || exit 1 +( + cd "$BASE_DIR/baseline" || exit 1 + run_benchmark +) +BASE_STATUS=$? +git worktree remove "$BASE_DIR/baseline" || exit 1 +rmdir "$BASE_DIR" || exit 1 +if [ "$BASE_STATUS" -ne 0 ]; then + echo "ERROR: baseline benchmark failed ($BASE_STATUS)" + exit "$BASE_STATUS" +fi ``` +Use an isolated worktree; never stash or switch the user's working tree. +Use `run_benchmark` for the same selected command as Phase 1. +If benchmarks leave files behind, report the worktree path and inspect them +before cleanup. Do not force-remove it or discard user files. + Compare results: - p50 latency change diff --git a/tests/vstack/skills/test_shell_workflows.py b/tests/vstack/skills/test_shell_workflows.py new file mode 100644 index 00000000..76c52cbd --- /dev/null +++ b/tests/vstack/skills/test_shell_workflows.py @@ -0,0 +1,86 @@ +"""Exercise executable skill recipes without touching the user's repository.""" + +from __future__ import annotations + +import os +import re +import subprocess +from pathlib import Path + +import pytest + + +def _git(repo: Path, *args: str) -> str: + """Run Git in an isolated fixture repository.""" + result = subprocess.run(["git", *args], cwd=repo, capture_output=True, text=True, check=True) + return result.stdout.strip() + + +def _bash_block(text: str, heading: str) -> str: + """Extract the first shell recipe following a known section heading.""" + section = text.split(heading, 1)[1] + match = re.search(r"```bash\n(.*?)```", section, re.DOTALL) + assert match is not None + return match.group(1) + + +@pytest.mark.parametrize("state", ["clean", "unstaged", "staged", "untracked"]) +@pytest.mark.parametrize("benchmark_status", [0, 9]) +def test_performance_baseline_preserves_user_git_state( + tmp_path: Path, generated_dir: Path, state: str, benchmark_status: int +) -> None: + """Baseline success and failure leave branches, index, files and stashes intact.""" + repo = tmp_path / "user project" + repo.mkdir() + _git(repo, "init", "-b", "main") + _git(repo, "config", "user.email", "fixture@example.invalid") + _git(repo, "config", "user.name", "Fixture") + tracked = repo / "tracked.txt" + tracked.write_text("base\n", encoding="utf-8") + _git(repo, "add", "tracked.txt") + _git(repo, "commit", "-m", "base") + tracked.write_text("older unrelated work\n", encoding="utf-8") + _git(repo, "stash", "push", "-m", "unrelated stash") + _git(repo, "switch", "-c", "feature/benchmark") + tracked.write_text("feature\n", encoding="utf-8") + _git(repo, "commit", "-am", "feature") + if state in {"unstaged", "staged"}: + tracked.write_text("user changes\n", encoding="utf-8") + if state == "staged": + _git(repo, "add", "tracked.txt") + if state == "untracked": + (repo / "user.txt").write_text("keep me\n", encoding="utf-8") + before = ( + _git(repo, "status", "--porcelain"), + _git(repo, "rev-parse", "HEAD"), + _git(repo, "symbolic-ref", "HEAD"), + _git(repo, "stash", "list", "--format=%H"), + _git(repo, "diff", "--cached"), + tracked.read_text(encoding="utf-8"), + ) + text = (generated_dir / "performance" / "SKILL.md").read_text(encoding="utf-8") + script = _bash_block(text, "## Phase 2:") + script = script.replace('BASE_REF="<base>"', 'BASE_REF="main"').replace( + "run_benchmark", + f'test "$(cat tracked.txt)" = base || exit 99\n exit {benchmark_status}', + ) + result = subprocess.run( + ["bash", "-c", script], + cwd=repo, + env={**os.environ, "TMPDIR": str(tmp_path)}, + capture_output=True, + text=True, + ) + assert result.returncode == benchmark_status, result.stdout + result.stderr + after = ( + _git(repo, "status", "--porcelain"), + _git(repo, "rev-parse", "HEAD"), + _git(repo, "symbolic-ref", "HEAD"), + _git(repo, "stash", "list", "--format=%H"), + _git(repo, "diff", "--cached"), + tracked.read_text(encoding="utf-8"), + ) + assert after == before + assert _git(repo, "worktree", "list", "--porcelain").count("worktree ") == 1 + if state == "untracked": + assert (repo / "user.txt").read_text(encoding="utf-8") == "keep me\n" From 2da88f3da7595a060445b2cfc6febdaff314556b Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:41:06 +0100 Subject: [PATCH 08/16] fix(performance): select native runners and report benchmark failures Remove cross-ecosystem fallbacks and suppressed errors. Distinguish failed or unavailable measurements from performance passes and test runner selection and exit propagation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/performance/SKILL.md | 84 ++++++++----------- .vstack/vstack.json | 6 +- docs/design/skills.md | 4 + .../_templates/skills/performance/config.yaml | 2 +- .../_templates/skills/performance/template.md | 69 ++++++++------- tests/vstack/skills/test_shell_workflows.py | 52 ++++++++++++ 6 files changed, 133 insertions(+), 84 deletions(-) diff --git a/.github/skills/performance/SKILL.md b/.github/skills/performance/SKILL.md index 3e41e787..94b2c594 100644 --- a/.github/skills/performance/SKILL.md +++ b/.github/skills/performance/SKILL.md @@ -74,50 +74,32 @@ optimizations. Measure first; never optimize without evidence. If on a feature branch, record performance metrics before and after the change: -```bash -# Record current branch metrics -CURRENT=$(git branch --show-current) +Inspect repository scripts and installed tooling first. Adapt `run_benchmark` to +one existing benchmark runner and the selected interpreter/package manager. +For monorepos, select the component explicitly. Do not install tools or fall back +to another ecosystem when a command fails. Ordinary tests are not benchmarks. -# Run benchmarks -echo "=== Benchmarks on $CURRENT ===" ```bash -# Detect test runner and run tests -if [ -f package.json ]; then - if grep -q '"vitest"' package.json 2>/dev/null; then - npx vitest run - elif grep -q '"jest"' package.json 2>/dev/null; then - npx jest - elif grep -q '"bun"' package.json 2>/dev/null; then - bun test +run_benchmark() { + if [ -f package.json ]; then + npm run bench + elif [ -f pyproject.toml ] || [ -f setup.py ]; then + python -m pytest --benchmark-only -v + elif [ -f go.mod ]; then + go test -bench=. -benchmem ./... + elif [ -f Cargo.toml ]; then + cargo bench else - npm test + echo "ERROR: no benchmark runner configured for this component" + return 2 fi -elif [ -f pyproject.toml ] || [ -f setup.py ]; then - python -m pytest -v -elif [ -f go.mod ]; then - go test ./... -elif [ -f Cargo.toml ]; then - cargo test -else - echo "No recognized test framework detected." -fi +} +run_benchmark || exit $? ``` -# Language-specific benchmark runners: -# Node/Bun -[ -f package.json ] && npm run bench 2>/dev/null \ - || npx vitest bench 2>/dev/null \ - || npx jest --config jest.bench.config.js 2>/dev/null || true - -# Python -[ -f pyproject.toml ] && python -m pytest --benchmark-only -v 2>/dev/null || true - -# Go -[ -f go.mod ] && go test -bench=. -benchmem ./... 2>/dev/null || true - -# Rust -[ -f Cargo.toml ] && cargo bench 2>/dev/null || true -``` +Record command, revision, workload, measurements, and exit status. +Unavailable tools or missing benchmark configuration mean `not run`, not a pass; +executed checks with nonzero exit status are `failed`. Keep error output visible. ## Phase 2: Comparison vs Base Branch @@ -157,23 +139,26 @@ Compare results: ```bash # Check for load test tools -which k6 2>/dev/null && echo "k6 available" -which hey 2>/dev/null && echo "hey available" -which wrk 2>/dev/null && echo "wrk available" -which ab 2>/dev/null && echo "ab available" +command -v k6 +command -v hey +command -v wrk +command -v ab # Example k6 run (adapt to your endpoint) # k6 run --vus 50 --duration 30s script.js ``` -For API endpoints, run a basic load test: +For API endpoints, choose one installed load-test tool and an approved target. +Do not generate load against production without explicit permission. ```bash -# Using hey (install: go install github.com/rakyll/hey@latest) -hey -n 1000 -c 50 "${SERVICE_URL}/health" 2>/dev/null || true +hey -n 1000 -c 50 "${SERVICE_URL}/health" +``` -# Using wrk (if available) -wrk -t4 -c100 -d30s "${SERVICE_URL}/health" 2>/dev/null || true +Or, when `wrk` is the selected installed tool: + +```bash +wrk -t4 -c100 -d30s "${SERVICE_URL}/health" ``` ## Phase 4: Profiling (if regression found) @@ -247,8 +232,9 @@ For each bottleneck identified: 1. [Change] — [Before: Xms → After: Xms] — [Commit SHA] ### Verdict -[NO REGRESSION / REGRESSION FIXED / REGRESSION NEEDS ATTENTION] +[NO REGRESSION / REGRESSION FIXED / REGRESSION NEEDS ATTENTION / NOT RUN / CHECK FAILED] +Only measured, comparable results support a regression verdict. ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20261026002","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20261026003","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index c5b3e8a9..2a7fcd02 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,7 +2,7 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T20:40:15.425216+00:00", + "installed_at": "2026-10-26T20:41:06.070048+00:00", "artifacts": { "agents": [ { @@ -441,8 +441,8 @@ { "name": "performance", "file": "skills/performance/SKILL.md", - "version": "20261026002", - "checksum": "0b621c3158f9dabc6b9a57df37c71348bcc11ad9a833623ab4e89ed4a8feaaa7", + "version": "20261026003", + "checksum": "040b0be42543cbcd3d1476a41a3cb38c7573c18069ccabd8597d8c5b23bd77a0", "checksum_algorithm": "sha256" }, { diff --git a/docs/design/skills.md b/docs/design/skills.md index c4aa3e40..1522e471 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -154,6 +154,10 @@ See [ADR-033](../architecture/adr/033-lightweight-sdd.md). It preserves the user's branch, index, working files, and existing stashes. Failed benchmarks remain failures; leftover benchmark files require inspection before cleanup, never forced removal. +Select an existing component-native benchmark runner before execution. Missing +tools/configuration are `not run`; nonzero command results are `failed`, with +visible error output. Never substitute another ecosystem or ordinary unit tests +for benchmark evidence. ______________________________________________________________________ diff --git a/src/vstack/_templates/skills/performance/config.yaml b/src/vstack/_templates/skills/performance/config.yaml index 2c32f4f6..b8e3647b 100644 --- a/src/vstack/_templates/skills/performance/config.yaml +++ b/src/vstack/_templates/skills/performance/config.yaml @@ -1,5 +1,5 @@ name: performance -version: 20261026002 +version: 20261026003 description: | Performance profiling and regression detection. Establishes baselines, detects regressions, profiles bottlenecks, and recommends optimizations. Use when asked diff --git a/src/vstack/_templates/skills/performance/template.md b/src/vstack/_templates/skills/performance/template.md index 33f49a89..e53e457b 100644 --- a/src/vstack/_templates/skills/performance/template.md +++ b/src/vstack/_templates/skills/performance/template.md @@ -34,30 +34,33 @@ optimizations. Measure first; never optimize without evidence. If on a feature branch, record performance metrics before and after the change: -```bash -# Record current branch metrics -CURRENT=$(git branch --show-current) - -# Run benchmarks -echo "=== Benchmarks on $CURRENT ===" -{{RUN_TESTS}} - -# Language-specific benchmark runners: -# Node/Bun -[ -f package.json ] && npm run bench 2>/dev/null \ - || npx vitest bench 2>/dev/null \ - || npx jest --config jest.bench.config.js 2>/dev/null || true - -# Python -[ -f pyproject.toml ] && python -m pytest --benchmark-only -v 2>/dev/null || true - -# Go -[ -f go.mod ] && go test -bench=. -benchmem ./... 2>/dev/null || true +Inspect repository scripts and installed tooling first. Adapt `run_benchmark` to +one existing benchmark runner and the selected interpreter/package manager. +For monorepos, select the component explicitly. Do not install tools or fall back +to another ecosystem when a command fails. Ordinary tests are not benchmarks. -# Rust -[ -f Cargo.toml ] && cargo bench 2>/dev/null || true +```bash +run_benchmark() { + if [ -f package.json ]; then + npm run bench + elif [ -f pyproject.toml ] || [ -f setup.py ]; then + python -m pytest --benchmark-only -v + elif [ -f go.mod ]; then + go test -bench=. -benchmem ./... + elif [ -f Cargo.toml ]; then + cargo bench + else + echo "ERROR: no benchmark runner configured for this component" + return 2 + fi +} +run_benchmark || exit $? ``` +Record command, revision, workload, measurements, and exit status. +Unavailable tools or missing benchmark configuration mean `not run`, not a pass; +executed checks with nonzero exit status are `failed`. Keep error output visible. + ## Phase 2: Comparison vs Base Branch ```bash @@ -96,23 +99,26 @@ Compare results: ```bash # Check for load test tools -which k6 2>/dev/null && echo "k6 available" -which hey 2>/dev/null && echo "hey available" -which wrk 2>/dev/null && echo "wrk available" -which ab 2>/dev/null && echo "ab available" +command -v k6 +command -v hey +command -v wrk +command -v ab # Example k6 run (adapt to your endpoint) # k6 run --vus 50 --duration 30s script.js ``` -For API endpoints, run a basic load test: +For API endpoints, choose one installed load-test tool and an approved target. +Do not generate load against production without explicit permission. ```bash -# Using hey (install: go install github.com/rakyll/hey@latest) -hey -n 1000 -c 50 "${SERVICE_URL}/health" 2>/dev/null || true +hey -n 1000 -c 50 "${SERVICE_URL}/health" +``` -# Using wrk (if available) -wrk -t4 -c100 -d30s "${SERVICE_URL}/health" 2>/dev/null || true +Or, when `wrk` is the selected installed tool: + +```bash +wrk -t4 -c100 -d30s "${SERVICE_URL}/health" ``` ## Phase 4: Profiling (if regression found) @@ -186,5 +192,6 @@ For each bottleneck identified: 1. [Change] — [Before: Xms → After: Xms] — [Commit SHA] ### Verdict -[NO REGRESSION / REGRESSION FIXED / REGRESSION NEEDS ATTENTION] +[NO REGRESSION / REGRESSION FIXED / REGRESSION NEEDS ATTENTION / NOT RUN / CHECK FAILED] +Only measured, comparable results support a regression verdict. ``` diff --git a/tests/vstack/skills/test_shell_workflows.py b/tests/vstack/skills/test_shell_workflows.py index 76c52cbd..8e27a9dc 100644 --- a/tests/vstack/skills/test_shell_workflows.py +++ b/tests/vstack/skills/test_shell_workflows.py @@ -84,3 +84,55 @@ def test_performance_baseline_preserves_user_git_state( assert _git(repo, "worktree", "list", "--porcelain").count("worktree ") == 1 if state == "untracked": assert (repo / "user.txt").read_text(encoding="utf-8") == "keep me\n" + + +@pytest.mark.parametrize( + ("marker", "runner"), + [ + ("package.json", "npm"), + ("pyproject.toml", "python"), + ("go.mod", "go"), + ("Cargo.toml", "cargo"), + ], +) +@pytest.mark.parametrize("runner_status", [0, 6]) +def test_performance_runs_only_component_native_benchmarks( + tmp_path: Path, generated_dir: Path, marker: str, runner: str, runner_status: int +) -> None: + """A failed native benchmark remains a failure without invoking fallback tools.""" + (tmp_path / marker).touch() + log = tmp_path / "runners.txt" + text = (generated_dir / "performance" / "SKILL.md").read_text(encoding="utf-8") + script = _bash_block(text, "## Phase 1:") + stubs = """ +npm() { echo npm >> "$CALL_LOG"; return "$RUNNER_STATUS"; } +python() { echo python >> "$CALL_LOG"; return "$RUNNER_STATUS"; } +go() { echo go >> "$CALL_LOG"; return "$RUNNER_STATUS"; } +cargo() { echo cargo >> "$CALL_LOG"; return "$RUNNER_STATUS"; } +npx() { echo unexpected-npx >> "$CALL_LOG"; return 99; } +""" + result = subprocess.run( + ["bash", "-c", stubs + script], + cwd=tmp_path, + env={**os.environ, "CALL_LOG": str(log), "RUNNER_STATUS": str(runner_status)}, + capture_output=True, + text=True, + ) + assert result.returncode == runner_status, result.stdout + result.stderr + assert log.read_text(encoding="utf-8").splitlines() == [runner] + procedure = text.split("# performance ", 1)[1] + assert "|| true" not in procedure + assert "2>/dev/null" not in procedure + + +def test_performance_reports_unconfigured_benchmarks(tmp_path: Path, generated_dir: Path) -> None: + """Unknown projects fail explicitly instead of reporting successful measurement.""" + text = (generated_dir / "performance" / "SKILL.md").read_text(encoding="utf-8") + result = subprocess.run( + ["bash", "-c", _bash_block(text, "## Phase 1:")], + cwd=tmp_path, + capture_output=True, + text=True, + ) + assert result.returncode == 2 + assert "no benchmark runner configured" in result.stdout From 65d98a78528dfae63cec7a6ec93207f837080626 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:41:17 +0100 Subject: [PATCH 09/16] fix(changedoc): align product ownership with the canonical change path Use the existing explicit project-root output override so product writes docs/changes consistently with the changedoc skill, including with a custom items root. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/agents/product.agent.md | 4 +- .vstack/vstack.json | 104 +++++++++--------- docs/design/skills.md | 2 + .../_templates/agents/product/config.yaml | 4 +- .../_fixtures/golden/agents/product.agent.md | 4 +- tests/vstack/agents/test_generator.py | 11 ++ 6 files changed, 71 insertions(+), 58 deletions(-) diff --git a/.github/agents/product.agent.md b/.github/agents/product.agent.md index f2afefab..9c52ee4c 100644 --- a/.github/agents/product.agent.md +++ b/.github/agents/product.agent.md @@ -179,7 +179,7 @@ Use `.vstack/memories/session/<RUN_ID>/` only to avoid replaying the same short- | `docs/product/vision.md` | | `docs/product/requirements.md` | | `docs/product/roadmap.md` | -| `docs/product/changes/*.md` | +| `docs/changes/*.md` | | `docs/product/issues/*.md` | ### baseline docs you maintain @@ -219,4 +219,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#vision` — vision document writing and review <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20261026002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index 2a7fcd02..0cd8f9d3 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,59 +2,8 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T20:41:06.070048+00:00", + "installed_at": "2026-10-26T20:41:17.186982+00:00", "artifacts": { - "agents": [ - { - "name": "architect", - "file": "agents/architect.agent.md", - "version": "20261026001", - "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", - "checksum_algorithm": "sha256" - }, - { - "name": "designer", - "file": "agents/designer.agent.md", - "version": "20261026001", - "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", - "checksum_algorithm": "sha256" - }, - { - "name": "engineer", - "file": "agents/engineer.agent.md", - "version": "20261026001", - "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", - "checksum_algorithm": "sha256" - }, - { - "name": "planner", - "file": "agents/planner.agent.md", - "version": "20261026001", - "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", - "checksum_algorithm": "sha256" - }, - { - "name": "product", - "file": "agents/product.agent.md", - "version": "20261026001", - "checksum": "55b959b8f6d6b4f933776b27d3dbd453a635afca1944a3605df09ff47175d992", - "checksum_algorithm": "sha256" - }, - { - "name": "release", - "file": "agents/release.agent.md", - "version": "20261026001", - "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", - "checksum_algorithm": "sha256" - }, - { - "name": "tester", - "file": "agents/tester.agent.md", - "version": "20261026001", - "checksum": "53d022b0253dfdfcbcf6c4e0f86ba6649e0b91d3635b9e9fd2b56a18fe34f945", - "checksum_algorithm": "sha256" - } - ], "hooks": [ { "name": "agent-call-audit", @@ -585,6 +534,57 @@ "checksum": "f8066d6f685418671992a75e103b96ce9b18bb0622c656c49ab93d3a382a69fb", "checksum_algorithm": "sha256" } + ], + "agents": [ + { + "name": "architect", + "file": "agents/architect.agent.md", + "version": "20261026001", + "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", + "checksum_algorithm": "sha256" + }, + { + "name": "designer", + "file": "agents/designer.agent.md", + "version": "20261026001", + "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", + "checksum_algorithm": "sha256" + }, + { + "name": "engineer", + "file": "agents/engineer.agent.md", + "version": "20261026001", + "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", + "checksum_algorithm": "sha256" + }, + { + "name": "planner", + "file": "agents/planner.agent.md", + "version": "20261026001", + "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", + "checksum_algorithm": "sha256" + }, + { + "name": "product", + "file": "agents/product.agent.md", + "version": "20261026002", + "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", + "checksum_algorithm": "sha256" + }, + { + "name": "release", + "file": "agents/release.agent.md", + "version": "20261026001", + "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", + "checksum_algorithm": "sha256" + }, + { + "name": "tester", + "file": "agents/tester.agent.md", + "version": "20261026001", + "checksum": "53d022b0253dfdfcbcf6c4e0f86ba6649e0b91d3635b9e9fd2b56a18fe34f945", + "checksum_algorithm": "sha256" + } ] } } diff --git a/docs/design/skills.md b/docs/design/skills.md index 1522e471..e9601270 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -130,6 +130,8 @@ Neither path bypasses project safety, gates, or required approvals. - Contributors: relevant roles enrich constraints, contracts, scenarios, tasks, and evidence without silently changing product intent. - Orchestration: `planner` coordinates updates and stage transitions. - Artifact path: `docs/changes/<slug>_<title>_YYYYMMDD.md`. + Product declares this as an explicit project-root output; changing the shared + agent items root does not relocate changedocs or historical records. Keep obligations, observable acceptance, checking methods, and actual results distinct without repeating prose. Tasks and local references are optional; diff --git a/src/vstack/_templates/agents/product/config.yaml b/src/vstack/_templates/agents/product/config.yaml index a1132976..ae7bf7db 100644 --- a/src/vstack/_templates/agents/product/config.yaml +++ b/src/vstack/_templates/agents/product/config.yaml @@ -1,5 +1,5 @@ name: product -version: 20261026001 +version: 20261026002 description: > Senior product manager. Owns vision, scope, requirements, and acceptance. Keeps change-local intent proportional and shared baselines current; @@ -38,7 +38,7 @@ defaults: baseline: true - path: roadmap.md baseline: true - - path: changes/*.md + - path: ./docs/changes/*.md - path: issues/*.md user-invocable: true diff --git a/tests/_fixtures/golden/agents/product.agent.md b/tests/_fixtures/golden/agents/product.agent.md index defd1fef..5b9119e5 100644 --- a/tests/_fixtures/golden/agents/product.agent.md +++ b/tests/_fixtures/golden/agents/product.agent.md @@ -179,7 +179,7 @@ Use `.vstack/memories/session/<RUN_ID>/` only to avoid replaying the same short- | `docs/product/vision.md` | | `docs/product/requirements.md` | | `docs/product/roadmap.md` | -| `docs/product/changes/*.md` | +| `docs/changes/*.md` | | `docs/product/issues/*.md` | ### baseline docs you maintain @@ -219,4 +219,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#vision` — vision document writing and review <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"<vstack-version>"} --> +<!-- VSTACK-META: {"artifact_name":"product","artifact_type":"agent","artifact_version":"20261026002","generator":"vstack","vstack_version":"<vstack-version>"} --> diff --git a/tests/vstack/agents/test_generator.py b/tests/vstack/agents/test_generator.py index 66a1c56d..e0c5a6cd 100644 --- a/tests/vstack/agents/test_generator.py +++ b/tests/vstack/agents/test_generator.py @@ -11,6 +11,17 @@ from vstack.constants import ARTIFACTS_DOCS_ROOT +@pytest.mark.parametrize("items_root", ["docs", "documentation"]) +def test_product_changedoc_output_uses_canonical_project_path(items_root: str) -> None: + """Product ownership agrees with changedoc guidance even with a custom item root.""" + template = Path(__file__).resolve().parents[3] / "src/vstack/_templates/agents/product" + result = AgentGenerator(items_root=items_root).template_partials(template) + output = result["AGENT_ARTIFACTS_OUTPUT"] + assert "`docs/changes/*.md`" in output + assert f"`{items_root}/product/vision.md`" in output + assert f"`{items_root}/product/changes/*.md`" not in output + + class TestAgentGenerator: """Tests for AgentGenerator and all its methods.""" From 89e8bcabfaef184e68f612ab423f8644caac172e Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:41:31 +0100 Subject: [PATCH 10/16] fix(tester): route operational reviews to verification skills Keep guardrails scoped to destructive-action safety and use inspect or authorized verify for reliability and observability checks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/agents/tester.agent.md | 8 +++++--- .vstack/vstack.json | 6 +++--- docs/design/skills.md | 6 ++++++ src/vstack/_templates/agents/tester/config.yaml | 2 +- src/vstack/_templates/agents/tester/template.md | 6 ++++-- tests/vstack/agents/test_template_structure.py | 10 ++++++++++ 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/agents/tester.agent.md b/.github/agents/tester.agent.md index 13c788d5..b92c03d0 100644 --- a/.github/agents/tester.agent.md +++ b/.github/agents/tester.agent.md @@ -147,7 +147,9 @@ is needed, state that and offer handoff. 1. Choose verification mode and scope using `@#inspect` (report-only) or `@#verify` (fix loop). 1. Compare actual scoped behavior to acceptance, including required behavior absent from the diff. Separate gaps, contradictions, unexplained additions, and missing evidence. -1. Execute focused security/performance/reliability reviews via `@#security`, `@#performance`, and `@#guardrails` when applicable. +1. Use `@#security` and `@#performance` for focused domain reviews. + Cover reliability and observability through `@#inspect` or authorized `@#verify`; + `@#guardrails` governs destructive-action safety, not service reliability. 1. Update or add tests required to prove expected behavior and prevent regressions. 1. Map criteria to checks/results, reviewed scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. Wording review, checkboxes, and code coverage @@ -207,7 +209,7 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#dependency` — dependency vulnerability and health audit - `@#docs` — keep verification and audit documentation complete and current - `@#explore` — codebase discovery and mapping -- `@#guardrails` — reliability and observability review +- `@#guardrails` — destructive-action safety and confirmation - `@#incident` — incident analysis and post-mortem writing - `@#inspect` — read-only verification audit, produces findings report - `@#migrate` — database migration safety review @@ -217,4 +219,4 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#threat-model` — structured threat analysis and mitigation prioritization <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"tester","artifact_type":"agent","artifact_version":"20261026001","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"tester","artifact_type":"agent","artifact_version":"20261026002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index 0cd8f9d3..8e1c8dda 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,7 +2,7 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T20:41:17.186982+00:00", + "installed_at": "2026-10-26T20:41:31.001237+00:00", "artifacts": { "hooks": [ { @@ -581,8 +581,8 @@ { "name": "tester", "file": "agents/tester.agent.md", - "version": "20261026001", - "checksum": "53d022b0253dfdfcbcf6c4e0f86ba6649e0b91d3635b9e9fd2b56a18fe34f945", + "version": "20261026002", + "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", "checksum_algorithm": "sha256" } ] diff --git a/docs/design/skills.md b/docs/design/skills.md index e9601270..4f7c9b8c 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -161,6 +161,12 @@ tools/configuration are `not run`; nonzero command results are `failed`, with visible error output. Never substitute another ecosystem or ordinary unit tests for benchmark evidence. +### tester operational verification + +Tester uses `inspect` or authorized `verify` for reliability and observability. +`guardrails` only governs destructive-action safety and confirmation; it does +not replace operational checks. + ______________________________________________________________________ ## file locations diff --git a/src/vstack/_templates/agents/tester/config.yaml b/src/vstack/_templates/agents/tester/config.yaml index d38ef351..95ac00b4 100644 --- a/src/vstack/_templates/agents/tester/config.yaml +++ b/src/vstack/_templates/agents/tester/config.yaml @@ -1,5 +1,5 @@ name: tester -version: 20261026001 +version: 20261026002 description: > Senior QA, security, and reliability engineer. Runs functional, security, and performance tests. Produces verification reports based on the approved diff --git a/src/vstack/_templates/agents/tester/template.md b/src/vstack/_templates/agents/tester/template.md index fbc5899d..82d525fe 100644 --- a/src/vstack/_templates/agents/tester/template.md +++ b/src/vstack/_templates/agents/tester/template.md @@ -86,7 +86,9 @@ is needed, state that and offer handoff. 1. Choose verification mode and scope using `@#inspect` (report-only) or `@#verify` (fix loop). 1. Compare actual scoped behavior to acceptance, including required behavior absent from the diff. Separate gaps, contradictions, unexplained additions, and missing evidence. -1. Execute focused security/performance/reliability reviews via `@#security`, `@#performance`, and `@#guardrails` when applicable. +1. Use `@#security` and `@#performance` for focused domain reviews. + Cover reliability and observability through `@#inspect` or authorized `@#verify`; + `@#guardrails` governs destructive-action safety, not service reliability. 1. Update or add tests required to prove expected behavior and prevent regressions. 1. Map criteria to checks/results, reviewed scope/revision, and `passed`, `failed`, `not run`, or `no longer current`. Wording review, checkboxes, and code coverage @@ -136,7 +138,7 @@ Keep this list lean. Use additional installed domain skills only when needed. - `@#dependency` — dependency vulnerability and health audit - `@#docs` — keep verification and audit documentation complete and current - `@#explore` — codebase discovery and mapping -- `@#guardrails` — reliability and observability review +- `@#guardrails` — destructive-action safety and confirmation - `@#incident` — incident analysis and post-mortem writing - `@#inspect` — read-only verification audit, produces findings report - `@#migrate` — database migration safety review diff --git a/tests/vstack/agents/test_template_structure.py b/tests/vstack/agents/test_template_structure.py index d3d9e2cc..475ed7d2 100644 --- a/tests/vstack/agents/test_template_structure.py +++ b/tests/vstack/agents/test_template_structure.py @@ -92,6 +92,16 @@ def test_rendered_contributors_preserve_scope_ownership(installed_target: Path) assert "not product scope or acceptance" in text +def test_tester_routes_operations_review_to_verification(installed_target: Path) -> None: + """Reliability review uses verification skills, not the destructive-action guard.""" + text = " ".join( + (installed_target / ".github/agents/tester.agent.md").read_text(encoding="utf-8").split() + ) + assert "reliability and observability through `@#inspect` or authorized `@#verify`" in text + assert "`@#guardrails` — destructive-action safety and confirmation" in text + assert "`@#guardrails` — reliability and observability review" not in text + + @pytest.mark.parametrize( ("role", "obligations"), [ From 7badbfc485f8f8d0a70bc4fe0901aeedee7f9841 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:41:52 +0100 Subject: [PATCH 11/16] fix(pr): push approved changes before reusing an existing pull request Do not exit before pushing when a PR exists. Stop on GitHub or push failures and replace blanket staging and cleanup messages with scoped Conventional Commits. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/pr/SKILL.md | 34 +++--- .vstack/vstack.json | 108 ++++++++++---------- docs/design/skills.md | 6 ++ src/vstack/_templates/skills/pr/config.yaml | 4 +- src/vstack/_templates/skills/pr/template.md | 30 ++++-- tests/vstack/skills/test_templates.py | 71 +++++++++++++ 6 files changed, 173 insertions(+), 80 deletions(-) diff --git a/.github/skills/pr/SKILL.md b/.github/skills/pr/SKILL.md index ba2f9fa2..b3ae3d0a 100644 --- a/.github/skills/pr/SKILL.md +++ b/.github/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: 'Commit, push, and open a pull request from the current branch to main. Uses the release notes from docs/releases/{date}.md as the PR body. Use when asked to "open a PR", "push and create PR", or "submit for review".' +description: 'Commit, push, and open a pull request from the current branch to main. Updates an existing PR after pushing; uses the repository PR template for new PRs. Use when asked to "open a PR", "push and create PR", or "submit for review".' license: 'MIT' compatibility: 'Requires a skills-compatible agent with repository file access and terminal command execution when needed.' metadata: @@ -52,7 +52,7 @@ before CI/CD takes over. ```bash # Confirm gh CLI is authenticated -gh auth status 2>/dev/null || echo "WARNING: gh CLI not authenticated — Step 4 will fail" +gh auth status || exit $? # Confirm not on the target base branch BRANCH=$(git branch --show-current) @@ -63,10 +63,10 @@ fi echo "Branch: $BRANCH" # Check if a PR already exists for this branch -EXISTING_PR=$(gh pr view --json url --jq '.url' 2>/dev/null) +EXISTING_PR=$(gh pr list --head "$BRANCH" --state open --json url \ + --jq '.[0].url // empty') || exit $? if [ -n "$EXISTING_PR" ]; then - echo "PR already open: $EXISTING_PR" - exit 0 + echo "Existing PR will be updated after push: $EXISTING_PR" fi # Show what will be included @@ -82,23 +82,31 @@ PR_TEMPLATE=$(cat .github/PULL_REQUEST_TEMPLATE.md \ ## Step 2: Commit -Stage and commit any uncommitted changes: +Review changed and already-staged files. Commit only approved task changes using +`@#conventional-commit` and an intent-specific message. Stage explicit paths; +never use `git add -A` or a generic cleanup commit. Leave unrelated work untouched. +If scope is unclear, ask before staging or committing. ```bash -git add -A git diff --cached --stat - -# Only commit if there are staged changes -git diff --cached --quiet || git commit -m "chore: pre-release cleanup" ``` ## Step 3: Push ```bash -git push --set-upstream origin "$BRANCH" +git push --set-upstream origin "$BRANCH" || exit $? ``` -## Step 4: Open PR +## Step 4: Reuse or Open PR + +Only after a successful push, reuse an existing PR: + +```bash +if [ -n "$EXISTING_PR" ]; then + echo "PR updated: $EXISTING_PR" + exit 0 +fi +``` Use the PR title and body provided by the invoking agent or user. If no body is provided, write a short summary of the changes on this branch. @@ -151,4 +159,4 @@ Next steps depend on the repository CI/CD configuration: ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"pr","artifact_type":"skill","artifact_version":"20260502013","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"pr","artifact_type":"skill","artifact_version":"20261026002","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index 8e1c8dda..d8613552 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,7 +2,7 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T20:41:31.001237+00:00", + "installed_at": "2026-10-26T20:41:52.724939+00:00", "artifacts": { "hooks": [ { @@ -141,6 +141,57 @@ "checksum_algorithm": "sha256" } ], + "agents": [ + { + "name": "architect", + "file": "agents/architect.agent.md", + "version": "20261026001", + "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", + "checksum_algorithm": "sha256" + }, + { + "name": "designer", + "file": "agents/designer.agent.md", + "version": "20261026001", + "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", + "checksum_algorithm": "sha256" + }, + { + "name": "engineer", + "file": "agents/engineer.agent.md", + "version": "20261026001", + "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", + "checksum_algorithm": "sha256" + }, + { + "name": "planner", + "file": "agents/planner.agent.md", + "version": "20261026001", + "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", + "checksum_algorithm": "sha256" + }, + { + "name": "product", + "file": "agents/product.agent.md", + "version": "20261026002", + "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", + "checksum_algorithm": "sha256" + }, + { + "name": "release", + "file": "agents/release.agent.md", + "version": "20261026001", + "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", + "checksum_algorithm": "sha256" + }, + { + "name": "tester", + "file": "agents/tester.agent.md", + "version": "20261026002", + "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", + "checksum_algorithm": "sha256" + } + ], "skills": [ { "name": "adr", @@ -404,8 +455,8 @@ { "name": "pr", "file": "skills/pr/SKILL.md", - "version": "20260502013", - "checksum": "fe27680c661475334ca97bbb0ba46f7516a4a351bdd58c0f39af975817627c99", + "version": "20261026002", + "checksum": "39fdf1f0df977b9dc71f47d637cea90febd312ebaa8a054687c5def7c7d653eb", "checksum_algorithm": "sha256" }, { @@ -534,57 +585,6 @@ "checksum": "f8066d6f685418671992a75e103b96ce9b18bb0622c656c49ab93d3a382a69fb", "checksum_algorithm": "sha256" } - ], - "agents": [ - { - "name": "architect", - "file": "agents/architect.agent.md", - "version": "20261026001", - "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", - "checksum_algorithm": "sha256" - }, - { - "name": "designer", - "file": "agents/designer.agent.md", - "version": "20261026001", - "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", - "checksum_algorithm": "sha256" - }, - { - "name": "engineer", - "file": "agents/engineer.agent.md", - "version": "20261026001", - "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", - "checksum_algorithm": "sha256" - }, - { - "name": "planner", - "file": "agents/planner.agent.md", - "version": "20261026001", - "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", - "checksum_algorithm": "sha256" - }, - { - "name": "product", - "file": "agents/product.agent.md", - "version": "20261026002", - "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", - "checksum_algorithm": "sha256" - }, - { - "name": "release", - "file": "agents/release.agent.md", - "version": "20261026001", - "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", - "checksum_algorithm": "sha256" - }, - { - "name": "tester", - "file": "agents/tester.agent.md", - "version": "20261026002", - "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", - "checksum_algorithm": "sha256" - } ] } } diff --git a/docs/design/skills.md b/docs/design/skills.md index 4f7c9b8c..a96587e4 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -167,6 +167,12 @@ Tester uses `inspect` or authorized `verify` for reliability and observability. `guardrails` only governs destructive-action safety and confirmation; it does not replace operational checks. +### pull request updates + +`pr` pushes approved task commits before reusing an existing PR. Authentication, +lookup, or push failures stop the procedure. Commit explicit reviewed paths +with an intent-specific Conventional Commit; never stage unrelated work. + ______________________________________________________________________ ## file locations diff --git a/src/vstack/_templates/skills/pr/config.yaml b/src/vstack/_templates/skills/pr/config.yaml index 6726ab81..7083baa9 100644 --- a/src/vstack/_templates/skills/pr/config.yaml +++ b/src/vstack/_templates/skills/pr/config.yaml @@ -1,8 +1,8 @@ name: pr -version: 20260502013 +version: 20261026002 description: | Commit, push, and open a pull request from the current branch to main. - Uses the release notes from docs/releases/{date}.md as the PR body. + Updates an existing PR after pushing; uses the repository PR template for new PRs. Use when asked to "open a PR", "push and create PR", or "submit for review". license: MIT diff --git a/src/vstack/_templates/skills/pr/template.md b/src/vstack/_templates/skills/pr/template.md index a670d4e4..0008d669 100644 --- a/src/vstack/_templates/skills/pr/template.md +++ b/src/vstack/_templates/skills/pr/template.md @@ -19,7 +19,7 @@ before CI/CD takes over. ```bash # Confirm gh CLI is authenticated -gh auth status 2>/dev/null || echo "WARNING: gh CLI not authenticated — Step 4 will fail" +gh auth status || exit $? # Confirm not on the target base branch BRANCH=$(git branch --show-current) @@ -30,10 +30,10 @@ fi echo "Branch: $BRANCH" # Check if a PR already exists for this branch -EXISTING_PR=$(gh pr view --json url --jq '.url' 2>/dev/null) +EXISTING_PR=$(gh pr list --head "$BRANCH" --state open --json url \ + --jq '.[0].url // empty') || exit $? if [ -n "$EXISTING_PR" ]; then - echo "PR already open: $EXISTING_PR" - exit 0 + echo "Existing PR will be updated after push: $EXISTING_PR" fi # Show what will be included @@ -49,23 +49,31 @@ PR_TEMPLATE=$(cat .github/PULL_REQUEST_TEMPLATE.md \ ## Step 2: Commit -Stage and commit any uncommitted changes: +Review changed and already-staged files. Commit only approved task changes using +`@#conventional-commit` and an intent-specific message. Stage explicit paths; +never use `git add -A` or a generic cleanup commit. Leave unrelated work untouched. +If scope is unclear, ask before staging or committing. ```bash -git add -A git diff --cached --stat - -# Only commit if there are staged changes -git diff --cached --quiet || git commit -m "chore: pre-release cleanup" ``` ## Step 3: Push ```bash -git push --set-upstream origin "$BRANCH" +git push --set-upstream origin "$BRANCH" || exit $? ``` -## Step 4: Open PR +## Step 4: Reuse or Open PR + +Only after a successful push, reuse an existing PR: + +```bash +if [ -n "$EXISTING_PR" ]; then + echo "PR updated: $EXISTING_PR" + exit 0 +fi +``` Use the PR title and body provided by the invoking agent or user. If no body is provided, write a short summary of the changes on this branch. diff --git a/tests/vstack/skills/test_templates.py b/tests/vstack/skills/test_templates.py index 40af7128..7eff59c4 100644 --- a/tests/vstack/skills/test_templates.py +++ b/tests/vstack/skills/test_templates.py @@ -2,7 +2,9 @@ from __future__ import annotations +import os import re +import subprocess from pathlib import Path import pytest @@ -12,6 +14,75 @@ from vstack.frontmatter import FrontmatterParser +@pytest.mark.parametrize("existing_pr", ["", "https://example.invalid/pull/1"]) +@pytest.mark.parametrize("push_status", [0, 7]) +def test_pr_recipe_pushes_before_reusing_existing_pr( + tmp_path: Path, generated_dir: Path, existing_pr: str, push_status: int +) -> None: + """Existing and new PR paths push first and never hide push failures.""" + text = (generated_dir / "pr" / "SKILL.md").read_text(encoding="utf-8") + blocks = [] + for heading in ("## Step 1:", "## Step 3:", "## Step 4:"): + match = re.search(r"```bash\n(.*?)```", text.split(heading, 1)[1], re.DOTALL) + assert match is not None + blocks.append(match.group(1)) + stubs = """ +git() { + case "$1" in + branch) echo feature/example ;; + push) echo push >> "$CALL_LOG"; return "$PUSH_STATUS" ;; + esac +} +gh() { + if [ "$1 $2" = "pr list" ]; then printf '%s' "$EXISTING_URL"; fi +} +""" + log = tmp_path / "calls.txt" + result = subprocess.run( + ["bash", "-c", stubs + "\n".join(blocks) + '\necho create >> "$CALL_LOG"'], + cwd=tmp_path, + env={ + **os.environ, + "CALL_LOG": str(log), + "PUSH_STATUS": str(push_status), + "EXISTING_URL": existing_pr, + }, + capture_output=True, + text=True, + ) + assert result.returncode == push_status, result.stdout + result.stderr + assert log.read_text(encoding="utf-8").splitlines() == ( + ["push", "create"] if not existing_pr and push_status == 0 else ["push"] + ) + assert "git add -A\n" not in text + assert 'git commit -m "chore: pre-release cleanup"' not in text + + +@pytest.mark.parametrize("failed_command", ["auth status", "pr list"]) +def test_pr_preflight_stops_on_github_errors( + tmp_path: Path, generated_dir: Path, failed_command: str +) -> None: + """Authentication and PR lookup failures do not become successful PR updates.""" + text = (generated_dir / "pr" / "SKILL.md").read_text(encoding="utf-8") + match = re.search(r"```bash\n(.*?)```", text.split("## Step 1:", 1)[1], re.DOTALL) + assert match is not None + stubs = """ +git() { echo feature/example; } +gh() { + if [ "$1 $2" = "$FAILED_COMMAND" ]; then return 8; fi +} +""" + result = subprocess.run( + ["bash", "-c", stubs + match.group(1) + "\necho unexpected-continuation"], + cwd=tmp_path, + env={**os.environ, "FAILED_COMMAND": failed_command}, + capture_output=True, + text=True, + ) + assert result.returncode == 8 + assert "unexpected-continuation" not in result.stdout + + def _skill_templates() -> list[Path]: """Internal helper to skill templates.""" if not SKILLS_TEMPLATES_DIR.exists(): From a0c00939142b1062e2fd00dc66418f50da3331af Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:41:58 +0100 Subject: [PATCH 12/16] docs(workflow): align baseline claims with the shipped delivery model Correct skill inventory and dependency constraints, document focused planner routing and configurable approval policy, and repair historical report links. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/design/workflow.md | 2 +- docs/product/requirements.md | 7 ++++--- docs/releases/2026-05-12.md | 6 +++--- docs/user/explanation/workflow-modes.md | 22 ++++++++++------------ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/docs/design/workflow.md b/docs/design/workflow.md index 73b38cf6..2edf6b04 100644 --- a/docs/design/workflow.md +++ b/docs/design/workflow.md @@ -340,7 +340,7 @@ flowchart TD - Each role is scoped to its domain - Each role reads its inputs from disk (artifacts from upstream roles) -- User approval is required after each stage output +- User approval follows each stage's configured `hitl` policy; the diagram shows `always` - Handoffs are only for happy-path continuation ### flow principles diff --git a/docs/product/requirements.md b/docs/product/requirements.md index ca927df7..9b696d93 100644 --- a/docs/product/requirements.md +++ b/docs/product/requirements.md @@ -100,7 +100,8 @@ ______________________________________________________________________ - 6 delivery agent roles: `product`, `architect`, `designer`, `engineer`, `tester`, `release`, plus a `planner` coordinator agent. -- 42 skills across the role set with canonical names enforced at source-verify time. +- 56 distributed skills across the role set with canonical names enforced at source-verify time. + Repository-only skills are outside the installed catalog. ### FR-11 — workflow mode semantics @@ -162,7 +163,7 @@ ______________________________________________________________________ 1. `vstack verify --target DIR` reports zero errors on a clean install. 1. `vstack validate` exits 0 when all source templates resolve cleanly. 1. Locally modified tracked files are preserved on re-install by default (FR-4). -1. All 42 canonical skill names are present after a full install. +1. All 56 canonical skill names are present after a full install. 1. `vstack manifest upgrade` migrates a legacy manifest without data loss. 1. `brew install eschaar/vstack/vstack` installs and runs `vstack --help` and `vstack --version` without errors on a supported macOS or Linux runner. @@ -171,7 +172,7 @@ ______________________________________________________________________ ## constraints -1. No external runtime dependencies (stdlib-only at runtime). +1. PyYAML is the only external runtime dependency; use the standard library otherwise. 1. Generated output lives under `.github/` only; source templates are never modified at runtime. 1. Manifest schema is versioned; old manifests require explicit upgrade before further diff --git a/docs/releases/2026-05-12.md b/docs/releases/2026-05-12.md index 97e8dd5a..d0e7c67d 100644 --- a/docs/releases/2026-05-12.md +++ b/docs/releases/2026-05-12.md @@ -90,9 +90,9 @@ All pre-release verification points are now green and documented: - **Performance baseline**: Freshly measured 2026-05-14 with timeit and subprocess timing. All metrics within acceptable thresholds. -See [docs/reports/test-report.md](docs/reports/test-report.md), -[docs/reports/security-report.md](docs/reports/security-report.md), and -[docs/reports/performance-baseline.md](docs/reports/performance-baseline.md) for full details. +See [test report](../reports/test-report.md), +[security report](../reports/security-report.md), and +[performance baseline](../reports/performance-baseline.md) for full details. ## Sign-offs diff --git a/docs/user/explanation/workflow-modes.md b/docs/user/explanation/workflow-modes.md index 55604c92..54888f11 100644 --- a/docs/user/explanation/workflow-modes.md +++ b/docs/user/explanation/workflow-modes.md @@ -64,14 +64,14 @@ In `hybrid`, pick one execution path per session and stay on it. ## Planner vs. direct agent invocation Choosing a workflow mode is separate from deciding whether to use the planner at all. -The planner is built for coordinating a full multi-role delivery pipeline. -It adds overhead — multiple model calls, orchestration logic, gate pauses — that is only -worthwhile when multiple roles genuinely need to collaborate in sequence. +The planner classifies focused work and multi-role delivery. For focused work it +routes to the relevant owner; a full pipeline adds model calls and coordination +only when the scope and configured workflow require them. **Use the planner when:** - Delivering a feature, fix, or change that spans multiple roles (product → architect → designer → engineer → tester → release). -- You want explicit gate approvals at each stage boundary. +- You need coordinated progression and approvals according to configured gate policy. - The work is large enough that cross-role coordination matters. **Use a specialist agent directly when:** @@ -80,14 +80,12 @@ worthwhile when multiple roles genuinely need to collaborate in sequence. - You are doing focused day-to-day maintenance: refreshing a report, writing an ADR, bumping a dependency. - You want the fastest path to a result. -**Why the planner cannot automatically do this better:** -The planner works from a stage-based pipeline, not from artifact ownership. It cannot -infer that "update the architecture docs" should skip product, designer, engineer, tester, -and release and route only to architect. Per-task stage qualification does not scale — -there is no finite list of task types that maps cleanly onto pipeline subsets. - -The effective pattern is: you make the routing decision. The planner handles orchestration -when the full pipeline is genuinely needed. Direct invocation handles everything else. +**How focused routing works:** +The planner assesses intent, ownership, risk, and ambiguity before choosing focused +delivery or a multi-role pipeline. Clear, low-risk work can use existing issue/chat +context. Focused routing never bypasses configured dependencies, gates, or approvals. +Invoke the specialist directly when ownership is already clear to avoid an extra +routing turn; use the planner when coordination or ownership is uncertain. | Situation | Best approach | | ------------------------------- | ---------------------------------------------------- | From d7d37ff26e55af81fdba754789ce4541af7ea3a4 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:43:03 +0100 Subject: [PATCH 13/16] chore(ci): verify the built wheel install lifecycle before publication Exercise fresh install, source/output verification, reinstall and tracked-artifact removal outside the checkout under Python isolated mode. Verified locally using a freshly built wheel in a separate environment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish.yml | 11 ++++++++++- docs/design/overview.md | 5 +++++ tests/vstack/test_publish_workflow.py | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index adaaafd2..e24f50c1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -114,7 +114,16 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install dist/*.whl - vstack --help >/dev/null + SMOKE_ROOT=$(mktemp -d) + cd "$SMOKE_ROOT" + mkdir project + python -I -m vstack --help + python -I -m vstack install --target "$SMOKE_ROOT/project" + python -I -m vstack verify --target "$SMOKE_ROOT/project" + python -I -m vstack install --target "$SMOKE_ROOT/project" + python -I -m vstack verify --target "$SMOKE_ROOT/project" + python -I -m vstack uninstall --target "$SMOKE_ROOT/project" + test ! -e "$SMOKE_ROOT/project/.github/skills/changedoc/SKILL.md" - name: Validate built artifact version run: | diff --git a/docs/design/overview.md b/docs/design/overview.md index d89b0a44..77471499 100644 --- a/docs/design/overview.md +++ b/docs/design/overview.md @@ -19,6 +19,11 @@ Coordinated runs may also use a disposable handoff cache under prompt context between delegated stages; it never replaces role-owned artifacts or `.vstack/vstack.json`. +Release publishing smoke-tests the built wheel outside the source checkout with +Python isolated mode (`-I`). It exercises install, source/output verification, +reinstall, and tracked-artifact uninstall before publishing. This checks packaged +templates and migrations, not just whether the CLI can display help. + ______________________________________________________________________ ## 1. domain model diff --git a/tests/vstack/test_publish_workflow.py b/tests/vstack/test_publish_workflow.py index 1474faa4..9b42406b 100644 --- a/tests/vstack/test_publish_workflow.py +++ b/tests/vstack/test_publish_workflow.py @@ -12,6 +12,20 @@ class TestPublishWorkflow: """Verify publish workflow contracts for PyPI and Homebrew distribution.""" + def test_built_wheel_smoke_covers_isolated_install_lifecycle(self) -> None: + """Publish checks packaged resources, reinstall and removal outside the checkout.""" + workflow = yaml.safe_load(WORKFLOW_PATH.read_text(encoding="utf-8")) + steps = workflow["jobs"]["publish"]["steps"] + smoke = next(step for step in steps if step["name"] == "Smoke test built wheel")["run"] + assert "python -m pip install dist/*.whl" in smoke + assert 'cd "$SMOKE_ROOT"' in smoke + assert "mkdir project" in smoke + assert smoke.count('python -I -m vstack install --target "$SMOKE_ROOT/project"') == 2 + assert smoke.count('python -I -m vstack verify --target "$SMOKE_ROOT/project"') == 2 + assert 'python -I -m vstack uninstall --target "$SMOKE_ROOT/project"' in smoke + assert 'test ! -e "$SMOKE_ROOT/project/.github/skills/changedoc/SKILL.md"' in smoke + assert "|| true" not in smoke + def test_homebrew_job_is_gated_and_sequential(self) -> None: """Homebrew publish should run only after PyPI publish behind a feature flag.""" workflow = yaml.safe_load(WORKFLOW_PATH.read_text(encoding="utf-8")) From 541ee6489ae1b864d4597e3ffbdcd070c4147e30 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 21:45:02 +0100 Subject: [PATCH 14/16] test(workflow): complete invalid-stage diagnostics coverage Exercise missing and blank roles through direct graph validation and refresh generated manifest state after the full install pass. The full quality gate now passes 778 tests with 100 percent coverage on Python 3.14. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .vstack/vstack.json | 378 ++++++++++++++--------------- tests/vstack/cli/test_interface.py | 12 + 2 files changed, 201 insertions(+), 189 deletions(-) diff --git a/.vstack/vstack.json b/.vstack/vstack.json index d8613552..a7d7c0d8 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,196 +2,8 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T20:41:52.724939+00:00", + "installed_at": "2026-10-26T20:44:29.425789+00:00", "artifacts": { - "hooks": [ - { - "name": "agent-call-audit", - "file": "hooks/agent-call-audit.json", - "version": "4.0.0", - "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", - "checksum_algorithm": "sha256" - }, - { - "name": "log-retention-cleanup", - "file": "hooks/log-retention-cleanup.json", - "version": "4.0.0", - "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", - "checksum_algorithm": "sha256" - }, - { - "name": "post-commit-security-scan", - "file": "hooks/post-commit-security-scan.json", - "version": "4.0.0", - "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", - "checksum_algorithm": "sha256" - }, - { - "name": "post-edit-format", - "file": "hooks/post-edit-format.json", - "version": "4.0.0", - "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", - "checksum_algorithm": "sha256" - }, - { - "name": "post-edit-markdown-quality", - "file": "hooks/post-edit-markdown-quality.json", - "version": "4.0.0", - "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", - "checksum_algorithm": "sha256" - }, - { - "name": "pre-tool-safety-gate", - "file": "hooks/pre-tool-safety-gate.json", - "version": "4.0.0", - "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", - "checksum_algorithm": "sha256" - }, - { - "name": "session-audit", - "file": "hooks/session-audit.json", - "version": "4.0.0", - "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", - "checksum_algorithm": "sha256" - } - ], - "instructions": [ - { - "name": "git", - "file": "instructions/git.instructions.md", - "version": "20260421001", - "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", - "checksum_algorithm": "sha256" - }, - { - "name": "helm", - "file": "instructions/helm.instructions.md", - "version": "20260502040", - "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", - "checksum_algorithm": "sha256" - }, - { - "name": "java", - "file": "instructions/java.instructions.md", - "version": "20260502001", - "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", - "checksum_algorithm": "sha256" - }, - { - "name": "k8s", - "file": "instructions/k8s.instructions.md", - "version": "20260502039", - "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", - "checksum_algorithm": "sha256" - }, - { - "name": "markdown", - "file": "instructions/markdown.instructions.md", - "version": "20260502002", - "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", - "checksum_algorithm": "sha256" - }, - { - "name": "python", - "file": "instructions/python.instructions.md", - "version": "20260421002", - "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", - "checksum_algorithm": "sha256" - }, - { - "name": "rancher", - "file": "instructions/rancher.instructions.md", - "version": "20260502041", - "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", - "checksum_algorithm": "sha256" - }, - { - "name": "security", - "file": "instructions/security.instructions.md", - "version": "20260502003", - "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", - "checksum_algorithm": "sha256" - }, - { - "name": "terraform", - "file": "instructions/terraform.instructions.md", - "version": "20260502034", - "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", - "checksum_algorithm": "sha256" - }, - { - "name": "terragrunt", - "file": "instructions/terragrunt.instructions.md", - "version": "20260502035", - "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", - "checksum_algorithm": "sha256" - }, - { - "name": "testing", - "file": "instructions/testing.instructions.md", - "version": "20261026001", - "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", - "checksum_algorithm": "sha256" - }, - { - "name": "typescript", - "file": "instructions/typescript.instructions.md", - "version": "20260502005", - "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", - "checksum_algorithm": "sha256" - } - ], - "agents": [ - { - "name": "architect", - "file": "agents/architect.agent.md", - "version": "20261026001", - "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", - "checksum_algorithm": "sha256" - }, - { - "name": "designer", - "file": "agents/designer.agent.md", - "version": "20261026001", - "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", - "checksum_algorithm": "sha256" - }, - { - "name": "engineer", - "file": "agents/engineer.agent.md", - "version": "20261026001", - "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", - "checksum_algorithm": "sha256" - }, - { - "name": "planner", - "file": "agents/planner.agent.md", - "version": "20261026001", - "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", - "checksum_algorithm": "sha256" - }, - { - "name": "product", - "file": "agents/product.agent.md", - "version": "20261026002", - "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", - "checksum_algorithm": "sha256" - }, - { - "name": "release", - "file": "agents/release.agent.md", - "version": "20261026001", - "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", - "checksum_algorithm": "sha256" - }, - { - "name": "tester", - "file": "agents/tester.agent.md", - "version": "20261026002", - "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", - "checksum_algorithm": "sha256" - } - ], "skills": [ { "name": "adr", @@ -585,6 +397,194 @@ "checksum": "f8066d6f685418671992a75e103b96ce9b18bb0622c656c49ab93d3a382a69fb", "checksum_algorithm": "sha256" } + ], + "agents": [ + { + "name": "architect", + "file": "agents/architect.agent.md", + "version": "20261026001", + "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", + "checksum_algorithm": "sha256" + }, + { + "name": "designer", + "file": "agents/designer.agent.md", + "version": "20261026001", + "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", + "checksum_algorithm": "sha256" + }, + { + "name": "engineer", + "file": "agents/engineer.agent.md", + "version": "20261026001", + "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", + "checksum_algorithm": "sha256" + }, + { + "name": "planner", + "file": "agents/planner.agent.md", + "version": "20261026001", + "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", + "checksum_algorithm": "sha256" + }, + { + "name": "product", + "file": "agents/product.agent.md", + "version": "20261026002", + "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", + "checksum_algorithm": "sha256" + }, + { + "name": "release", + "file": "agents/release.agent.md", + "version": "20261026001", + "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", + "checksum_algorithm": "sha256" + }, + { + "name": "tester", + "file": "agents/tester.agent.md", + "version": "20261026002", + "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", + "checksum_algorithm": "sha256" + } + ], + "hooks": [ + { + "name": "agent-call-audit", + "file": "hooks/agent-call-audit.json", + "version": "4.0.0", + "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", + "checksum_algorithm": "sha256" + }, + { + "name": "log-retention-cleanup", + "file": "hooks/log-retention-cleanup.json", + "version": "4.0.0", + "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", + "checksum_algorithm": "sha256" + }, + { + "name": "post-commit-security-scan", + "file": "hooks/post-commit-security-scan.json", + "version": "4.0.0", + "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", + "checksum_algorithm": "sha256" + }, + { + "name": "post-edit-format", + "file": "hooks/post-edit-format.json", + "version": "4.0.0", + "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", + "checksum_algorithm": "sha256" + }, + { + "name": "post-edit-markdown-quality", + "file": "hooks/post-edit-markdown-quality.json", + "version": "4.0.0", + "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", + "checksum_algorithm": "sha256" + }, + { + "name": "pre-tool-safety-gate", + "file": "hooks/pre-tool-safety-gate.json", + "version": "4.0.0", + "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", + "checksum_algorithm": "sha256" + }, + { + "name": "session-audit", + "file": "hooks/session-audit.json", + "version": "4.0.0", + "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", + "checksum_algorithm": "sha256" + } + ], + "instructions": [ + { + "name": "git", + "file": "instructions/git.instructions.md", + "version": "20260421001", + "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", + "checksum_algorithm": "sha256" + }, + { + "name": "helm", + "file": "instructions/helm.instructions.md", + "version": "20260502040", + "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", + "checksum_algorithm": "sha256" + }, + { + "name": "java", + "file": "instructions/java.instructions.md", + "version": "20260502001", + "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", + "checksum_algorithm": "sha256" + }, + { + "name": "k8s", + "file": "instructions/k8s.instructions.md", + "version": "20260502039", + "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", + "checksum_algorithm": "sha256" + }, + { + "name": "markdown", + "file": "instructions/markdown.instructions.md", + "version": "20260502002", + "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", + "checksum_algorithm": "sha256" + }, + { + "name": "python", + "file": "instructions/python.instructions.md", + "version": "20260421002", + "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", + "checksum_algorithm": "sha256" + }, + { + "name": "rancher", + "file": "instructions/rancher.instructions.md", + "version": "20260502041", + "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", + "checksum_algorithm": "sha256" + }, + { + "name": "security", + "file": "instructions/security.instructions.md", + "version": "20260502003", + "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", + "checksum_algorithm": "sha256" + }, + { + "name": "terraform", + "file": "instructions/terraform.instructions.md", + "version": "20260502034", + "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", + "checksum_algorithm": "sha256" + }, + { + "name": "terragrunt", + "file": "instructions/terragrunt.instructions.md", + "version": "20260502035", + "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", + "checksum_algorithm": "sha256" + }, + { + "name": "testing", + "file": "instructions/testing.instructions.md", + "version": "20261026001", + "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", + "checksum_algorithm": "sha256" + }, + { + "name": "typescript", + "file": "instructions/typescript.instructions.md", + "version": "20260502005", + "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", + "checksum_algorithm": "sha256" + } ] } } diff --git a/tests/vstack/cli/test_interface.py b/tests/vstack/cli/test_interface.py index d0069aa6..270c969b 100644 --- a/tests/vstack/cli/test_interface.py +++ b/tests/vstack/cli/test_interface.py @@ -670,6 +670,18 @@ def test_raises_when_depends_on_graph_contains_cycle(self, tmp_path: Path) -> No class TestValidateWorkflowStages: """Tests for CommandLineInterface._validate_workflow_stages.""" + @pytest.mark.parametrize("invalid_stage", [{}, {"role": ""}, {"role": " "}]) + def test_rejects_missing_or_blank_role_with_indexed_diagnostic( + self, invalid_stage: dict + ) -> None: + """Direct validation rejects invalid roles even without the YAML reader.""" + with pytest.raises(ValueError) as error: + CommandLineInterface._validate_workflow_stages([{"role": "product"}, invalid_stage]) + + assert str(error.value) == ( + "Invalid workflow config: workflow.stages[1].role must be a non-empty string" + ) + def test_accepts_linear_workflow_without_explicit_handoffs(self) -> None: """A plain stage list without handoffs is treated as a valid acyclic flow.""" CommandLineInterface._validate_workflow_stages( From 4882e8495f39880c622dd2aad13c0a9179225a7c Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 22:14:43 +0100 Subject: [PATCH 15/16] fix(performance): preserve component paths in baseline worktrees Compare the selected nested component on both revisions instead of benchmarking the repository root. Cover nested paths, user Git state, benchmark failures and components absent from the base revision. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/performance/SKILL.md | 10 +- .vstack/vstack.json | 382 +++++++++--------- docs/design/skills.md | 3 + .../_templates/skills/performance/config.yaml | 2 +- .../_templates/skills/performance/template.md | 8 +- tests/vstack/skills/test_shell_workflows.py | 51 ++- 6 files changed, 254 insertions(+), 202 deletions(-) diff --git a/.github/skills/performance/SKILL.md b/.github/skills/performance/SKILL.md index 94b2c594..e49ea72d 100644 --- a/.github/skills/performance/SKILL.md +++ b/.github/skills/performance/SKILL.md @@ -105,10 +105,11 @@ executed checks with nonzero exit status are `failed`. Keep error output visible ```bash BASE_REF="<base>" +COMPONENT_DIR=$(git rev-parse --show-prefix) || exit $? BASE_DIR=$(mktemp -d) || exit 1 git worktree add --detach "$BASE_DIR/baseline" "$BASE_REF" || exit 1 ( - cd "$BASE_DIR/baseline" || exit 1 + cd "$BASE_DIR/baseline/$COMPONENT_DIR" || exit 1 run_benchmark ) BASE_STATUS=$? @@ -121,7 +122,10 @@ fi ``` Use an isolated worktree; never stash or switch the user's working tree. -Use `run_benchmark` for the same selected command as Phase 1. +Start Phase 2 in the same component directory as Phase 1; preserve its +repository-relative path and use the same `run_benchmark` command. +If the component does not exist at the base revision, report comparison unavailable; +never substitute a root-level benchmark. If benchmarks leave files behind, report the worktree path and inspect them before cleanup. Do not force-remove it or discard user files. @@ -237,4 +241,4 @@ Only measured, comparable results support a regression verdict. ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20261026003","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"performance","artifact_type":"skill","artifact_version":"20261026004","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index a7d7c0d8..060173f2 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,8 +2,196 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T20:44:29.425789+00:00", + "installed_at": "2026-10-26T21:14:43.202748+00:00", "artifacts": { + "agents": [ + { + "name": "architect", + "file": "agents/architect.agent.md", + "version": "20261026001", + "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", + "checksum_algorithm": "sha256" + }, + { + "name": "designer", + "file": "agents/designer.agent.md", + "version": "20261026001", + "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", + "checksum_algorithm": "sha256" + }, + { + "name": "engineer", + "file": "agents/engineer.agent.md", + "version": "20261026001", + "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", + "checksum_algorithm": "sha256" + }, + { + "name": "planner", + "file": "agents/planner.agent.md", + "version": "20261026001", + "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", + "checksum_algorithm": "sha256" + }, + { + "name": "product", + "file": "agents/product.agent.md", + "version": "20261026002", + "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", + "checksum_algorithm": "sha256" + }, + { + "name": "release", + "file": "agents/release.agent.md", + "version": "20261026001", + "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", + "checksum_algorithm": "sha256" + }, + { + "name": "tester", + "file": "agents/tester.agent.md", + "version": "20261026002", + "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", + "checksum_algorithm": "sha256" + } + ], + "hooks": [ + { + "name": "agent-call-audit", + "file": "hooks/agent-call-audit.json", + "version": "4.0.0", + "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", + "checksum_algorithm": "sha256" + }, + { + "name": "log-retention-cleanup", + "file": "hooks/log-retention-cleanup.json", + "version": "4.0.0", + "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", + "checksum_algorithm": "sha256" + }, + { + "name": "post-commit-security-scan", + "file": "hooks/post-commit-security-scan.json", + "version": "4.0.0", + "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", + "checksum_algorithm": "sha256" + }, + { + "name": "post-edit-format", + "file": "hooks/post-edit-format.json", + "version": "4.0.0", + "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", + "checksum_algorithm": "sha256" + }, + { + "name": "post-edit-markdown-quality", + "file": "hooks/post-edit-markdown-quality.json", + "version": "4.0.0", + "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", + "checksum_algorithm": "sha256" + }, + { + "name": "pre-tool-safety-gate", + "file": "hooks/pre-tool-safety-gate.json", + "version": "4.0.0", + "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", + "checksum_algorithm": "sha256" + }, + { + "name": "session-audit", + "file": "hooks/session-audit.json", + "version": "4.0.0", + "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", + "checksum_algorithm": "sha256" + } + ], + "instructions": [ + { + "name": "git", + "file": "instructions/git.instructions.md", + "version": "20260421001", + "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", + "checksum_algorithm": "sha256" + }, + { + "name": "helm", + "file": "instructions/helm.instructions.md", + "version": "20260502040", + "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", + "checksum_algorithm": "sha256" + }, + { + "name": "java", + "file": "instructions/java.instructions.md", + "version": "20260502001", + "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", + "checksum_algorithm": "sha256" + }, + { + "name": "k8s", + "file": "instructions/k8s.instructions.md", + "version": "20260502039", + "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", + "checksum_algorithm": "sha256" + }, + { + "name": "markdown", + "file": "instructions/markdown.instructions.md", + "version": "20260502002", + "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", + "checksum_algorithm": "sha256" + }, + { + "name": "python", + "file": "instructions/python.instructions.md", + "version": "20260421002", + "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", + "checksum_algorithm": "sha256" + }, + { + "name": "rancher", + "file": "instructions/rancher.instructions.md", + "version": "20260502041", + "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", + "checksum_algorithm": "sha256" + }, + { + "name": "security", + "file": "instructions/security.instructions.md", + "version": "20260502003", + "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", + "checksum_algorithm": "sha256" + }, + { + "name": "terraform", + "file": "instructions/terraform.instructions.md", + "version": "20260502034", + "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", + "checksum_algorithm": "sha256" + }, + { + "name": "terragrunt", + "file": "instructions/terragrunt.instructions.md", + "version": "20260502035", + "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", + "checksum_algorithm": "sha256" + }, + { + "name": "testing", + "file": "instructions/testing.instructions.md", + "version": "20261026001", + "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", + "checksum_algorithm": "sha256" + }, + { + "name": "typescript", + "file": "instructions/typescript.instructions.md", + "version": "20260502005", + "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", + "checksum_algorithm": "sha256" + } + ], "skills": [ { "name": "adr", @@ -253,8 +441,8 @@ { "name": "performance", "file": "skills/performance/SKILL.md", - "version": "20261026003", - "checksum": "040b0be42543cbcd3d1476a41a3cb38c7573c18069ccabd8597d8c5b23bd77a0", + "version": "20261026004", + "checksum": "37af3a2c62320d3f20cd6bdeaeaf6b86ad8ca2f516ed9b76ddcdbb93434a191e", "checksum_algorithm": "sha256" }, { @@ -397,194 +585,6 @@ "checksum": "f8066d6f685418671992a75e103b96ce9b18bb0622c656c49ab93d3a382a69fb", "checksum_algorithm": "sha256" } - ], - "agents": [ - { - "name": "architect", - "file": "agents/architect.agent.md", - "version": "20261026001", - "checksum": "ae96b91c872b14f2484fff6cad2ce6190cddd5b5d2983af4b86fb924ac57e633", - "checksum_algorithm": "sha256" - }, - { - "name": "designer", - "file": "agents/designer.agent.md", - "version": "20261026001", - "checksum": "06cbf40147f6a00dcad027f304a67eb3c45c27a4639ddf2266f6f499ac2b93bf", - "checksum_algorithm": "sha256" - }, - { - "name": "engineer", - "file": "agents/engineer.agent.md", - "version": "20261026001", - "checksum": "6f29ff92fc7dd84c49e6ef292932087179908c98b2275259c3b4fd145e3f9c40", - "checksum_algorithm": "sha256" - }, - { - "name": "planner", - "file": "agents/planner.agent.md", - "version": "20261026001", - "checksum": "7871e51eda348cf46abfabfa8b3a1ea274b716bad30e4acdb5a94ee7d6b74bfa", - "checksum_algorithm": "sha256" - }, - { - "name": "product", - "file": "agents/product.agent.md", - "version": "20261026002", - "checksum": "2e5a8c6ae877e04a6053b606670854f221501aa91a86f5676729aad9f8be5e78", - "checksum_algorithm": "sha256" - }, - { - "name": "release", - "file": "agents/release.agent.md", - "version": "20261026001", - "checksum": "a728911476e729ba96886d3018003d2d65b70b30a2a9a453f6b2eff8606c872c", - "checksum_algorithm": "sha256" - }, - { - "name": "tester", - "file": "agents/tester.agent.md", - "version": "20261026002", - "checksum": "5df6ff1f6b8188e48f2cce6331a246b74925e35474eedb1fc45be74980927d5e", - "checksum_algorithm": "sha256" - } - ], - "hooks": [ - { - "name": "agent-call-audit", - "file": "hooks/agent-call-audit.json", - "version": "4.0.0", - "checksum": "a03cc5df031670dd4902599048a9fc955a852862b2cb73408f5889ee74baa636", - "checksum_algorithm": "sha256" - }, - { - "name": "log-retention-cleanup", - "file": "hooks/log-retention-cleanup.json", - "version": "4.0.0", - "checksum": "2c3048637dc0f85b7196934b0f6c5a2ee9a21739b45bc7a529e2f5531f2b2609", - "checksum_algorithm": "sha256" - }, - { - "name": "post-commit-security-scan", - "file": "hooks/post-commit-security-scan.json", - "version": "4.0.0", - "checksum": "154305889deb5676a6b7d686400b14b4237687be130438d19843341addbdff8e", - "checksum_algorithm": "sha256" - }, - { - "name": "post-edit-format", - "file": "hooks/post-edit-format.json", - "version": "4.0.0", - "checksum": "5911a2fc0211b268749e5200db8d43eec953f456294c8cbc5556cea9ab11f875", - "checksum_algorithm": "sha256" - }, - { - "name": "post-edit-markdown-quality", - "file": "hooks/post-edit-markdown-quality.json", - "version": "4.0.0", - "checksum": "b8ef6b1805492a580902675ccd16564c693ec2ccf30fdb81d6b1d8dce610ab22", - "checksum_algorithm": "sha256" - }, - { - "name": "pre-tool-safety-gate", - "file": "hooks/pre-tool-safety-gate.json", - "version": "4.0.0", - "checksum": "1d55d6c9cee6137472e37c9e16febb5a96419fc0813c4c474af5a50ee03ee5a0", - "checksum_algorithm": "sha256" - }, - { - "name": "session-audit", - "file": "hooks/session-audit.json", - "version": "4.0.0", - "checksum": "0190aa65dfea26b2129ad8a5304377b2d40febf03779f561194e788bb8b27bfa", - "checksum_algorithm": "sha256" - } - ], - "instructions": [ - { - "name": "git", - "file": "instructions/git.instructions.md", - "version": "20260421001", - "checksum": "cdceba38ad301bb3e751a0ca4cfc3acb811ea170e0882a541816c0c121ca3503", - "checksum_algorithm": "sha256" - }, - { - "name": "helm", - "file": "instructions/helm.instructions.md", - "version": "20260502040", - "checksum": "a07a1ad6fd64d8f27e39397bb962c303b0c9d6b8e6a5e2e7c63d7334b8c4d0ad", - "checksum_algorithm": "sha256" - }, - { - "name": "java", - "file": "instructions/java.instructions.md", - "version": "20260502001", - "checksum": "7461e0098ba8f517c060378aeb39ba9720f2b5eda9b54cbb73dfe9fe5633d765", - "checksum_algorithm": "sha256" - }, - { - "name": "k8s", - "file": "instructions/k8s.instructions.md", - "version": "20260502039", - "checksum": "801a4ed9eae6492b92b887a092469b38c4f8c204ab73d42c2aebca5c8ac5131b", - "checksum_algorithm": "sha256" - }, - { - "name": "markdown", - "file": "instructions/markdown.instructions.md", - "version": "20260502002", - "checksum": "af3abd860c52d3ee761653e526b4113e8baef64b639471c1ec8fe09de0762729", - "checksum_algorithm": "sha256" - }, - { - "name": "python", - "file": "instructions/python.instructions.md", - "version": "20260421002", - "checksum": "e9b726d7d343379e5636c270e058a04028b67648fbf90468ac315df4b337c066", - "checksum_algorithm": "sha256" - }, - { - "name": "rancher", - "file": "instructions/rancher.instructions.md", - "version": "20260502041", - "checksum": "86551c7caf6bad401962de48ef5ff2bb2cc7260d5cda5971e1062c1eb384fbfe", - "checksum_algorithm": "sha256" - }, - { - "name": "security", - "file": "instructions/security.instructions.md", - "version": "20260502003", - "checksum": "baaaa6d49c38e7ca67cf1a3b0305d911731bd35de54608a5705c6c03f277c882", - "checksum_algorithm": "sha256" - }, - { - "name": "terraform", - "file": "instructions/terraform.instructions.md", - "version": "20260502034", - "checksum": "b698ccff280139a43fb527b5cfd3c5f885bfaf37282ff656c98c0f0682471109", - "checksum_algorithm": "sha256" - }, - { - "name": "terragrunt", - "file": "instructions/terragrunt.instructions.md", - "version": "20260502035", - "checksum": "695b2ecb23f940ad072f208cd78b9be44a58d55c6a348f25166706f735ba515e", - "checksum_algorithm": "sha256" - }, - { - "name": "testing", - "file": "instructions/testing.instructions.md", - "version": "20261026001", - "checksum": "f05a4c6f6a5d20eeb5165f408826553e24754e49f16a1aa058481e5cda620d84", - "checksum_algorithm": "sha256" - }, - { - "name": "typescript", - "file": "instructions/typescript.instructions.md", - "version": "20260502005", - "checksum": "8eddbd79ac24b2419136b8549587efa3d3ba328505c61dd79f02a7463fad6b38", - "checksum_algorithm": "sha256" - } ] } } diff --git a/docs/design/skills.md b/docs/design/skills.md index a96587e4..051d430f 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -154,6 +154,9 @@ See [ADR-033](../architecture/adr/033-lightweight-sdd.md). `performance` benchmarks the base revision in a detached temporary worktree. It preserves the user's branch, index, working files, and existing stashes. +Run both revisions in the same repository-relative component directory. A +component missing from the base revision makes comparison unavailable, not a +reason to benchmark a different root-level project. Failed benchmarks remain failures; leftover benchmark files require inspection before cleanup, never forced removal. Select an existing component-native benchmark runner before execution. Missing diff --git a/src/vstack/_templates/skills/performance/config.yaml b/src/vstack/_templates/skills/performance/config.yaml index b8e3647b..7940bfc9 100644 --- a/src/vstack/_templates/skills/performance/config.yaml +++ b/src/vstack/_templates/skills/performance/config.yaml @@ -1,5 +1,5 @@ name: performance -version: 20261026003 +version: 20261026004 description: | Performance profiling and regression detection. Establishes baselines, detects regressions, profiles bottlenecks, and recommends optimizations. Use when asked diff --git a/src/vstack/_templates/skills/performance/template.md b/src/vstack/_templates/skills/performance/template.md index e53e457b..a84b0997 100644 --- a/src/vstack/_templates/skills/performance/template.md +++ b/src/vstack/_templates/skills/performance/template.md @@ -65,10 +65,11 @@ executed checks with nonzero exit status are `failed`. Keep error output visible ```bash BASE_REF="<base>" +COMPONENT_DIR=$(git rev-parse --show-prefix) || exit $? BASE_DIR=$(mktemp -d) || exit 1 git worktree add --detach "$BASE_DIR/baseline" "$BASE_REF" || exit 1 ( - cd "$BASE_DIR/baseline" || exit 1 + cd "$BASE_DIR/baseline/$COMPONENT_DIR" || exit 1 run_benchmark ) BASE_STATUS=$? @@ -81,7 +82,10 @@ fi ``` Use an isolated worktree; never stash or switch the user's working tree. -Use `run_benchmark` for the same selected command as Phase 1. +Start Phase 2 in the same component directory as Phase 1; preserve its +repository-relative path and use the same `run_benchmark` command. +If the component does not exist at the base revision, report comparison unavailable; +never substitute a root-level benchmark. If benchmarks leave files behind, report the worktree path and inspect them before cleanup. Do not force-remove it or discard user files. diff --git a/tests/vstack/skills/test_shell_workflows.py b/tests/vstack/skills/test_shell_workflows.py index 8e27a9dc..7af6e45a 100644 --- a/tests/vstack/skills/test_shell_workflows.py +++ b/tests/vstack/skills/test_shell_workflows.py @@ -26,8 +26,13 @@ def _bash_block(text: str, heading: str) -> str: @pytest.mark.parametrize("state", ["clean", "unstaged", "staged", "untracked"]) @pytest.mark.parametrize("benchmark_status", [0, 9]) +@pytest.mark.parametrize("component_path", ["", "services/go service"]) def test_performance_baseline_preserves_user_git_state( - tmp_path: Path, generated_dir: Path, state: str, benchmark_status: int + tmp_path: Path, + generated_dir: Path, + state: str, + benchmark_status: int, + component_path: str, ) -> None: """Baseline success and failure leave branches, index, files and stashes intact.""" repo = tmp_path / "user project" @@ -35,9 +40,14 @@ def test_performance_baseline_preserves_user_git_state( _git(repo, "init", "-b", "main") _git(repo, "config", "user.email", "fixture@example.invalid") _git(repo, "config", "user.name", "Fixture") - tracked = repo / "tracked.txt" + component = repo / component_path + component.mkdir(parents=True, exist_ok=True) + (repo / "package.json").write_text("{}", encoding="utf-8") + if component_path: + (component / "go.mod").write_text("module fixture\n", encoding="utf-8") + tracked = component / "tracked.txt" tracked.write_text("base\n", encoding="utf-8") - _git(repo, "add", "tracked.txt") + _git(repo, "add", ".") _git(repo, "commit", "-m", "base") tracked.write_text("older unrelated work\n", encoding="utf-8") _git(repo, "stash", "push", "-m", "unrelated stash") @@ -47,7 +57,7 @@ def test_performance_baseline_preserves_user_git_state( if state in {"unstaged", "staged"}: tracked.write_text("user changes\n", encoding="utf-8") if state == "staged": - _git(repo, "add", "tracked.txt") + _git(repo, "add", str(tracked.relative_to(repo))) if state == "untracked": (repo / "user.txt").write_text("keep me\n", encoding="utf-8") before = ( @@ -66,7 +76,7 @@ def test_performance_baseline_preserves_user_git_state( ) result = subprocess.run( ["bash", "-c", script], - cwd=repo, + cwd=component, env={**os.environ, "TMPDIR": str(tmp_path)}, capture_output=True, text=True, @@ -86,6 +96,37 @@ def test_performance_baseline_preserves_user_git_state( assert (repo / "user.txt").read_text(encoding="utf-8") == "keep me\n" +def test_performance_missing_base_component_does_not_benchmark_root( + tmp_path: Path, generated_dir: Path +) -> None: + """A newly added component cannot produce a false root-level comparison.""" + _git(tmp_path, "init", "-b", "main") + _git(tmp_path, "config", "user.email", "fixture@example.invalid") + _git(tmp_path, "config", "user.name", "Fixture") + (tmp_path / "package.json").write_text("{}", encoding="utf-8") + _git(tmp_path, "add", ".") + _git(tmp_path, "commit", "-m", "base") + _git(tmp_path, "switch", "-c", "feature/new-component") + component = tmp_path / "services" / "new" + component.mkdir(parents=True) + (component / "go.mod").write_text("module fixture\n", encoding="utf-8") + _git(tmp_path, "add", ".") + _git(tmp_path, "commit", "-m", "add component") + text = (generated_dir / "performance" / "SKILL.md").read_text(encoding="utf-8") + script = _bash_block(text, "## Phase 2:").replace('BASE_REF="<base>"', 'BASE_REF="main"') + result = subprocess.run( + ["bash", "-c", "run_benchmark() { echo WRONG_COMPONENT; }\n" + script], + cwd=component, + capture_output=True, + text=True, + ) + assert result.returncode == 1 + assert "baseline benchmark failed" in result.stdout + assert "WRONG_COMPONENT" not in result.stdout + assert _git(tmp_path, "status", "--porcelain") == "" + assert _git(tmp_path, "worktree", "list", "--porcelain").count("worktree ") == 1 + + @pytest.mark.parametrize( ("marker", "runner"), [ From 77386f4e98ee003525e08ae30191a3596a428f81 Mon Sep 17 00:00:00 2001 From: Erik Schaareman <erik@schaareman.org> Date: Mon, 26 Oct 2026 22:15:34 +0100 Subject: [PATCH 16/16] fix(pr): match push repository identity before reusing pull requests Select existing PRs by both head repository and branch in the explicit base repository. Bind push and new PR creation to the verified push destination and cover unrelated forks, repositories, branches and mixed candidate lists. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/pr/SKILL.md | 29 +++++++++-- .vstack/vstack.json | 6 +-- ...weight-sdd_changedoc_evolution_20261017.md | 38 +++++++++++++- docs/design/skills.md | 3 ++ src/vstack/_templates/skills/pr/config.yaml | 2 +- src/vstack/_templates/skills/pr/template.md | 27 ++++++++-- tests/vstack/skills/test_templates.py | 51 ++++++++++++++++--- 7 files changed, 137 insertions(+), 19 deletions(-) diff --git a/.github/skills/pr/SKILL.md b/.github/skills/pr/SKILL.md index b3ae3d0a..796f6db0 100644 --- a/.github/skills/pr/SKILL.md +++ b/.github/skills/pr/SKILL.md @@ -50,7 +50,19 @@ before CI/CD takes over. ## Step 1: Pre-flight +Resolve the configured remote's **push** URL to its GitHub owner/repository +(including SSH aliases), then set `PUSH_REPO` below. Set `BASE_REPO` to the target +repository, which may differ for forks. Confirm both are on the same GitHub host. +Stop on ambiguous or multiple push destinations; never infer push identity from +the fetch URL or branch name alone. Requires `gh` and `jq`. + ```bash +PUSH_REMOTE="origin" +PUSH_REPO="<push-owner>/<push-repo>" +BASE_REPO="<base-owner>/<base-repo>" +PUSH_OWNER=${PUSH_REPO%/*} +git remote get-url --push --all "$PUSH_REMOTE" || exit $? + # Confirm gh CLI is authenticated gh auth status || exit $? @@ -63,8 +75,14 @@ fi echo "Branch: $BRANCH" # Check if a PR already exists for this branch -EXISTING_PR=$(gh pr list --head "$BRANCH" --state open --json url \ - --jq '.[0].url // empty') || exit $? +PR_CANDIDATES=$(gh pr list --repo "$BASE_REPO" --head "$BRANCH" --state open \ + --json url,headRepositoryOwner,headRepository,headRefName) || exit $? +EXISTING_PR=$(printf '%s' "$PR_CANDIDATES" | jq -r \ + --arg repo "$PUSH_REPO" --arg branch "$BRANCH" \ + '[.[] | select( + (.headRepositoryOwner.login + "/" + .headRepository.name) == $repo + and .headRefName == $branch + )] | .[0].url // empty') || exit $? if [ -n "$EXISTING_PR" ]; then echo "Existing PR will be updated after push: $EXISTING_PR" fi @@ -94,7 +112,7 @@ git diff --cached --stat ## Step 3: Push ```bash -git push --set-upstream origin "$BRANCH" || exit $? +git push --set-upstream "$PUSH_REMOTE" "$BRANCH" || exit $? ``` ## Step 4: Reuse or Open PR @@ -115,6 +133,7 @@ Use `--draft` when the work is not yet ready for review. ```bash # Short body (inline): gh pr create \ + --repo "$BASE_REPO" --head "$PUSH_OWNER:$BRANCH" \ --base main \ --title "<title>" \ --body "<body>" @@ -124,12 +143,14 @@ cat > /tmp/pr-body.md <<'EOF' <body> EOF gh pr create \ + --repo "$BASE_REPO" --head "$PUSH_OWNER:$BRANCH" \ --base main \ --title "<title>" \ --body-file /tmp/pr-body.md # Draft PR (not ready for review): gh pr create \ + --repo "$BASE_REPO" --head "$PUSH_OWNER:$BRANCH" \ --base main \ --title "<title>" \ --body "<body>" \ @@ -159,4 +180,4 @@ Next steps depend on the repository CI/CD configuration: ``` <!-- AUTO-GENERATED — maintained by vstack, do not edit directly --> -<!-- VSTACK-META: {"artifact_name":"pr","artifact_type":"skill","artifact_version":"20261026002","generator":"vstack","vstack_version":"4.0.0"} --> +<!-- VSTACK-META: {"artifact_name":"pr","artifact_type":"skill","artifact_version":"20261026003","generator":"vstack","vstack_version":"4.0.0"} --> diff --git a/.vstack/vstack.json b/.vstack/vstack.json index 060173f2..fb4c50bf 100644 --- a/.vstack/vstack.json +++ b/.vstack/vstack.json @@ -2,7 +2,7 @@ "manifest_version": 2, "hash_algorithm": "sha256", "vstack_version": "4.0.0", - "installed_at": "2026-10-26T21:14:43.202748+00:00", + "installed_at": "2026-10-26T21:15:34.969954+00:00", "artifacts": { "agents": [ { @@ -455,8 +455,8 @@ { "name": "pr", "file": "skills/pr/SKILL.md", - "version": "20261026002", - "checksum": "39fdf1f0df977b9dc71f47d637cea90febd312ebaa8a054687c5def7c7d653eb", + "version": "20261026003", + "checksum": "9265be80e0652dbce7a65233fbefceaeb405dae5ce8a7df93e99de6396df3cc1", "checksum_algorithm": "sha256" }, { diff --git a/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md b/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md index 413d757b..d47791c3 100644 --- a/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md +++ b/docs/changes/lightweight-sdd_changedoc_evolution_20261017.md @@ -388,7 +388,8 @@ adoption reliability remains a follow-up, not a claimed deterministic result. - Focused template/role/instruction/install regressions passed. - `make check` passed: formatting, Markdown lint, Ruff, mypy, and all tests on Python 3.14 with 100% code coverage. Python 3.11, 3.12, 3.13, and 3.15 were - **not run** because their interpreters are unavailable; tox reported skips. + **not run** in the initial check because tox could not discover their + interpreters; the final verification below supersedes this limitation. - `vstack validate`, regeneration with `vstack install`, and `vstack verify` passed using the local interpreter and `PYTHONPATH=src`. - Four affected golden fixtures were regenerated from source. Existing installed @@ -406,6 +407,41 @@ decreased. These are reproducible text-size proxies, not tokenizer measurements or guaranteed credit/session-cost savings. Regression limits retain the original aggregate ceilings rather than requiring every individual artifact to shrink. +### Final verification and scope closure (2026-10-26) + +The agreed lightweight SDD change is **IMPLEMENTED**. The initial evidence above +remains a historical snapshot; the following results cover the stabilized PR +working tree based on `4882e8495f39` and the fork-safe PR fix originally reviewed +as `e03d82f378f9` (this documentation-only amendment changes that commit ID). + +- **Passed:** `PATH="$HOME/.pyenv/shims:$PATH" make check`: 793 tests on each of + Python 3.11, 3.12, 3.13, 3.14, and 3.15, with 100% coverage per runtime. + Formatting, Markdown lint, Ruff, and mypy passed. The earlier skips were a + discovery/PATH issue, not missing pyenv installations. +- **Passed:** source validation and installed artifact verification after + regenerating the affected skills and manifest. +- **Passed:** wheel and sdist builds at the preceding stabilization revision + `a93986e31383` (later reworded as `541ee6489ae1` without tree changes), followed + by fresh wheel install, verify, reinstall, verify, and uninstall outside the + checkout under Python isolated mode. Subsequent component-path and PR-identity + fixes were verified by executable regressions and CI artifact install checks; + this package result is not a claim of a new wheel test after those fixes. +- **Passed:** all applicable Actions on + [PR #121](https://github.com/eschaar/vstack/pull/121), including the Python + matrix, artifact checks, commit validation, quality checks, security scan, + and CodeQL. The Dependabot-only auto-merge job was correctly skipped. +- Both Copilot findings were fixed in separate commits, with executable + regressions and regenerated skills: + [nested-component comparison](https://github.com/eschaar/vstack/pull/121#discussion_r4382529741) + and [fork-safe PR reuse](https://github.com/eschaar/vstack/pull/121#discussion_r4382529800). + Both review threads were resolved. +- Actual credit-consumption measurement and live Copilot delivery scenarios + are explicitly **outside the user-approved scope**, not unfinished acceptance + work or claimed passes. Autonomous adherence remains unproven. + +This records implementation completion, not merge or release. The +documentation-only amendment must pass its own PR checks before merging. + ## Notes ### Decisions Approved diff --git a/docs/design/skills.md b/docs/design/skills.md index 051d430f..bee02de8 100644 --- a/docs/design/skills.md +++ b/docs/design/skills.md @@ -175,6 +175,9 @@ not replace operational checks. `pr` pushes approved task commits before reusing an existing PR. Authentication, lookup, or push failures stop the procedure. Commit explicit reviewed paths with an intent-specific Conventional Commit; never stage unrelated work. +Resolve the actual push destination (not just the fetch remote); match both head +repository and branch before reusing a PR. Fork PRs are looked up and created in +the explicit base repository. Ambiguous push destinations require clarification. ______________________________________________________________________ diff --git a/src/vstack/_templates/skills/pr/config.yaml b/src/vstack/_templates/skills/pr/config.yaml index 7083baa9..c390bd04 100644 --- a/src/vstack/_templates/skills/pr/config.yaml +++ b/src/vstack/_templates/skills/pr/config.yaml @@ -1,5 +1,5 @@ name: pr -version: 20261026002 +version: 20261026003 description: | Commit, push, and open a pull request from the current branch to main. Updates an existing PR after pushing; uses the repository PR template for new PRs. diff --git a/src/vstack/_templates/skills/pr/template.md b/src/vstack/_templates/skills/pr/template.md index 0008d669..aa652c59 100644 --- a/src/vstack/_templates/skills/pr/template.md +++ b/src/vstack/_templates/skills/pr/template.md @@ -17,7 +17,19 @@ before CI/CD takes over. ## Step 1: Pre-flight +Resolve the configured remote's **push** URL to its GitHub owner/repository +(including SSH aliases), then set `PUSH_REPO` below. Set `BASE_REPO` to the target +repository, which may differ for forks. Confirm both are on the same GitHub host. +Stop on ambiguous or multiple push destinations; never infer push identity from +the fetch URL or branch name alone. Requires `gh` and `jq`. + ```bash +PUSH_REMOTE="origin" +PUSH_REPO="<push-owner>/<push-repo>" +BASE_REPO="<base-owner>/<base-repo>" +PUSH_OWNER=${PUSH_REPO%/*} +git remote get-url --push --all "$PUSH_REMOTE" || exit $? + # Confirm gh CLI is authenticated gh auth status || exit $? @@ -30,8 +42,14 @@ fi echo "Branch: $BRANCH" # Check if a PR already exists for this branch -EXISTING_PR=$(gh pr list --head "$BRANCH" --state open --json url \ - --jq '.[0].url // empty') || exit $? +PR_CANDIDATES=$(gh pr list --repo "$BASE_REPO" --head "$BRANCH" --state open \ + --json url,headRepositoryOwner,headRepository,headRefName) || exit $? +EXISTING_PR=$(printf '%s' "$PR_CANDIDATES" | jq -r \ + --arg repo "$PUSH_REPO" --arg branch "$BRANCH" \ + '[.[] | select( + (.headRepositoryOwner.login + "/" + .headRepository.name) == $repo + and .headRefName == $branch + )] | .[0].url // empty') || exit $? if [ -n "$EXISTING_PR" ]; then echo "Existing PR will be updated after push: $EXISTING_PR" fi @@ -61,7 +79,7 @@ git diff --cached --stat ## Step 3: Push ```bash -git push --set-upstream origin "$BRANCH" || exit $? +git push --set-upstream "$PUSH_REMOTE" "$BRANCH" || exit $? ``` ## Step 4: Reuse or Open PR @@ -82,6 +100,7 @@ Use `--draft` when the work is not yet ready for review. ```bash # Short body (inline): gh pr create \ + --repo "$BASE_REPO" --head "$PUSH_OWNER:$BRANCH" \ --base main \ --title "<title>" \ --body "<body>" @@ -91,12 +110,14 @@ cat > /tmp/pr-body.md <<'EOF' <body> EOF gh pr create \ + --repo "$BASE_REPO" --head "$PUSH_OWNER:$BRANCH" \ --base main \ --title "<title>" \ --body-file /tmp/pr-body.md # Draft PR (not ready for review): gh pr create \ + --repo "$BASE_REPO" --head "$PUSH_OWNER:$BRANCH" \ --base main \ --title "<title>" \ --body "<body>" \ diff --git a/tests/vstack/skills/test_templates.py b/tests/vstack/skills/test_templates.py index 7eff59c4..07414aad 100644 --- a/tests/vstack/skills/test_templates.py +++ b/tests/vstack/skills/test_templates.py @@ -2,6 +2,7 @@ from __future__ import annotations +import json import os import re import subprocess @@ -14,10 +15,12 @@ from vstack.frontmatter import FrontmatterParser -@pytest.mark.parametrize("existing_pr", ["", "https://example.invalid/pull/1"]) +@pytest.mark.parametrize( + "candidate_kind", ["none", "other-fork", "other-repo", "other-branch", "matching"] +) @pytest.mark.parametrize("push_status", [0, 7]) def test_pr_recipe_pushes_before_reusing_existing_pr( - tmp_path: Path, generated_dir: Path, existing_pr: str, push_status: int + tmp_path: Path, generated_dir: Path, candidate_kind: str, push_status: int ) -> None: """Existing and new PR paths push first and never hide push failures.""" text = (generated_dir / "pr" / "SKILL.md").read_text(encoding="utf-8") @@ -25,18 +28,49 @@ def test_pr_recipe_pushes_before_reusing_existing_pr( for heading in ("## Step 1:", "## Step 3:", "## Step 4:"): match = re.search(r"```bash\n(.*?)```", text.split(heading, 1)[1], re.DOTALL) assert match is not None - blocks.append(match.group(1)) + blocks.append( + match.group(1) + .replace("<push-owner>/<push-repo>", "contributor/fork") + .replace("<base-owner>/<base-repo>", "upstream/project") + ) stubs = """ git() { case "$1" in branch) echo feature/example ;; - push) echo push >> "$CALL_LOG"; return "$PUSH_STATUS" ;; + push) + test "$*" = "push --set-upstream origin feature/example" || return 99 + echo push >> "$CALL_LOG"; return "$PUSH_STATUS" ;; esac } gh() { - if [ "$1 $2" = "pr list" ]; then printf '%s' "$EXISTING_URL"; fi + if [ "$1 $2" = "pr list" ]; then + test "$3 $4" = "--repo upstream/project" || return 99 + printf '%s' "$PR_CANDIDATES_JSON" + fi } """ + candidate = { + "url": "https://example.invalid/pull/1", + "headRepositoryOwner": {"login": "contributor"}, + "headRepository": {"name": "fork"}, + "headRefName": "feature/example", + } + if candidate_kind == "other-fork": + candidate["headRepositoryOwner"] = {"login": "unrelated"} + elif candidate_kind == "other-repo": + candidate["headRepository"] = {"name": "another"} + elif candidate_kind == "other-branch": + candidate["headRefName"] = "feature/different" + candidates = [] if candidate_kind == "none" else [candidate] + if candidate_kind == "matching": + candidates.insert( + 0, + { + **candidate, + "url": "https://example.invalid/pull/unrelated", + "headRepositoryOwner": {"login": "unrelated"}, + }, + ) log = tmp_path / "calls.txt" result = subprocess.run( ["bash", "-c", stubs + "\n".join(blocks) + '\necho create >> "$CALL_LOG"'], @@ -45,15 +79,18 @@ def test_pr_recipe_pushes_before_reusing_existing_pr( **os.environ, "CALL_LOG": str(log), "PUSH_STATUS": str(push_status), - "EXISTING_URL": existing_pr, + "PR_CANDIDATES_JSON": json.dumps(candidates), }, capture_output=True, text=True, ) assert result.returncode == push_status, result.stdout + result.stderr assert log.read_text(encoding="utf-8").splitlines() == ( - ["push", "create"] if not existing_pr and push_status == 0 else ["push"] + ["push", "create"] if candidate_kind != "matching" and push_status == 0 else ["push"] ) + if candidate_kind == "matching" and push_status == 0: + assert "PR updated: https://example.invalid/pull/1" in result.stdout + assert "PR updated: https://example.invalid/pull/unrelated" not in result.stdout assert "git add -A\n" not in text assert 'git commit -m "chore: pre-release cleanup"' not in text