Contracts

cli-flow-contract.md

CLI Flow Contract — Charter Golden-Path E2E (Tranche 1)

This document is the authoritative contract between the test and the public CLI surface. The test is the consumer; spec-kitty is the provider. If the live CLI deviates from this contract at implementation time, the deviation is recorded under spec FR-021 in the PR description (not silently absorbed).

Forbidden surface (C-001, C-002)

The test MUST NOT import, call, or reference any of the following symbols:

  • decide_next_via_runtime
  • _dispatch_via_composition
  • StepContractExecutor
  • run_terminus
  • apply_proposals
  • ProfileInvocationExecutor (the writer; the test reads its output, never calls it)
  • Any private member of specify_cli.next._internal_runtime or sibling internal-only modules.

The test MUST NOT monkeypatch the dispatcher, executor, DRG resolver, or frozen-template loader.

Public CLI surface contract (in flow order)

Step 1 — Project bootstrap

SubprocessArgsEnvExpected exitExpected post-state
gitinit -b maininherit0.git/HEAD present, on main
gitconfig user.email e2e@example.cominherit0git config
gitconfig user.name "E2E Test"inherit0git config
spec-kittyinit . --ai codex --non-interactiveisolated (run_cli)0.kittify/ exists; .gitignore present
gitadd .inherit0staged
gitcommit -m "Initial spec-kitty init"inherit0commit on main

Step 2 — Charter governance

SubprocessArgsExpected exitExpected post-state
spec-kittycharter interview --profile minimal --defaults --json0parseable JSON; interview answers cached under .kittify/charter/
spec-kittycharter generate --from-interview --json0parseable JSON; .kittify/charter/charter.md exists
spec-kittycharter bundle validate --json0parseable JSON; success / compliance indicator
spec-kittycharter synthesize --adapter fixture --dry-run --json0parseable JSON; .kittify/doctrine/ does NOT exist (or is unchanged from pre-call snapshot)
spec-kittycharter synthesize --adapter fixture --json0parseable JSON; .kittify/doctrine/ exists with provenance/manifest
spec-kittycharter status --json0parseable JSON; non-error state
spec-kittycharter lint --json0 (or documented warning-only non-zero)parseable JSON; no silent error downgrade

Step 3 — Mission scaffolding

SubprocessArgsExpected exitExpected post-state
spec-kittyagent mission create "<slug>" --mission-type software-dev --friendly-name "<title>" --purpose-tldr "<…>" --purpose-context "<…>" --json0JSON result == "success"; kitty-specs/<slug>/spec.md and meta.json present
spec-kittyagent mission setup-plan --mission <slug> --json0JSON result == "success"; kitty-specs/<slug>/plan.md present
(test)inline-write minimal spec.md, tasks.md, tasks/WP01-*.md, meta.json updates per smoke recipen/afiles present
gitadd . then commit -m "Seed minimal mission"0clean working tree
spec-kittyagent mission finalize-tasks --mission <slug> --json0JSON result == "success"; WP01 frontmatter contains dependencies field

Step 4 — next issue and advance

SubprocessArgsExpected exitExpected post-state
spec-kittynext --agent test-agent --mission <slug> --json (query mode)0parseable JSON; step_id (or equivalent) present; prompt-file field non-null when exposed
spec-kittynext --agent test-agent --mission <slug> --result success --json0parseable JSON; advancement decision OR documented structured "blocked / missing guard" envelope

After step 4, <temp-project>/.kittify/events/profile-invocations/ contains at least one JSONL file with paired started / completed records for the issued action.

Step 5 — Retrospect

SubprocessArgsExpected exitExpected post-state
spec-kittyretrospect summary --project <temp-project> --json0parseable JSON object; no mutation of temp project state

Step 6 — Source-checkout pollution guard

This step has no subprocess; it's a read-only assertion against the source checkout:

assert post_status == pre_status                     # FR-017
assert post_inventory == pre_inventory               # FR-018

where inventory = recursive listing of REPO_ROOT/{kitty-specs,.kittify,.worktrees,docs} plus any **/profile-invocations/ paths.

Non-contract behaviours (the test must NOT depend on these)

  • The exact text of charter lint warnings.
  • The order of fields in any --json envelope.
  • The on-disk format of .kittify/charter/generated/ artifacts (the fixture adapter owns this; the test only asserts post-promote .kittify/doctrine/ presence).
  • The specific composed action issued by next for a freshly-finalized software-dev mission. The test asserts the action is structurally valid (step_id present, prompt-file present, paired lifecycle records emitted with matching action name) but does NOT hard-code which step is first.

Failure-diagnostics contract (FR-019, NFR-004)

On any subprocess returning a non-expected exit code, the assertion message MUST include at minimum:

command: spec-kitty <args>
cwd:     <path>
rc:      <int>
stdout:  <captured>
stderr:  <captured>

A compact non-recursive directory listing of the temp project MAY be appended.

Bulk-edit contract

Not applicable. This mission is change_mode: normal (no change_mode key set in meta.json ⇒ default normal). No occurrence_map.yaml is required.