specsail 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable SpecSail changes are recorded here.
4
+
5
+ ## 0.1.0 — 2026-10-20
6
+
7
+ - First public release of the SpecSail methodology and Node.js CLI.
8
+ - Add the Captain-led crew: Scout, Navigator, Quartermaster, Hands, First Mate, and Bosun.
9
+ - Add merge-safe project initialization, feature scaffolding, and setup diagnostics.
10
+ - Include stack-neutral templates, portable Markdown skills, and optional Bash helpers.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Seija
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,81 @@
1
- # Temporary Holding Version
1
+ # SpecSail
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **A spec-driven AI development crew.**
4
+
5
+ > **Navigate by spec. Deliver with confidence.**
6
+
7
+ SpecSail gives developers a repeatable, human-led way to work with AI coding agents: capture the request, approve the spec, plan the work, approve tests, implement one task at a time, review independently, and ship. The durable artifacts live in your repository—not in chat history.
8
+
9
+ ## The crew
10
+
11
+ | Stage | Development role | Sailing alias | Responsibility |
12
+ |---|---|---|---|
13
+ | Understand | Product Owner | **Scout** | Clarifies the request and records routing, constraints, and open questions. |
14
+ | Plan | Tech Lead | **Navigator** | Writes the spec, then the technical plan and thin tasks. |
15
+ | Acceptance tests | QA | **Quartermaster** | Encodes approved criteria as observable tests before implementation. |
16
+ | Implement | Developer | **Hands** | Implements one planned task and runs project verification. |
17
+ | Review | Reviewer | **First Mate** | Independently checks behavior, evidence, scope, and invariants. |
18
+ | Ship | Release | **Bosun** | Updates release docs and prepares the pull request. |
19
+
20
+ The **Captain is always human**: the Captain resolves questions, approves the spec, approves phase acceptance tests, and merges. Agents can prepare a gate; they cannot pass it.
21
+
22
+ ## Quick start
23
+
24
+ Requires Node.js 20+ for the CLI. No runtime dependencies.
25
+
26
+ ```sh
27
+ npx specsail init
28
+ npx specsail doctor
29
+ npx specsail new password-reset new
30
+ ```
31
+
32
+ `init` adds the kit without replacing existing project files. It installs skills and scripts under `.specsail/`, adds a marked section to `AGENTS.md`, and creates project templates only when the destination does not already exist. It writes the installed version to `.specsail.json`.
33
+
34
+ Then fill in `docs/project.md` and `docs/architecture.md`, configure the generated `Makefile` targets for your stack, and add your Captain/team to `.github/CODEOWNERS`. Start the crew by reading `.specsail/docs/runbook.md`.
35
+
36
+ ### Use with your coding tool
37
+
38
+ SpecSail does not require a vendor-specific agent integration. Use any coding tool that can read repository instructions and Markdown files; follow the stage's `SKILL.md` directly if your tool does not discover skills automatically. The optional Bash headless runner supports Claude, Codex, and OpenCode CLIs, but it is not required.
39
+
40
+ For tools using the Agent Skills convention, you can also install a skill from this repository, for example:
41
+
42
+ ```sh
43
+ npx skills add dseija/specsail --skill understand
44
+ ```
45
+
46
+ ## The flow
47
+
48
+ ```text
49
+ request → Captain-approved spec → plan → Captain-approved phase tests
50
+ → implement one task → independent review → PR → Captain merges
51
+ ```
52
+
53
+ The plan is approved before acceptance tests are written. Tests are approved per phase before implementation starts. Bug fixes can use a shorter path; trivial changes can use a normal PR and the project's `make verify`.
54
+
55
+ ## Commands
56
+
57
+ | Command | Purpose |
58
+ |---|---|
59
+ | `specsail init` | Add SpecSail files without overwriting existing project files. |
60
+ | `specsail new <slug> <fix\|update\|new>` | Scaffold request, spec, plan, and task artifacts. |
61
+ | `specsail doctor` | Check required files, role skills, and `make verify`. |
62
+ | `specsail --version` | Print the installed version. |
63
+
64
+ Optional scripts in `.specsail/scripts/` create phase branches, run configured CLIs, check protected-path commit prefixes, and open a PR. They require Git and Bash (macOS, Linux, WSL, or Git Bash). Interactive workflow use does not.
65
+
66
+ ## Stack-neutral by design
67
+
68
+ SpecSail does not select a language, framework, CI provider, test runner, or model. The project owner wires `make setup`, `make lint`, `make typecheck`, `make test`, and `make accept` to the real project. The generated targets fail loudly until configured; they do not pretend generic checks are sufficient.
69
+
70
+ ## Development
71
+
72
+ ```sh
73
+ make setup
74
+ make verify
75
+ ```
76
+
77
+ Read [CONTRIBUTING.md](CONTRIBUTING.md), the [workflow reference](docs/workflow.md), the [runbook](docs/runbook.md), and the [roadmap](ROADMAP.md).
78
+
79
+ ## Open source
80
+
81
+ MIT licensed. Contributions and issue reports are welcome. See [CHANGELOG.md](CHANGELOG.md) for release notes.
package/ROADMAP.md ADDED
@@ -0,0 +1,19 @@
1
+ # SpecSail roadmap
2
+
3
+ The first release focuses on a safe, readable baseline. The items below are ordered by the evidence and safety they unlock; they are proposals, not promises.
4
+
5
+ ## Before calling the workflow stable (1.0)
6
+
7
+ 1. **Run cross-stack pilots.** Complete at least two real feature cycles in each of a JavaScript/TypeScript, Python, and Go project. Record where the human or agent had to reinterpret instructions; keep representative cases as regression/evaluation fixtures.
8
+ 2. **Validate agent compatibility.** Exercise the same stages with multiple coding tools using their native instruction discovery and with manual `AGENTS.md`/`SKILL.md` references. Publish a tested matrix; distinguish tested tools from tools that should work by convention.
9
+ 3. **Harden initialization.** Add a dry-run mode and explicit conflict report; test interrupted initialization, existing agent instructions, symlinked paths, and Windows filesystem behavior.
10
+ 4. **Prove the gates.** Add evaluation cases where agents encounter ambiguous specs, failing tests, scope changes, and the Captain approval gates; verify they stop instead of guessing, weakening tests, or merging.
11
+ 5. **Document release/support policy.** Use pilot feedback to settle supported Node versions, upgrade expectations, and the optional runner's platform support before declaring 1.0 stability.
12
+
13
+ ## Later, based on user demand
14
+
15
+ - Add a conflict-aware `specsail update` that previews changes and never overwrites local edits.
16
+ - Add opt-in agent-specific adapters or commands only when they improve the universal Markdown workflow without making them mandatory.
17
+ - Consider a Windows-native runner if users need headless execution outside WSL or Git Bash.
18
+ - Automate release notes and npm publishing with GitHub Actions trusted publishing/provenance after the maintainer account is configured.
19
+ - Consider language/framework presets as separately maintained opt-ins; the core remains stack-neutral.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "../src/cli.js";
3
+
4
+ process.exitCode = await runCli(process.argv.slice(2));
package/package.json CHANGED
@@ -1,6 +1,53 @@
1
1
  {
2
2
  "name": "specsail",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "A spec-driven AI development crew. Navigate by spec. Deliver with confidence.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "specsail": "bin/specsail.js"
9
+ },
10
+ "engines": {
11
+ "node": ">=20"
12
+ },
13
+ "files": [
14
+ "bin/",
15
+ "src/",
16
+ "scripts/*.sh",
17
+ "scripts/check-content.mjs",
18
+ "skills/",
19
+ "specs/_templates/",
20
+ "test/",
21
+ "templates/",
22
+ "README.md",
23
+ "ROADMAP.md",
24
+ "LICENSE",
25
+ "CHANGELOG.md"
26
+ ],
27
+ "scripts": {
28
+ "lint": "node scripts/check-content.mjs",
29
+ "typecheck": "node --check bin/specsail.js && node --check src/cli.js",
30
+ "test": "node --test test/*.test.js",
31
+ "accept": "node --test test/acceptance/*.test.js",
32
+ "verify": "npm run lint && npm run typecheck && npm test && npm run accept",
33
+ "prepublishOnly": "npm run verify"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/dseija/specsail.git"
41
+ },
42
+ "homepage": "https://github.com/dseija/specsail#readme",
43
+ "bugs": {
44
+ "url": "https://github.com/dseija/specsail/issues"
45
+ },
46
+ "keywords": [
47
+ "spec-driven-development",
48
+ "ai-agents",
49
+ "agent-skills",
50
+ "methodology",
51
+ "development-workflow"
52
+ ]
53
+ }
@@ -0,0 +1,62 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
6
+ const roles = {
7
+ understand: ["Product Owner", "Scout"],
8
+ plan: ["Tech Lead", "Navigator"],
9
+ "acceptance-tests": ["QA", "Quartermaster"],
10
+ implement: ["Developer", "Hands"],
11
+ review: ["Reviewer", "First Mate"],
12
+ ship: ["Release", "Bosun"],
13
+ };
14
+
15
+ let errors = 0;
16
+ function fail(message) {
17
+ console.error(`✗ ${message}`);
18
+ errors += 1;
19
+ }
20
+
21
+ const manifest = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
22
+ if (manifest.name !== "specsail") fail("package name must be specsail");
23
+ if (!/^\d+\.\d+\.\d+$/.test(manifest.version)) fail("package version must be a stable x.y.z version");
24
+ if (manifest.engines?.node !== ">=20") fail("package must declare Node.js >=20");
25
+ if (manifest.bin?.specsail !== "bin/specsail.js") fail("the specsail binary path must use the normalized bin/specsail.js form");
26
+ if (Object.keys(manifest.dependencies ?? {}).length > 0) fail("the CLI should not add runtime dependencies");
27
+
28
+ for (const [stage, [title, crew]] of Object.entries(roles)) {
29
+ const skillPath = path.join(root, "skills", stage, "SKILL.md");
30
+ let content;
31
+ try {
32
+ content = await readFile(skillPath, "utf8");
33
+ } catch {
34
+ fail(`missing skill ${path.relative(root, skillPath)}`);
35
+ continue;
36
+ }
37
+ const frontmatter = content.match(/^---\n([\s\S]*?)\n---\n/);
38
+ if (!frontmatter) {
39
+ fail(`${stage}/SKILL.md is missing YAML frontmatter`);
40
+ continue;
41
+ }
42
+ const fields = frontmatter[1];
43
+ if (!new RegExp(`^name: ${stage.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").test(fields)) {
44
+ fail(`${stage}/SKILL.md name must match its directory`);
45
+ }
46
+ if (!fields.includes(`specsail-title: ${title}`)) fail(`${stage}/SKILL.md must identify the ${title} role`);
47
+ if (!fields.includes(`specsail-crew: ${crew}`)) fail(`${stage}/SKILL.md must identify the ${crew} crew alias`);
48
+ if (!content.includes(`${title} — ${crew}`)) fail(`${stage}/SKILL.md heading must show ${title} — ${crew}`);
49
+ }
50
+
51
+ const readme = await readFile(path.join(root, "README.md"), "utf8");
52
+ for (const term of ["Navigate by spec. Deliver with confidence.", "The **Captain is always human**", ...Object.values(roles).flat()]) {
53
+ if (!readme.includes(term)) fail(`README.md must document: ${term}`);
54
+ }
55
+
56
+ const templateFiles = await readdir(path.join(root, "specs/_templates"));
57
+ for (const name of ["request.md", "spec.md", "plan.md", "tasks.md"]) {
58
+ if (!templateFiles.includes(name)) fail(`missing feature scaffold template specs/_templates/${name}`);
59
+ }
60
+
61
+ if (errors) process.exitCode = 1;
62
+ else console.log("✓ content, crew metadata, and package invariants are valid");
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ # Fail if protected files changed in a commit that isn't prefixed spec:/accept:/plan:.
3
+ # Usage: scripts/check-protected-paths.sh [base-ref] (default origin/main)
4
+ # Backstop for fake prefixes: CODEOWNERS review on the same paths.
5
+ set -euo pipefail
6
+ BASE="${1:-origin/main}"
7
+ PROTECTED='^(tests/acceptance/|specs/[^/]+/(spec|plan)\.md$)'
8
+ ALLOWED='^(spec|accept|plan)(\(.+\))?!?:'
9
+ fail=0
10
+ for c in $(git rev-list --no-merges "$BASE"..HEAD); do
11
+ subj="$(git log -1 --format=%s "$c")"
12
+ hits="$(git diff-tree --no-commit-id --name-only -r "$c" | grep -E "$PROTECTED" || true)"
13
+ if [ -n "$hits" ] && ! printf '%s' "$subj" | grep -Eq "$ALLOWED"; then
14
+ echo "Protected paths changed in ${c:0:8} ('$subj'):"
15
+ printf '%s\n' "$hits" | sed 's/^/ /'
16
+ fail=1
17
+ fi
18
+ done
19
+ [ "$fail" -eq 0 ] && echo "Protected paths OK"
20
+ exit "$fail"
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env bash
2
+ # Scaffold specs/<slug>/ from templates.
3
+ # Usage: scripts/new-feature.sh <slug> <fix|update|new>
4
+ set -euo pipefail
5
+ SLUG="${1:?usage: new-feature.sh <slug> <fix|update|new>}"
6
+ KIND="${2:?usage: new-feature.sh <slug> <fix|update|new>}"
7
+ [[ "$SLUG" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]] || { echo "slug must be lowercase kebab-case" >&2; exit 1; }
8
+ case "$KIND" in
9
+ fix) TYPE="FIX" ;;
10
+ update) TYPE="FEATURE UPDATE" ;;
11
+ new) TYPE="NEW FEATURE" ;;
12
+ *) echo "type must be fix|update|new" >&2; exit 1 ;;
13
+ esac
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ SPECSAIL_DIR="${SPECSAIL_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)}"
16
+ cd "$(git rev-parse --show-toplevel)"
17
+ DIR="specs/$SLUG"
18
+ [ -e "$DIR" ] && { echo "$DIR already exists" >&2; exit 1; }
19
+ TEMPLATES="$SPECSAIL_DIR/templates/specs/_templates"
20
+ [ -d "$TEMPLATES" ] || TEMPLATES="$SPECSAIL_DIR/specs/_templates"
21
+ mkdir -p "$DIR"
22
+ for f in request spec plan tasks; do
23
+ sed "s/{{SLUG}}/$SLUG/g; s/{{TYPE}}/$TYPE/g" "$TEMPLATES/$f.md" > "$DIR/$f.md"
24
+ done
25
+ echo "Created $DIR. Commit scaffolds with a spec: prefix. Next: .specsail/scripts/run-agent.sh scout $SLUG"
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+ # Verify, then open the PR for a phase. Usage: scripts/open-pr.sh <feature> <phase-number>
3
+ set -euo pipefail
4
+ SLUG="${1:?feature}"; N="${2:?phase number}"
5
+ [[ "$SLUG" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]] || { echo "feature slug must be lowercase kebab-case" >&2; exit 1; }
6
+ [[ "$N" =~ ^[1-9][0-9]*$ ]] || { echo "phase must be a positive integer" >&2; exit 1; }
7
+ cd "$(git rev-parse --show-toplevel)"
8
+ make verify
9
+ BODY="Spec: specs/$SLUG/spec.md
10
+ Plan: specs/$SLUG/plan.md (phase $N)
11
+
12
+ Task status:
13
+ $(cat "specs/$SLUG/tasks.md")"
14
+ git push -u origin HEAD
15
+ gh pr create --title "$SLUG: phase $N" --body "$BODY"
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+ # Run one stage headlessly with whichever CLI/model is configured for it.
3
+ # Usage: scripts/run-agent.sh <stage-or-crew-alias> <feature> [task-id]
4
+ # Config: .specsail/agents.env (see .specsail/agents.env.example)
5
+ set -euo pipefail
6
+ ROLE="${1:?usage: run-agent.sh <stage-or-crew-alias> <feature> [task-id]}"
7
+ FEATURE="${2:?feature slug}"
8
+ TASK="${3:-}"
9
+ [[ "$FEATURE" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]] || { echo "feature slug must be lowercase kebab-case" >&2; exit 1; }
10
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ SPECSAIL_DIR="${SPECSAIL_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)}"
12
+ cd "$(git rev-parse --show-toplevel)"
13
+ [ -f "$SPECSAIL_DIR/agents.env" ] && . "$SPECSAIL_DIR/agents.env"
14
+
15
+ case "$ROLE" in
16
+ understand|scout) STAGE=understand; TITLE="Product Owner"; CREW="Scout" ;;
17
+ plan|navigator) STAGE=plan; TITLE="Tech Lead"; CREW="Navigator" ;;
18
+ acceptance-tests|quartermaster) STAGE=acceptance-tests; TITLE="QA"; CREW="Quartermaster" ;;
19
+ implement|hands) STAGE=implement; TITLE="Developer"; CREW="Hands" ;;
20
+ review|first-mate) STAGE=review; TITLE="Reviewer"; CREW="First Mate" ;;
21
+ ship|bosun) STAGE=ship; TITLE="Release"; CREW="Bosun" ;;
22
+ *) echo "Unknown stage or crew alias '$ROLE'." >&2; exit 1 ;;
23
+ esac
24
+
25
+ SKILL="$SPECSAIL_DIR/skills/$STAGE/SKILL.md"
26
+ [ -f "$SKILL" ] || { echo "No skill for stage '$STAGE' ($SKILL)" >&2; exit 1; }
27
+
28
+ KEY="$(printf '%s' "$STAGE" | tr 'a-z-' 'A-Z_')"
29
+ CLI_VAR="AGENT_CLI_$KEY"; MODEL_VAR="AGENT_MODEL_$KEY"
30
+ CLI="${!CLI_VAR:-${AGENT_CLI:-claude}}"
31
+ MODEL="${!MODEL_VAR:-}"
32
+
33
+ PROMPT="You are the $TITLE ($CREW) agent for the $STAGE stage. Read AGENTS.md, $SPECSAIL_DIR/AGENTS.md, and $SKILL, then do your job for specs/$FEATURE/. The human is the Captain: never approve specs/tests or merge. Follow your Must-not and Escalate rules strictly."
34
+ [ -n "$TASK" ] && PROMPT="$PROMPT Task: $TASK. Work on this task only."
35
+
36
+ # NOTE: headless runs need tool permissions configured in each tool (allowed
37
+ # commands, writable paths). Keep them minimal per role.
38
+ case "$CLI" in
39
+ claude) exec claude -p ${MODEL:+--model "$MODEL"} "$PROMPT" ;;
40
+ codex) exec codex exec ${MODEL:+-m "$MODEL"} "$PROMPT" ;;
41
+ opencode) exec opencode run ${MODEL:+-m "$MODEL"} "$PROMPT" ;;
42
+ custom) : "${AGENT_CUSTOM_CMD:?set AGENT_CUSTOM_CMD}"; exec $AGENT_CUSTOM_CMD "$PROMPT" ;;
43
+ *) echo "Unsupported CLI '$CLI'. Edit scripts/run-agent.sh to add it." >&2; exit 1 ;;
44
+ esac
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ # Create the branch for a phase. Usage: scripts/start-phase.sh <feature> <phase-number> [base]
3
+ set -euo pipefail
4
+ SLUG="${1:?feature}"; N="${2:?phase number}"; BASE="${3:-main}"
5
+ [[ "$SLUG" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]] || { echo "feature slug must be lowercase kebab-case" >&2; exit 1; }
6
+ [[ "$N" =~ ^[1-9][0-9]*$ ]] || { echo "phase must be a positive integer" >&2; exit 1; }
7
+ git fetch origin "$BASE" 2>/dev/null || true
8
+ git checkout -b "$SLUG/phase-$N" "origin/$BASE" 2>/dev/null || git checkout -b "$SLUG/phase-$N" "$BASE"
9
+ echo "On branch $SLUG/phase-$N"
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: acceptance-tests
3
+ description: Turn approved spec acceptance criteria into executable failing acceptance tests. Use once per phase, before implementation.
4
+ metadata:
5
+ specsail-title: QA
6
+ specsail-crew: Quartermaster
7
+ ---
8
+ # QA — Quartermaster (acceptance-tests)
9
+ **Model tier:** frontier. **Isolated context: you do not see the plan or the implementation.** The Captain approves the tests before implementation begins.
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `specs/<feature>/spec.md` (must be APPROVED), glossary in `docs/project.md`, existing test harness/fixtures and public interfaces (only to write tests that run).
13
+
14
+ ## Writes
15
+ `tests/acceptance/<feature>/**` only. Commit prefix `accept:`.
16
+
17
+ ## Scope
18
+ If the task argument lists AC IDs (e.g. `AC-1,AC-2`), write tests only for those. Otherwise write them for all ACs. This keeps `main` green when a feature ships in several phases.
19
+
20
+ ## Process
21
+ 1. One test per AC at minimum. Name it with the ID (e.g. `test_AC1_...` / `it("AC-1: ...")`).
22
+ 2. Test observable behavior through public interfaces (API, UI, CLI), not internals.
23
+ 3. Run `make accept`. Every new test must FAIL for the right reason (missing behavior), not for imports, syntax, setup or typos. Report each failure message.
24
+ 4. Keep tests deterministic: no sleeps, no network, no shared state.
25
+
26
+ ## Must not
27
+ - Read `plan.md` or implementation code beyond public interfaces.
28
+ - Edit `spec.md` or production code.
29
+ - Write a test that can't fail, or one that mocks the behavior under test.
30
+
31
+ ## Done when
32
+ Every AC has a test, all fail for the right reason, and the report lists AC → test → failure message.
33
+
34
+ ## Escalate when
35
+ An AC can't be tested as written. Write `blocked.md` quoting the AC.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: implement
3
+ description: Implement exactly one task from plan.md so its acceptance tests pass. Use per task, also for CHANGES_REQUESTED rework.
4
+ metadata:
5
+ specsail-title: Developer
6
+ specsail-crew: Hands
7
+ ---
8
+ # Developer — Hands (implement)
9
+ **Model tier:** mid/cheap. **One task per run.**
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `specs/<feature>/spec.md`, `plan.md` (your task only), `tasks.md`, `review.md` (if status is CHANGES_REQUESTED), `docs/architecture/<module>.md` for your module.
13
+
14
+ ## Writes
15
+ Production code, unit/integration tests, docs listed in plan.md "Docs to update", your task's row in `tasks.md`.
16
+
17
+ ## Process
18
+ 1. Pick the first `TODO` or `CHANGES_REQUESTED` task. Set `IN_PROGRESS`.
19
+ 2. If reworking: address every BLOCKER and MAJOR finding in review.md; mention how you handled NITs.
20
+ 3. TDD for unit-level logic: red, green, refactor. Make the linked acceptance tests pass.
21
+ 4. Run `make verify`. Fix until green.
22
+ 5. Update docs the plan lists. Commit (`feat:`/`fix:`/`docs:`). Set `DEV_DONE`.
23
+ 6. Report: what changed, AC → test status, anything out of scope you noticed.
24
+
25
+ ## Must not
26
+ - Edit `tests/acceptance/**`, `spec.md`, `plan.md`.
27
+ - Delete, skip, loosen or special-case a failing test.
28
+ - Touch modules outside the task's scope or refactor unrelated code.
29
+ - Mark DEV_DONE while `make verify` is red.
30
+
31
+ ## Done when
32
+ `make verify` is green, linked ACs pass, docs updated, status `DEV_DONE`.
33
+
34
+ ## Escalate when
35
+ - The spec/AC seems wrong, ambiguous or conflicting → write `blocked.md`, set `BLOCKED`, stop.
36
+ - 3 failed attempts at the same failure → write `blocked.md` with what you tried.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: plan
3
+ description: Write spec.md (and then plan.md + tasks.md once spec is approved). Use after request.md is confirmed.
4
+ metadata:
5
+ specsail-title: Tech Lead
6
+ specsail-crew: Navigator
7
+ ---
8
+ # Tech Lead — Navigator (plan)
9
+ **Model tier:** frontier. **Two modes, chosen by state. Stop at the end of each mode.** The human is the Captain; agents never approve artifacts.
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `docs/project.md`, `docs/architecture.md`, `specs/<feature>/request.md`; in plan mode also the approved `spec.md` and `docs/architecture/<module>.md` for modules in request.md.
13
+
14
+ ## Mode A: spec (when spec.md is missing or `Status: DRAFT`)
15
+ Writes `spec.md`: Overview, Objective, Acceptance criteria, Out of scope.
16
+ - Acceptance criteria are Given/When/Then, with stable IDs `AC-1`, `AC-2`, ...
17
+ - Each AC is observable behavior, testable without knowing the implementation.
18
+ - Use glossary terms exactly. Put anything uncertain under "Open questions", not in an AC.
19
+ - FIX type: AC-1 must be the reproduction of the bug.
20
+ - Stop. The Captain reviews and approves the spec by setting `Status: APPROVED` before mode B. Acceptance tests are written and approved later, after the plan, by the Quartermaster.
21
+
22
+ ## Mode B: plan (when spec.md is `Status: APPROVED`)
23
+ Writes `plan.md` and `tasks.md`.
24
+ - Tasks are thin vertical slices, grouped in phases. Each lists: AC IDs, scope, verification command.
25
+ - Do not create tasks for branches or PRs (scripted).
26
+ - Multi-app: define the API contract first, then per-app tasks that can run in parallel.
27
+ - Include "Docs to update" and "Risks and mitigations".
28
+ - Architecture decisions only if request.md says Architecture affected = YES; create ADRs for significant ones.
29
+ - Every AC must be covered by at least one task.
30
+
31
+ ## Must not
32
+ Edit an APPROVED spec; write tests or code; set `Status: APPROVED`.
33
+
34
+ ## Done when
35
+ Mode A: spec complete and every AC testable. Mode B: every AC mapped to a task, every task has a verify command.
36
+
37
+ ## Escalate when
38
+ An AC is untestable, contradictory, or requires an architecture change the request didn't flag.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: review
3
+ description: Review a task's or phase's diff against spec and plan. Use after a task reaches DEV_DONE.
4
+ metadata:
5
+ specsail-title: Reviewer
6
+ specsail-crew: First Mate
7
+ ---
8
+ # Reviewer — First Mate (review)
9
+ **Model tier:** frontier, preferably a different model family than the implementer. **Report only, never fix.**
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `specs/<feature>/spec.md`, `plan.md`, `tasks.md`, the diff against the base branch, `docs/architecture.md` (invariants + boundaries), module doc for touched modules.
13
+
14
+ ## Writes
15
+ `specs/<feature>/review.md` (only when changes are needed) and the task status in `tasks.md`.
16
+
17
+ ## Checklist (evidence required: file:line)
18
+ 1. `make verify` is green (run it; don't trust the report).
19
+ 2. Each AC of the task has a passing test that really exercises it (not trivially passing).
20
+ 3. Behavior matches the spec, including Out of scope: no scope creep, no missing cases.
21
+ 4. Architecture boundaries and invariants respected.
22
+ 5. Protected paths untouched (`make check-protected`).
23
+ 6. Docs listed in plan.md updated.
24
+ 7. Correctness, error handling, security, obvious perf traps in the changed code.
25
+
26
+ ## Outcome
27
+ - No BLOCKER/MAJOR → set `DONE`. NITs may be listed in the report but don't block.
28
+ - Otherwise → write `review.md` from the template (overwrite previous), set `CHANGES_REQUESTED`, increment loops in `tasks.md`.
29
+ - Loops reaches 3 → don't request again; write `blocked.md` summarizing the disagreement and stop.
30
+
31
+ ## Must not
32
+ Edit code or tests; approve without running verify; raise findings without evidence; review style already covered by lint.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: ship
3
+ description: Prepare a phase for merge: docs, changelog, PR description. Use after all tasks of a phase are DONE. Prefer scripts for anything mechanical.
4
+ metadata:
5
+ specsail-title: Release
6
+ specsail-crew: Bosun
7
+ ---
8
+ # Release — Bosun (ship)
9
+ **Model tier:** cheap. **Mostly mechanical; the Captain merges.**
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `specs/<feature>/spec.md`, `plan.md`, `tasks.md`, the phase diff, current README / API docs / changelog / `docs/project.md` / `docs/architecture.md`.
13
+
14
+ ## Writes
15
+ Docs only, in the same PR: changelog entry, README, API docs, architecture/project/module docs where the diff changed reality. Commit prefix `docs:`.
16
+
17
+ ## Process
18
+ 1. Confirm every task in the phase is `DONE` and `make verify` is green. If not, stop.
19
+ 2. Compare the diff to the docs; update only what became false or incomplete. Keep project.md/architecture.md short.
20
+ 3. Add a changelog entry from the spec Objective and ACs (user-facing language).
21
+ 4. Run `scripts/open-pr.sh <feature> <phase>`; the PR description links spec.md and lists AC coverage.
22
+
23
+ ## Must not
24
+ Merge; edit code, tests, spec or plan; grow docs with history or status.
25
+
26
+ ## Done when
27
+ PR is open, docs are current, and the human has what they need to merge.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: understand
3
+ description: Turn a raw request into specs/<feature>/request.md. Use at the start of any feature, update or fix.
4
+ metadata:
5
+ specsail-title: Product Owner
6
+ specsail-crew: Scout
7
+ ---
8
+ # Product Owner — Scout (understand)
9
+ **Model tier:** frontier. **Interactive with the human.**
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `docs/project.md`, `docs/architecture.md`, the raw request, `specs/<feature>/request.md` (template).
13
+
14
+ ## Writes
15
+ `specs/<feature>/request.md` only.
16
+
17
+ ## Process
18
+ 1. Read the docs, then the request. Look at code only to confirm which modules are involved.
19
+ 2. Interrogate the human before writing: ask about goal, users, edge cases, constraints. Ask in small batches, most important first.
20
+ 3. Fill the template. Decide Type and Routing flags honestly; they select the path (see `docs/workflow.md`).
21
+ 4. List unresolved questions under "Open questions".
22
+
23
+ ## Must not
24
+ - Write spec, plan, tests or code.
25
+ - Guess an answer to an open question; ask.
26
+ - Invent modules; use names from the project.md repo map.
27
+
28
+ ## Done when
29
+ Every template field is filled, Open questions is empty or explicitly deferred by the human, and the human confirmed the request.
30
+
31
+ ## Escalate when
32
+ The request conflicts with a non-goal or invariant in project.md/architecture.md. Say so and stop.
@@ -0,0 +1,15 @@
1
+ # Blocked: {{SLUG}} / T-?
2
+ Raised by: <role>
3
+ Date:
4
+
5
+ ## What I was trying to do
6
+
7
+ ## Why I can't proceed
8
+ <!-- Quote the spec line / AC ID that is ambiguous, contradictory or impossible. -->
9
+
10
+ ## Options I see
11
+ 1.
12
+ 2.
13
+
14
+ ## Recommendation
15
+ <!-- A human resolves this and, if needed, updates spec.md. -->
@@ -0,0 +1,23 @@
1
+ # Plan: {{SLUG}}
2
+ <!-- Branch and PR creation are scripted (scripts/start-phase.sh, scripts/open-pr.sh). Don't list them as tasks. -->
3
+
4
+ ## Overview
5
+
6
+ ## Architecture decisions
7
+ <!-- Omit if request.md says Architecture affected: NO. Link or create ADRs for significant ones. -->
8
+
9
+ ## API contract
10
+ <!-- Multi-app only: define first. Endpoints, payloads, errors. -->
11
+
12
+ ## Phases
13
+
14
+ ### Phase 1: <name>
15
+ - **T-1** <title>
16
+ - AC: AC-1
17
+ - Scope: <modules/files>
18
+ - Verify: `make verify` + <specific command>
19
+
20
+ ## Docs to update (same PR)
21
+ <!-- README, API docs, changelog, architecture.md, project.md, module docs. -->
22
+
23
+ ## Risks and mitigations
@@ -0,0 +1,19 @@
1
+ # Request: {{SLUG}}
2
+ Type: {{TYPE}}
3
+
4
+ ## Overview
5
+ <!-- What is being asked and why, in 3-6 lines. -->
6
+
7
+ ## Routing
8
+ | Question | Answer |
9
+ |---|---|
10
+ | Architecture affected | YES / NO |
11
+ | API affected | YES / NO |
12
+ | UI/UX affected | YES / NO |
13
+ | Apps involved | BACKEND / FRONTEND / MOBILE |
14
+ | Modules involved | <names matching docs/project.md repo map> |
15
+
16
+ ## Constraints and risks
17
+
18
+ ## Open questions
19
+ <!-- Must be empty (or answered) before moving to spec. -->