Work Packages: CLI Acceptance Scenarios & Cucumber-JVM Nightly

Inputs: Design documents from kitty-specs/cli-acceptance-bdd-nightly-01M4NZRJ/ Prerequisites: plan.md (required), spec.md, research.md (grounding), data-model.md, quickstart.md

Tests: This mission's product is a test surface. Scenario authoring (WP02) and the Java harness tests (WP04) are the deliverable; WP05/WP08 add red-first Python tests for the guard and the packaging exclusion. Normal ATDD discipline applies.

Organization: Fine-grained subtasks (Txxx) roll up into work packages (WPxx), derived from the plan's Implementation Concern Map (IC-01…IC-07).

Subtask Format: [Txxx] [P?] Description

spec-kitty agent tasks mark-status <Txxx> --status done.

  • [P] indicates the subtask can proceed in parallel (different files/components).
  • Subtasks are reference rows, not checkboxes: record completion with

Path Conventions

  • CLI source under test: src/specify_cli/ (black-box only — never imported by the runner).
  • New scenario corpus: tests/scenarios/. New JVM runner: acceptance-jvm/.
  • CI: .github/workflows/. Packaging: pyproject.toml + tests/cross_cutting/packaging/.

Work Package WP01: ADR amendment — record the owner ruling (Priority: P0)

Goal: Amend ADR 2026-10-11-3 to record the 2026-10-11 owner ruling narrowing promise machinery out of core. This is the mission's first deliverable. Independent Test: The ADR carries an Amendment section stating the four narrowed items and the scenarios-gates-no-job flip; the original Decision text is preserved. Prompt: /tasks/WP01-adr-amendment.md Requirement Refs: FR-001, FR-014, C-003

Included Subtasks

T001 Add an "Amendment (2026-10-11 owner ruling)" section recording that the promise index (tests/scenarios/promise-index.json), the per-PR promise-tag check (tests/architectural/test_scenario_promise_tags.py) and PROMISE_INDEX_SYNC_TOKEN are out of core scope (spec-kitty-qa owns them) and were never built T002 Record the consequences: the scenarios ci-router group gates no job (was "gates the architectural job"); acceptance_jvm gates no job; @promise/@defect/@qa are inert in core; only @wip/@manual affect the nightly filter; @manual is an allowed tag T003 Preserve the original Decision text and update the Status/front-matter note to point at the amendment, keeping the ADR internally coherent

Dependencies

  • None (can land first).

Risks & Mitigations

  • Rewriting rather than amending history → keep the original Decision intact; add an Amendment section only.

Work Package WP02: Seed init scenarios + corpus layout (Priority: P1) 🎯 MVP

Goal: Establish tests/scenarios/<area>/ and author the two bound, untagged init scenarios drawn verbatim from init_help.py. Independent Test: Both scenarios parse as valid Gherkin and encode the idempotent-restore and no-git promises with same-fixture positive controls. Prompt: /tasks/WP02-seed-init-scenarios.md Requirement Refs: FR-002, FR-003, FR-004, SC-002

Included Subtasks

T004 Create the tests/scenarios/init/ area layout T005 Author scenario "re-running init keeps project state, only restores missing skill roots" with a same-fixture positive control (a deleted skill root is restored; an untouched root + other project state stay unchanged) — bound, untagged T006 Author scenario "init never runs git init or commits" with a same-fixture positive control (project files ARE created; repository HEAD + commit count unchanged; no new .git) — bound, untagged T007 [P] Fix the Gherkin step vocabulary so WP04's step definitions can bind it (shared step language)

Dependencies

  • None. Must be git-tracked before/with WP07 (glob-is-live gate).

Risks & Mitigations

  • Vacuous ratchet → each scenario pairs its unchanged/absent assertion with a positive control on the same fixture.

Work Package WP03: acceptance-jvm Gradle scaffolding + supply-chain pinning (Priority: P1)

Goal: Stand up the acceptance-jvm/ Gradle subproject mirroring the contracts/ pinning precedent, wired for Cucumber-JVM 7 on the JUnit Platform (Java 25), reading ../tests/scenarios in place. Independent Test: gradle help runs under the pinned, checksum-verified Gradle with no committed wrapper jar; verification-metadata.xml is present and Gradle-generated. Prompt: /tasks/WP03-acceptance-jvm-scaffolding.md Requirement Refs: FR-005, FR-006, C-006, NFR-003

Included Subtasks

T008 Create acceptance-jvm/settings.gradle (names the subproject; documents "no committed wrapper jar") and acceptance-jvm/build.gradle (Cucumber-JVM 7, JUnit Platform, allure-cucumber7-jvm; Java 25 toolchain; cucumber tag-filter system property; test resources point at ../tests/scenarios) T009 Create acceptance-jvm/tools/pins.json (Gradle 8.14.5 + its pinned sha256, mirroring contracts/tools/pins.json) and a README noting reuse of contracts/tools/install_tools.py and the metadata-generation command T010 Generate and commit acceptance-jvm/gradle/verification-metadata.xml via gradle --write-verification-metadata sha256 … --no-daemon

Dependencies

  • None. Must be git-tracked before/with WP07 (glob-is-live gate).

Risks & Mitigations

  • Hand-editing verification-metadata.xml → always regenerate; it carries origin="Generated by Gradle".

Work Package WP04: SpecKittyDriver port, process driver, isolation & runner (Priority: P1) 🎯 MVP

Goal: The black-box harness: a SpecKittyDriver port, a CliProcessDriver, per-scenario isolated env + temp git repo, the wheel-under-test provisioning, step definitions for the two init scenarios, and the JUnit-Platform Cucumber runner. Independent Test: Running gradle test locally executes both init scenarios against a uv build wheel in a temp venv and reports Cucumber/JUnit results, touching no real home state. Prompt: /tasks/WP04-driver-and-runner.md Requirement Refs: FR-007, FR-008, FR-009, C-001, C-002, NFR-002, SC-004

Included Subtasks

T011 Define the SpecKittyDriver port (run a command → exit code, stdout, stderr, parsed --json, working tree) T012 Implement CliProcessDriver with ProcessBuilder: drained streams, timeout, descendant-process kill, line-ending normalisation, real-path comparison T013 Provision the CLI under test: uv build wheel installed into a temporary venv (never PyPI, never editable); invoked only through the driver T014 Per-scenario isolated environment + temp git repo (SPEC_KITTY_HOME/HOME/USERPROFILE/XDG/LOCALAPPDATA inside the temp dir; UTF-8, NO_COLOR, fixed COLUMNS) with the NFR-002 positive control T015 Step definitions binding the two init scenarios' Gherkin to the driver (no Python import; no internal Java) T016 JUnit-Platform Cucumber runner + Allure reporter honouring the not @wip and not @manual / @wip tag filters

Dependencies

  • Depends on WP02 (scenarios to bind/execute) and WP03 (build.gradle to compile).

Risks & Mitigations

  • Cross-OS process/path/line-ending differences, descendant-kill on Windows → centralise in CliProcessDriver; assert on normalised output.

Work Package WP05: Generalize the shared Gradle pin-drift guard (Priority: P2)

Goal: Extend contracts/tools/gradle_pin_check.py to also scan acceptance-jvm/ and the acceptance-bdd nightly job's gradle-version, keeping one canonical GRADLE_PIN_MISMATCH authority (decision DM-01M4P2B3). Independent Test: The guard fails GRADLE_PIN_MISMATCH on injected acceptance-jvm pin drift and passes when pins match; contracts/ behaviour is unchanged. Prompt: /tasks/WP05-generalize-gradle-pin-guard.md Requirement Refs: NFR-003

Included Subtasks

T017 Generalize gradle_pin_check.py to scan acceptance-jvm/ (build.gradle gradle refs, tools/pins.json, gradle/verification-metadata.xml) and the acceptance-bdd workflow step's gradle-version, with contracts/ behaviour byte-identical T018 Add red-first unit tests in tests/contract/test_gradle_pin_check.py for the new scan paths (matching pins pass; injected drift fails) using fixtures

Dependencies

  • Depends on WP03 (acceptance-jvm pins exist to scan).

Risks & Mitigations

  • Shared-gate regression → keep contracts/ scan paths and codes untouched; add coverage for new paths only.

Work Package WP06: Nightly acceptance-bdd job (3 OSes) (Priority: P2)

Goal: Add an acceptance-bdd job to ci-nightly.yml on a Linux/macOS/Windows matrix: a gating run (not @wip and not @manual, no retries) and a separate non-gating @wip run; upload Cucumber JSON, JUnit XML and Allure results; run the generalized pin-guard as a pre-step. Independent Test: The job definition parses; the matrix is 3 OSes; the gating step uses the correct tag filter and no retries; artifacts are uploaded under named keys. Prompt: /tasks/WP06-nightly-acceptance-bdd-job.md Requirement Refs: FR-010, FR-011, FR-014, NFR-001, NFR-004, NFR-005, SC-001

Included Subtasks

T019 Add the acceptance-bdd job (3-OS matrix): build the wheel (uv build), install the pinned Gradle via contracts/tools/install_tools.py --pins acceptance-jvm/tools/pins.json, set up JDK 25, run the gating (not @wip and not @manual, 0 retries) and the non-gating @wip runs T020 Upload Cucumber JSON, JUnit XML and Allure results as named artifacts for the spec-kitty-qa nightly T021 Run the generalized gradle_pin_check.py as a pre-step; leave the job out of nightly-summary.needs (verify release-readiness.yml / tests/release/test_release_ci_ownership.py do not require it)

Dependencies

  • Depends on WP04 (runner to invoke) and WP05 (generalized guard).

Risks & Mitigations

  • Hot file, first multi-OS nightly job → keep the job additive and self-contained; confirm release/ownership tests don't freeze the nightly job set.

Work Package WP07: Non-gating ci-router groups (Priority: P2)

Goal: Add scenarios (tests/scenarios/) and acceptance_jvm (acceptance-jvm/) to the ci-router, gating no per-PR job, and register them in the coherence gate's deliberately-ungated set. Independent Test: gate_selection parses both groups; no job if: references them; test_workflow_coherence and the transcription guards stay green. Prompt: /tasks/WP07-ci-router-nongating-groups.md Requirement Refs: FR-012, C-005, NFR-004, SC-003

Included Subtasks

T022 Add scenarios + acceptance_jvm to the dorny filter block and the changes.outputs block of ci-router.yml; gate no job; keep both out of the unmatched union (non-src) T023 Add "scenarios" and "acceptance_jvm" to _DELIBERATELY_UNGATED_FILTER_GROUPS in tests/architectural/test_workflow_coherence.py; confirm the transcription guards (test_changes_outputs_cover_every_routing_group, test_unmatched_union_covers_every_src_backed_group) pass

Dependencies

  • Depends on WP02 and WP03 (both globs must match git-tracked paths — FR-003c glob-is-live).

Risks & Mitigations

  • Hot file (54 commits/90d) → keep the diff minimal/additive; the frozenset exemption is honest (both genuinely gate no job).

Work Package WP08: sdist exclusion + packaging assertion (Priority: P2)

Goal: Exclude acceptance-jvm/ and tests/scenarios/ from the sdist and assert it (with a same-fixture positive control) in test_packaging_safety.py. Independent Test: A built sdist contains neither tree; a src/ package IS present (positive control); the wheel is unchanged. Prompt: /tasks/WP08-sdist-exclude-and-assert.md Requirement Refs: FR-013, C-004

Included Subtasks

T024 Add "acceptance-jvm/" and "tests/scenarios/" to [tool.hatch.build.targets.sdist].exclude in pyproject.toml T025 Add a @pytest.mark.slow assertion in tests/cross_cutting/packaging/test_packaging_safety.py (reusing the build_artifacts fixture) that both trees are absent from the sdist, paired with a positive control that a src/ package IS present

Dependencies

  • Depends on WP02 and WP03 (both trees must exist so the exclusion is exercised non-vacuously).

Risks & Mitigations

  • Second sdist build cost → reuse the existing build_artifacts session fixture; keep the test in the slow tier.

Dependency & Execution Summary

  • Sequence: WP01 ∥ WP02 ∥ WP03 (no deps) → WP04 (needs WP02+WP03), WP05 (needs WP03) → WP06 (needs WP04+WP05), WP07 (needs WP02+WP03), WP08 (needs WP02+WP03).
  • Parallelization: WP01, WP02, WP03 can run concurrently. After WP02+WP03 land, WP07 and WP08 can run alongside WP04/WP05.
  • MVP Scope: WP02 + WP03 + WP04 + WP06 deliver US-1 (write a scenario, see it run nightly cross-OS). WP01 is the mandated first deliverable; WP05/WP07/WP08 are the governance/CI/packaging guards.

Requirements Coverage Summary

Requirement IDCovered By Work Package(s)
FR-001WP01
FR-002WP02
FR-003WP02
FR-004WP02
FR-005WP03
FR-006WP03
FR-007WP04
FR-008WP04
FR-009WP04
FR-010WP06
FR-011WP06
FR-012WP07
FR-013WP08
FR-014WP01, WP06
NFR-001WP06
NFR-002WP04
NFR-003WP03, WP05
NFR-004WP06, WP07
NFR-005WP06
C-001WP04
C-002WP04
C-003WP01
C-004WP08
C-005WP07
C-006WP03
SC-001WP06
SC-002WP02
SC-003WP07
SC-004WP04

Subtask Index (Reference)

Subtask IDSummaryWork PackagePriorityParallel?
T001ADR amendment: narrowed itemsWP01P0No
T002ADR amendment: consequences/tagsWP01P0No
T003Preserve original Decision; coherenceWP01P0No
T004tests/scenarios/init/ layoutWP02P1No
T005Scenario: idempotent restoreWP02P1No
T006Scenario: never git-init/commitWP02P1No
T007Align step vocabularyWP02P1Yes
T008settings.gradle + build.gradleWP03P1No
T009pins.json + READMEWP03P1No
T010Generate verification-metadata.xmlWP03P1No
T011SpecKittyDriver portWP04P1No
T012CliProcessDriverWP04P1No
T013Wheel-under-test provisioningWP04P1No
T014Isolated env + temp git repoWP04P1No
T015Step definitionsWP04P1No
T016JUnit/Cucumber runner + AllureWP04P1No
T017Generalize gradle_pin_check.pyWP05P2No
T018Pin-check unit testsWP05P2No
T019acceptance-bdd job (3 OS)WP06P2No
T020Upload results artifactsWP06P2No
T021Pin-check pre-step; summary wiringWP06P2No
T022ci-router filter + outputs groupsWP07P2No
T023Coherence frozenset + guardsWP07P2No
T024pyproject sdist excludeWP08P2No
T025Packaging assertion + positive controlWP08P2No