specsail 0.0.0-stage → 0.2.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +92 -2
  4. package/ROADMAP.md +18 -0
  5. package/bin/specsail.js +4 -0
  6. package/package.json +51 -4
  7. package/scripts/check-content.mjs +80 -0
  8. package/scripts/check-protected-paths.sh +20 -0
  9. package/scripts/new-feature.sh +25 -0
  10. package/scripts/open-pr.sh +15 -0
  11. package/scripts/release.sh +29 -0
  12. package/scripts/run-agent.sh +45 -0
  13. package/scripts/start-phase.sh +9 -0
  14. package/skills/acceptance-tests/SKILL.md +38 -0
  15. package/skills/implement/SKILL.md +39 -0
  16. package/skills/manage/SKILL.md +70 -0
  17. package/skills/plan/SKILL.md +41 -0
  18. package/skills/review/SKILL.md +35 -0
  19. package/skills/ship/SKILL.md +30 -0
  20. package/skills/understand/SKILL.md +35 -0
  21. package/specs/_templates/blocked.md +15 -0
  22. package/specs/_templates/plan.md +23 -0
  23. package/specs/_templates/request.md +19 -0
  24. package/specs/_templates/review.md +18 -0
  25. package/specs/_templates/spec.md +20 -0
  26. package/specs/_templates/tasks.md +7 -0
  27. package/src/cli.js +300 -0
  28. package/templates/.github/CODEOWNERS +6 -0
  29. package/templates/.github/workflows/verify.yml +18 -0
  30. package/templates/.specsail/AGENTS.md +41 -0
  31. package/templates/.specsail/agents.env.example +15 -0
  32. package/templates/.specsail/docs/runbook.md +44 -0
  33. package/templates/.specsail/docs/workflow.md +56 -0
  34. package/templates/Makefile +19 -0
  35. package/templates/docs/architecture/.gitkeep +0 -0
  36. package/templates/docs/architecture.md +15 -0
  37. package/templates/docs/project.md +19 -0
  38. package/test/acceptance/cli.acceptance.test.js +129 -0
  39. package/test/cli.test.js +26 -0
  40. package/test/release.test.js +17 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ All notable SpecSail changes are recorded here.
4
+
5
+ ## 0.2.0 — 2026-10-21
6
+
7
+ - Add conversational mode: ask your coding agent for a change and the First Mate (`manage`) runs the workflow, bootstrapping project docs and the Makefile first.
8
+ - Add the `manage` orchestrator skill; chat approvals are recorded in artifacts as `Status: APPROVED — Captain (chat), <date>`.
9
+ - Review now asks whether to use a second session/model and records any same-model caveat.
10
+ - Rename crew aliases: Reviewer is now **Bosun** and Release is now **Clerk**. Stage names and commands are unchanged.
11
+ - Publish releases from GitHub Actions with npm trusted publishing and provenance; add `make release` and the release guide.
12
+
13
+ ## 0.1.0 — 2026-10-20
14
+
15
+ - First public release of the SpecSail methodology and Node.js CLI.
16
+ - Add the Captain-led crew: Scout, Navigator, Quartermaster, Hands, First Mate, and Bosun.
17
+ - Add merge-safe project initialization, feature scaffolding, and setup diagnostics.
18
+ - 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,93 @@
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
+ Start with one sentence. Your agent runs the workflow.
10
+
11
+ ## The crew
12
+
13
+ | Skill | Development role | Sailing alias | Responsibility |
14
+ |---|---|---|---|
15
+ | `manage` | Orchestrator | **First Mate** | Bootstraps project context, runs the workflow, and stops at every gate. |
16
+ | `understand` | Product Owner | **Scout** | Clarifies the request and records routing, constraints, and open questions. |
17
+ | `plan` | Tech Lead | **Navigator** | Writes the spec, then the technical plan and thin tasks. |
18
+ | `acceptance-tests` | QA | **Quartermaster** | Encodes approved criteria as observable tests before implementation. |
19
+ | `implement` | Developer | **Hands** | Implements one planned task and runs project verification. |
20
+ | `review` | Reviewer | **Bosun** | Independently checks behavior, evidence, scope, and invariants. |
21
+ | `ship` | Release | **Clerk** | Updates release docs and prepares the pull request. |
22
+
23
+ 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.
24
+
25
+ ## Quick start
26
+
27
+ Requires Node.js 20+ for the one-time setup. No runtime dependencies.
28
+
29
+ ```sh
30
+ npx specsail init
31
+ ```
32
+
33
+ Then open your coding agent and ask for what you want:
34
+
35
+ > "Let's add user authentication."
36
+
37
+ The First Mate checks `docs/project.md`, `docs/architecture.md`, and the `Makefile`. If they are missing or still starter templates, it interviews you and drafts them. It then scaffolds `specs/<feature>/` and runs Scout → Navigator → Quartermaster → Hands → Bosun → Clerk, asking questions and stopping at each approval gate. You answer in chat; the agent records each decision in the artifact.
38
+
39
+ No commands are required after `init`. The CLI stays available for manual control, CI, and scripting.
40
+
41
+ ## How the flow works
42
+
43
+ ```text
44
+ request → Captain-approved spec → plan → Captain-approved phase tests
45
+ → implement one task → independent review → PR → Captain merges
46
+ ```
47
+
48
+ The spec is approved before planning; phase tests are approved before implementation. Bug fixes use a shorter path; trivial changes can use a normal PR and the project's `make verify`.
49
+
50
+ At every stage the agent may ask you questions. Two gates are always explicit:
51
+
52
+ 1. **Spec approval** — the acceptance criteria are observable and complete.
53
+ 2. **Test approval** — the tests fail for the right reason before code is written.
54
+
55
+ Review independence is also explicit: the First Mate asks whether to open a second session/model. If you accept a same-model review, the caveat is recorded in `review.md`.
56
+
57
+ ## Use with your coding tool
58
+
59
+ SpecSail does not require a vendor-specific agent integration. Use any tool that reads repository instructions and Markdown — OpenCode, Claude Code, Codex, Cursor, Copilot, Gemini CLI, or anything else. `AGENTS.md` tells the agent to start the workflow; if your tool does not discover skills automatically, it can read the `SKILL.md` files directly.
60
+
61
+ For tools using the Agent Skills convention, you can also install individual skills from this repository:
62
+
63
+ ```sh
64
+ npx skills add dseija/specsail --skill manage
65
+ ```
66
+
67
+ ## Commands (optional)
68
+
69
+ | Command | Purpose |
70
+ |---|---|
71
+ | `specsail init` | Add SpecSail files without overwriting existing project files. |
72
+ | `specsail new <slug> <fix\|update\|new>` | Scaffold request, spec, plan, and task artifacts manually. |
73
+ | `specsail doctor` | Check required files, crew skills, `make verify`, and the workflow trigger. |
74
+ | `specsail --version` | Print the installed version. |
75
+
76
+ 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). The conversational workflow does not.
77
+
78
+ ## Stack-neutral by design
79
+
80
+ 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.
81
+
82
+ ## Development
83
+
84
+ ```sh
85
+ make setup
86
+ make verify
87
+ ```
88
+
89
+ Read [CONTRIBUTING.md](CONTRIBUTING.md), the [workflow reference](docs/workflow.md), the [runbook](docs/runbook.md), the [release guide](docs/releasing.md), and the [roadmap](ROADMAP.md).
90
+
91
+ ## Open source
92
+
93
+ MIT licensed. Contributions and issue reports are welcome. See [CHANGELOG.md](CHANGELOG.md) for release notes.
package/ROADMAP.md ADDED
@@ -0,0 +1,18 @@
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
+ - 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.2.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,80 @@
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
+ manage: ["Orchestrator", "First Mate"],
8
+ understand: ["Product Owner", "Scout"],
9
+ plan: ["Tech Lead", "Navigator"],
10
+ "acceptance-tests": ["QA", "Quartermaster"],
11
+ implement: ["Developer", "Hands"],
12
+ review: ["Reviewer", "Bosun"],
13
+ ship: ["Release", "Clerk"],
14
+ };
15
+
16
+ let errors = 0;
17
+ function fail(message) {
18
+ console.error(`✗ ${message}`);
19
+ errors += 1;
20
+ }
21
+
22
+ const manifest = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
23
+ if (manifest.name !== "specsail") fail("package name must be specsail");
24
+ if (!/^\d+\.\d+\.\d+$/.test(manifest.version)) fail("package version must be a stable x.y.z version");
25
+ if (manifest.engines?.node !== ">=20") fail("package must declare Node.js >=20");
26
+ if (manifest.bin?.specsail !== "bin/specsail.js") fail("the specsail binary path must use the normalized bin/specsail.js form");
27
+ if (Object.keys(manifest.dependencies ?? {}).length > 0) fail("the CLI should not add runtime dependencies");
28
+
29
+ for (const [stage, [title, crew]] of Object.entries(roles)) {
30
+ const skillPath = path.join(root, "skills", stage, "SKILL.md");
31
+ let content;
32
+ try {
33
+ content = await readFile(skillPath, "utf8");
34
+ } catch {
35
+ fail(`missing skill ${path.relative(root, skillPath)}`);
36
+ continue;
37
+ }
38
+ const frontmatter = content.match(/^---\n([\s\S]*?)\n---\n/);
39
+ if (!frontmatter) {
40
+ fail(`${stage}/SKILL.md is missing YAML frontmatter`);
41
+ continue;
42
+ }
43
+ const fields = frontmatter[1];
44
+ if (!new RegExp(`^name: ${stage.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").test(fields)) {
45
+ fail(`${stage}/SKILL.md name must match its directory`);
46
+ }
47
+ if (!fields.includes(`specsail-title: ${title}`)) fail(`${stage}/SKILL.md must identify the ${title} role`);
48
+ if (!fields.includes(`specsail-crew: ${crew}`)) fail(`${stage}/SKILL.md must identify the ${crew} crew alias`);
49
+ if (!content.includes(`${title} — ${crew}`)) fail(`${stage}/SKILL.md heading must show ${title} — ${crew}`);
50
+ }
51
+
52
+ const readme = await readFile(path.join(root, "README.md"), "utf8");
53
+ for (const term of ["Navigate by spec. Deliver with confidence.", "The **Captain is always human**", ...Object.values(roles).flat()]) {
54
+ if (!readme.includes(term)) fail(`README.md must document: ${term}`);
55
+ }
56
+
57
+ const templateFiles = await readdir(path.join(root, "specs/_templates"));
58
+ for (const name of ["request.md", "spec.md", "plan.md", "tasks.md"]) {
59
+ if (!templateFiles.includes(name)) fail(`missing feature scaffold template specs/_templates/${name}`);
60
+ }
61
+
62
+ const templateAgents = await readFile(path.join(root, "templates/.specsail/AGENTS.md"), "utf8");
63
+ if (!templateAgents.includes(".specsail/skills/manage/SKILL.md")) {
64
+ fail("the installed AGENTS.md must trigger the conversational workflow via the manage skill");
65
+ }
66
+ const cliSource = await readFile(path.join(root, "src/cli.js"), "utf8");
67
+ if (!cliSource.includes("skills/manage/SKILL.md")) {
68
+ fail("specsail init must add the conversational workflow trigger to AGENTS.md");
69
+ }
70
+
71
+ const releaseWorkflow = await readFile(path.join(root, ".github/workflows/release.yml"), "utf8");
72
+ if (!/^\s*id-token:\s*write$/m.test(releaseWorkflow)) fail("release workflow must request the GitHub OIDC token (id-token: write)");
73
+ if (!/^\s*contents:\s*write$/m.test(releaseWorkflow)) fail("release workflow must be allowed to create the GitHub release (contents: write)");
74
+ if (!/tags:\s*\["v\*"\]/.test(releaseWorkflow)) fail("release workflow must run on v* tags");
75
+ if (!releaseWorkflow.includes("--provenance")) fail("release workflow must publish with --provenance");
76
+ if (releaseWorkflow.includes("environment: npm") === false) fail("release workflow must use the npm environment configured as the trusted publisher");
77
+ if (/NODE_AUTH_TOKEN|NPM_TOKEN|secrets\./.test(releaseWorkflow)) fail("release workflow must not use npm tokens or repository secrets");
78
+
79
+ if (errors) process.exitCode = 1;
80
+ 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: ask your agent to start the SpecSail workflow for $SLUG; the First Mate will continue from the request stage."
@@ -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,29 @@
1
+ #!/usr/bin/env bash
2
+ # Bump the version, commit, and push a release tag. The tag starts the release workflow.
3
+ # Usage: scripts/release.sh <x.y.z>
4
+ set -euo pipefail
5
+ VERSION="${1:?usage: release.sh <x.y.z>}"
6
+ [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "version must be x.y.z (no leading v)" >&2; exit 1; }
7
+
8
+ cd "$(git rev-parse --show-toplevel)"
9
+ [ -z "$(git status --porcelain)" ] || { echo "working tree must be clean" >&2; exit 1; }
10
+ BRANCH="$(git rev-parse --abbrev-ref HEAD)"
11
+ [ "$BRANCH" = "main" ] || { echo "release from main, not $BRANCH" >&2; exit 1; }
12
+
13
+ git fetch origin main
14
+ [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ] || { echo "local main must match origin/main" >&2; exit 1; }
15
+ grep -q "^## $VERSION " CHANGELOG.md || { echo "CHANGELOG.md is missing a '## $VERSION' heading" >&2; exit 1; }
16
+ git rev-parse -q --verify "refs/tags/v$VERSION" >/dev/null && { echo "tag v$VERSION already exists" >&2; exit 1; }
17
+
18
+ make verify
19
+ CURRENT="$(node -p "require('./package.json').version")"
20
+ if [ "$CURRENT" != "$VERSION" ]; then
21
+ npm version "$VERSION" --no-git-tag-version
22
+ git add package.json package-lock.json
23
+ git commit -m "chore: release $VERSION"
24
+ fi
25
+ git tag "v$VERSION"
26
+ git push origin main
27
+ git push origin "v$VERSION"
28
+
29
+ echo "Pushed v$VERSION. Watch the release workflow with: gh run watch"
@@ -0,0 +1,45 @@
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
+ manage|first-mate) STAGE=manage; TITLE="Orchestrator"; CREW="First Mate" ;;
17
+ understand|scout) STAGE=understand; TITLE="Product Owner"; CREW="Scout" ;;
18
+ plan|navigator) STAGE=plan; TITLE="Tech Lead"; CREW="Navigator" ;;
19
+ acceptance-tests|quartermaster) STAGE=acceptance-tests; TITLE="QA"; CREW="Quartermaster" ;;
20
+ implement|hands) STAGE=implement; TITLE="Developer"; CREW="Hands" ;;
21
+ review|bosun) STAGE=review; TITLE="Reviewer"; CREW="Bosun" ;;
22
+ ship|clerk) STAGE=ship; TITLE="Release"; CREW="Clerk" ;;
23
+ *) echo "Unknown stage or crew alias '$ROLE'." >&2; exit 1 ;;
24
+ esac
25
+
26
+ SKILL="$SPECSAIL_DIR/skills/$STAGE/SKILL.md"
27
+ [ -f "$SKILL" ] || { echo "No skill for stage '$STAGE' ($SKILL)" >&2; exit 1; }
28
+
29
+ KEY="$(printf '%s' "$STAGE" | tr 'a-z-' 'A-Z_')"
30
+ CLI_VAR="AGENT_CLI_$KEY"; MODEL_VAR="AGENT_MODEL_$KEY"
31
+ CLI="${!CLI_VAR:-${AGENT_CLI:-claude}}"
32
+ MODEL="${!MODEL_VAR:-}"
33
+
34
+ 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."
35
+ [ -n "$TASK" ] && PROMPT="$PROMPT Task: $TASK. Work on this task only."
36
+
37
+ # NOTE: headless runs need tool permissions configured in each tool (allowed
38
+ # commands, writable paths). Keep them minimal per role.
39
+ case "$CLI" in
40
+ claude) exec claude -p ${MODEL:+--model "$MODEL"} "$PROMPT" ;;
41
+ codex) exec codex exec ${MODEL:+-m "$MODEL"} "$PROMPT" ;;
42
+ opencode) exec opencode run ${MODEL:+-m "$MODEL"} "$PROMPT" ;;
43
+ custom) : "${AGENT_CUSTOM_CMD:?set AGENT_CUSTOM_CMD}"; exec $AGENT_CUSTOM_CMD "$PROMPT" ;;
44
+ *) echo "Unsupported CLI '$CLI'. Edit scripts/run-agent.sh to add it." >&2; exit 1 ;;
45
+ 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,38 @@
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
+ ## Conversational mode
12
+ The First Mate (orchestrator) may run you in the same session. Read only the approved spec, glossary, and public interfaces; do not inspect the plan or implementation. Ask the Captain about test placement or harness details instead of reading the plan.
13
+
14
+ ## Reads
15
+ `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).
16
+
17
+ ## Writes
18
+ `tests/acceptance/<feature>/**` only. Commit prefix `accept:`.
19
+
20
+ ## Scope
21
+ 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.
22
+
23
+ ## Process
24
+ 1. One test per AC at minimum. Name it with the ID (e.g. `test_AC1_...` / `it("AC-1: ...")`).
25
+ 2. Test observable behavior through public interfaces (API, UI, CLI), not internals.
26
+ 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.
27
+ 4. Keep tests deterministic: no sleeps, no network, no shared state.
28
+
29
+ ## Must not
30
+ - Read `plan.md` or implementation code beyond public interfaces.
31
+ - Edit `spec.md` or production code.
32
+ - Write a test that can't fail, or one that mocks the behavior under test.
33
+
34
+ ## Done when
35
+ Every AC has a test, all fail for the right reason, and the report lists AC → test → failure message.
36
+
37
+ ## Escalate when
38
+ An AC can't be tested as written. Write `blocked.md` quoting the AC.
@@ -0,0 +1,39 @@
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
+ ## Conversational mode
12
+ The First Mate (orchestrator) may ask you to implement one task at a time in the same session. Keep to that task, run `make verify`, and report scope issues; the orchestrator handles gates and commits only as this skill allows.
13
+
14
+ ## Reads
15
+ `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.
16
+
17
+ ## Writes
18
+ Production code, unit/integration tests, docs listed in plan.md "Docs to update", your task's row in `tasks.md`.
19
+
20
+ ## Process
21
+ 1. Pick the first `TODO` or `CHANGES_REQUESTED` task. Set `IN_PROGRESS`.
22
+ 2. If reworking: address every BLOCKER and MAJOR finding in review.md; mention how you handled NITs.
23
+ 3. TDD for unit-level logic: red, green, refactor. Make the linked acceptance tests pass.
24
+ 4. Run `make verify`. Fix until green.
25
+ 5. Update docs the plan lists. Commit (`feat:`/`fix:`/`docs:`). Set `DEV_DONE`.
26
+ 6. Report: what changed, AC → test status, anything out of scope you noticed.
27
+
28
+ ## Must not
29
+ - Edit `tests/acceptance/**`, `spec.md`, `plan.md`.
30
+ - Delete, skip, loosen or special-case a failing test.
31
+ - Touch modules outside the task's scope or refactor unrelated code.
32
+ - Mark DEV_DONE while `make verify` is red.
33
+
34
+ ## Done when
35
+ `make verify` is green, linked ACs pass, docs updated, status `DEV_DONE`.
36
+
37
+ ## Escalate when
38
+ - The spec/AC seems wrong, ambiguous or conflicting → write `blocked.md`, set `BLOCKED`, stop.
39
+ - 3 failed attempts at the same failure → write `blocked.md` with what you tried.
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: manage
3
+ description: Orchestrate the SpecSail workflow from a feature request to a merge-ready PR. Use whenever the user asks to add, change, or fix something non-trivial and expects the crew to run the process conversationally.
4
+ metadata:
5
+ specsail-title: Orchestrator
6
+ specsail-crew: First Mate
7
+ ---
8
+ # Orchestrator — First Mate (manage)
9
+ **Model tier:** frontier. **You run the ship; the Captain decides.** The human is the Captain and is the only one who approves artifacts or merges. You sequence the stages, ask questions, and report at each gate.
10
+
11
+ ## Reads
12
+ `AGENTS.md`, `.specsail/AGENTS.md`, `docs/project.md`, `docs/architecture.md`, the `Makefile`, `specs/<feature>/**`, and `.specsail/docs/workflow.md`. Before acting as a stage, read that stage's `SKILL.md` and follow it.
13
+
14
+ ## When to start
15
+ The user asked for a non-trivial change ("add authentication", "fix the lockout bug") and there is no finished feature for it. Trivial edits (typo, config, dependency bump) need only a normal change and `make verify`; say so and skip the workflow unless the user wants it.
16
+
17
+ ## 1. Bootstrap the project (once)
18
+ Check for the three things the workflow depends on:
19
+ - `docs/project.md` is filled in, not the starter skeleton.
20
+ - `docs/architecture.md` is filled in.
21
+ - `make verify` runs real project checks (not the `SPECSAIL_UNCONFIGURED_TEMPLATE` starter).
22
+
23
+ If any are missing or unconfigured, stop and interview the Captain in small batches:
24
+ - What does this project do, for whom, and what is explicitly out of scope?
25
+ - What are the main modules and their boundaries? Which invariants must no PR break?
26
+ - What are the real commands for setup, lint, typecheck, unit/integration tests, and acceptance tests?
27
+
28
+ Draft the missing files yourself from the answers and the repository. Never invent an invariant, a non-goal, or a command. Show the diff before saving. Configure the `Makefile` targets, run `npx specsail doctor` if available, and commit with `docs:`/`chore:` as appropriate. Only then continue.
29
+
30
+ ## 2. Start the feature
31
+ Ask the Captain for a short kebab-case slug if it is not obvious, and classify it:
32
+ - **FIX**: bug with a reproducible failure.
33
+ - **UPDATE**: an existing behavior changes.
34
+ - **NEW FEATURE**: new behavior.
35
+
36
+ Scaffold `specs/<slug>/` from `.specsail/templates/specs/_templates/`, or run `npx specsail new <slug> <fix|update|new>` if available. Commit the scaffold with the `spec:` prefix.
37
+
38
+ ## 3. Run the stages
39
+ Each stage is a role lens: read its `SKILL.md`, adopt its reads/writes/must-not rules, and stop where it says to stop. Ask the Captain questions at any stage; never guess an answer that belongs to them.
40
+
41
+ 1. **Scout (`understand`)** — clarify and write `request.md`. Confirm routing and open questions. Gate: Captain confirms the request.
42
+ 2. **Navigator (`plan`), spec mode** — write `spec.md` with observable `AC-n` criteria. Gate: Captain approves the spec.
43
+ 3. **Navigator, plan mode** — write `plan.md` and `tasks.md` from the approved spec. Gate: architecture decisions, if affected.
44
+ 4. **Quartermaster (`acceptance-tests`)** — write failing tests for this phase's ACs only. Gate: Captain approves the tests.
45
+ 5. **Hands (`implement`)** — one task at a time, TDD, `make verify` green, status `DEV_DONE`.
46
+ 6. **Bosun (`review`)** — independent review. Ask the Captain each time: open a second session/model for an independent review, or accept same-model review. If they accept, record the caveat in `review.md`. Rework up to three times.
47
+ 7. **Clerk (`ship`)** — docs, changelog, PR body. The Captain merges.
48
+
49
+ Do not skip a stage because the change "looks simple" or to save time. For FIX, still write the reproduction AC.
50
+
51
+ ## Gate protocol
52
+ - Present the artifact and ask: **"APPROVE, or what should change?"**
53
+ - Silence, a different topic, or "ok" about something else is not approval. Ask again.
54
+ - On explicit approval, record it in the artifact: `Status: APPROVED — Captain (chat), YYYY-MM-DD`. You are recording the Captain's decision, not making it. If the Captain edits the file directly, keep their wording and do not overwrite it.
55
+ - On changes, revise and return to the same gate. Never approve on the Captain's behalf, never merge, never weaken an acceptance test to get past a gate.
56
+
57
+ ## Resuming
58
+ Read `specs/*/` and `tasks.md`. If one feature is active, say where it is and continue from that stage. If several are active, ask which one. Use the "Where am I?" table in `.specsail/docs/runbook.md` when unsure.
59
+
60
+ ## Mechanical steps you may run
61
+ Scaffolding, stage commits with the required prefixes (`spec:`, `plan:`, `accept:`, `feat:`, `fix:`, `docs:`), `make verify`, `make check-protected`, and placeholder-free PR creation. Do not hand-edit protected artifacts outside their owning stage.
62
+
63
+ ## Must not
64
+ Implement outside the Hands stage; approve specs or tests; merge; invent requirements; skip the independent-review question; let the Captain's chat content be the only record when a file can carry the decision.
65
+
66
+ ## Done when
67
+ The PR is open, docs are current, and the Captain has what they need to merge.
68
+
69
+ ## Escalate when
70
+ The spec is contradictory or untestable, a gate stalls, or review hits three loops. Write `specs/<feature>/blocked.md`, set the task `BLOCKED`, and stop for the Captain.
@@ -0,0 +1,41 @@
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
+ ## Conversational mode
12
+ When the First Mate (orchestrator) runs this stage, present the artifact and ask the Captain to approve or request changes. Record their explicit decision as described in `.specsail/skills/manage/SKILL.md`; never infer approval.
13
+
14
+ ## Reads
15
+ `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.
16
+
17
+ ## Mode A: spec (when spec.md is missing or `Status: DRAFT`)
18
+ Writes `spec.md`: Overview, Objective, Acceptance criteria, Out of scope.
19
+ - Acceptance criteria are Given/When/Then, with stable IDs `AC-1`, `AC-2`, ...
20
+ - Each AC is observable behavior, testable without knowing the implementation.
21
+ - Use glossary terms exactly. Put anything uncertain under "Open questions", not in an AC.
22
+ - FIX type: AC-1 must be the reproduction of the bug.
23
+ - 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.
24
+
25
+ ## Mode B: plan (when spec.md is `Status: APPROVED`)
26
+ Writes `plan.md` and `tasks.md`.
27
+ - Tasks are thin vertical slices, grouped in phases. Each lists: AC IDs, scope, verification command.
28
+ - Do not create tasks for branches or PRs (scripted).
29
+ - Multi-app: define the API contract first, then per-app tasks that can run in parallel.
30
+ - Include "Docs to update" and "Risks and mitigations".
31
+ - Architecture decisions only if request.md says Architecture affected = YES; create ADRs for significant ones.
32
+ - Every AC must be covered by at least one task.
33
+
34
+ ## Must not
35
+ Edit an APPROVED spec; write tests or code; set `Status: APPROVED`.
36
+
37
+ ## Done when
38
+ Mode A: spec complete and every AC testable. Mode B: every AC mapped to a task, every task has a verify command.
39
+
40
+ ## Escalate when
41
+ An AC is untestable, contradictory, or requires an architecture change the request didn't flag.