Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Contributing

Boatstack is a generated content distribution. Propose changes to workflow semantics, templates, evidence rules, or generated presentation in [Intelligence Flow](https://github.com/operatorstack/intelligence-flow/tree/d37975f8c3960b03c701f029d4815f6d6814ed7c/examples/12-product-engineering-loop).
Boatstack is a generated content distribution. Propose changes to workflow semantics, templates, evidence rules, or generated presentation in [Intelligence Flow](https://github.com/operatorstack/intelligence-flow/tree/4bc614dd6355dcc408e2a49955cb53b868d5dee8/examples/12-product-engineering-loop).

The Boatstack repository receives product/runtime changes through a generated pull request. Review the PR's `UPSTREAM.json`, tests, adapter diff, and context-size change; do not hand-edit generated output on `main`. `.github/workflows` is the exception: it is Boatstack's executable control plane, excluded from scheduled projection and changed only through a separate manually reviewed Boatstack PR.

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ Boatstack does not replace your product context or force a new documentation sys

These tools may propose content. They do not approve their own proposal or bypass Boatstack's evidence checks.

## Updates stay out of product work

<!-- boatstack-claim:visible-updates -->After a PR is published, Boatstack can quietly report that a new stable release exists. It does not change the feature branch. From a clean default branch, `/boatstack-update` prepares a versioned infrastructure branch, shows the exact diff, and waits for `open update PR` before changing GitHub. It never merges the update.

[See how updates remain visible and separate](docs/getting-started.md#keeping-boatstack-current).

<details>
<summary><strong>Install manually</strong></summary>

Expand Down
46 changes: 24 additions & 22 deletions UPSTREAM.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"canonical_context": {
"characters": 30577,
"estimated_tokens": 7645,
"characters": 32685,
"estimated_tokens": 8172,
"estimator": "ceil(total characters / 4); compactness signal, not provider billing",
"files": [
"product-engineering-loop/references/workflow.md",
Expand All @@ -12,12 +12,12 @@
},
"files": {
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
"CONTRIBUTING.md": "fe20dd1fbfa7e5b2cca253ce089808b388250ddecec603099688064a23e4e664",
"README.md": "0b817ceabe61d874f21f98362f550cb77f1819bfc3db6df40b69337f50b4641c",
"CONTRIBUTING.md": "c08d6fc79c330a4cb3e8f2a8ab1d4ca2a44c8cb294f0c523fbc6a587a0695875",
"README.md": "9dcc7ba6fd7032b2a11d66891a353508f2f23ffa8fb8969a32a94a5e6db1a3aa",
"assets/boatstack-journey.svg": "c1f7fe2741f5e9ca66bb3fe9b103e6364ba5acbca8b7a8054768ffd85cf325ea",
"assets/boatstack-mark.svg": "c46e935f06fcfde3b37abfd579c1963b765b2337a0fa993f9538c9b652297e39",
"assets/boatstack-model-choice.svg": "979952c2fc6220d41426f9072186fca000fb3f388a4e775cc09cc1e830ebdde4",
"boatstack/SKILL.md": "4d80c39521763831655df0f98224769e0bf3caf535c0751ecf96c33bc33039e5",
"boatstack/SKILL.md": "5c37ec90eb8c3eae60f435f5d62afd1dc826f8bca6916726588379bcb99f3f58",
"boatstack/agents/openai.yaml": "68a30a60859556c5a26e16d184594ca243a6043d99c8cf7d66b5dd6d50a93cd1",
"boatstack/assets/templates/adr.md": "c577a3c1c1319061f61deb053597e6e853657022185fe28b8f733327e2a78565",
"boatstack/assets/templates/approval.md": "74b0b816703a6dce3c96c8f95f981af910b020b6908e7f76cf5630778637e9f5",
Expand All @@ -31,64 +31,66 @@
"boatstack/assets/templates/test-plan.md": "6db8a9f27dd171fb80222a501cae50eb051e7278c04703fa43b5ff86dd4d2df4",
"boatstack/atomic_unix.go": "89f2723361591de2bb8bd22ce7e34ec529d3278509f0df78fd5c4a7d4140fbe9",
"boatstack/atomic_windows.go": "cefd775cbe7e7c3bd8a3f5673b11cdd784c6d3ebd6de7dcb8f39406b0bee511f",
"boatstack/cmd/boatstack-helper/main.go": "7e3039dbae40a98666709583c42ca52fc94570b6cfebf16508c100d6f9593144",
"boatstack/export.go": "bfc8971516addb67cbc27cfce44180e4b62db2b3dc588634d7d5b8f8762d9d1c",
"boatstack/export_test.go": "dd3c2ea58f1ba5591ac21c7c161c730a8d0ac11cbca0148d7f6d505a6a8d0e4b",
"boatstack/cmd/boatstack-helper/main.go": "93a3eda3c6216018d83e0e419e201da7a046aab8f36f9dc6cb2f8b0842335242",
"boatstack/export.go": "c53c5ec83dcea392d2e360c6819202b5f7cf9b3ae64510087bd627c4aaee82e3",
"boatstack/export_test.go": "f95be9c458645e9b150f25921a0452c9e10e6a94809567ee5ddbc8e833e4f040",
"boatstack/go.mod": "daf262a00abfe961d8ca266d4b26eea09a6aee73e4c53baaa537a809eaef59f6",
"boatstack/hooks.go": "3030ca262a39b5bbef8509bb1395b3b9635719dd9ce0b196f72c596922509e92",
"boatstack/hooks_test.go": "5b8852e6176d96315c983f261d8503b57298063eb251283088eb103e42d7ec0d",
"boatstack/init.go": "90d38fb666ac8bbdf3c3f17f8367d3542963477a1eb67a4f1ffcc83dad01a7a6",
"boatstack/init_test.go": "5a65a7d8243e615ef47f797680a3b508a15a7b638e43c857ac74fb139cfded58",
"boatstack/init.go": "74e8f1dda5761c36d62c6679ee8e935138115b930f654c9b9d04a153af2642a7",
"boatstack/init_test.go": "b761ada1f5a04c0a27225a6f1eb99baf5477a424c5a9748a3267f07ba5a84605",
"boatstack/integrations.go": "75b39ce2e662fccd66bf4b9bff0e097a4db558f23b3aa1d9bc83a5fc6373444c",
"boatstack/plan.go": "519fe7a782c0384d62fda228c58145d36e01a3941691b1839a2d1476528c27b7",
"boatstack/plan_test.go": "006cdc6681f77e579c5a0f709e30ede759c337132d4f2f5193b7b79b29bd7149",
"boatstack/planning.go": "a4ff58547b6b880742d213c3cebccb2d7288a622b6c392c31f7dba827af71568",
"boatstack/planning.go": "9485eedde503f54141388ea91d6d7a17f5d59663a38db2af9fddcd933f057571",
"boatstack/planning_test.go": "4662908c1ec063aa8ef6f91db52247864303d9b91ef2363a8f68b41082fe383f",
"boatstack/pr.go": "6fbfd1e673c55e8358090693b20edb9bc6e8efb8913de9ffcaa5143ca24f0947",
"boatstack/pr_test.go": "f200a3a860e3da22798ec17a8eaf335724885b09d48b36bf0c350acdd3cc3ab7",
"boatstack/references/artifacts.md": "0a72961aa7a942056f3185417f545d205a3ce21856e602e367141660298c9410",
"boatstack/references/failure-moves.md": "5ac4bbc279a1f7c2b420c15b0f9bc73fb15c37c8f2ec08c45e1acd3aae46b75a",
"boatstack/references/irreversible-operation-boundary.md": "2a695f2d7de95cfc8750f107bef9c86581712aa1f02e7233b69b850d8c2af42e",
"boatstack/references/portability.md": "fb683095991bb0cb06ec56fb8884c49038b283172a7d2f8b203483b7cacb4bae",
"boatstack/references/workflow.md": "113bf1f207eaa019223462b85faac380d7c43c3217494845e8552f7707f5e645",
"boatstack/references/workflow.md": "0a32f00c12ea1d92db2e3b29ce5cfdcdd5a013c50ae67f2fc56f0ebde6951988",
"boatstack/runtime.go": "b988d57ec14e15fc6a57949a995879fc0e0d6bfa9a7b62935e7754df0b85d87a",
"boatstack/safety.go": "fbf30c34642db6ac18e0e15abbf78cbcd9177cc7aa678b44b4eaabc0202f5bd5",
"boatstack/safety_test.go": "62375fd640d543ab8875c7b31fd935ac7f5385830f625123f44508e629b4ff08",
"boatstack/testdata/reviewer-pr-body.md": "4c64e3788e5d61a377aeb0f797f7fc8d2316ab6e49572d15636eea7ba9e34ac4",
"boatstack/testdata/safety/safe_apply.py.txt": "c9ec7fb932cf21b6aa8df597c4d4c54d6ec65e796240e49118d699f583383975",
"boatstack/testdata/safety/unsafe_apply.py.txt": "42db1751865cc15c4dd69a03146b5deca8f21f916d258e433b27bbef5f884ab1",
"boatstack/update.go": "b801318dce2268f9c02fabc71ab783a36aff9b9b110457204d3231bc18382370",
"boatstack/update_test.go": "aa0c2ca97038aad661c46321600034e206e88639f89e0216b3c4cf597312cbae",
"docs/account-recovery-walkthrough.md": "acd3558a95f48004f18a0590670de496e1cc9f0cd1d187f924615497f57e1d6f",
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
"docs/evidence-engineered-coding.md": "f14acdbaf6da6a11ad8ce73e5befde8af5f879571452b679d18a71a2c6f18191",
"docs/generated-files.md": "7f4d7cddff80d794361c26962b4c89b4e525eafb53776553be966258c6d867c6",
"docs/getting-started.md": "dccb5895bfbf6ac40309c6779f2a23dcdc27355e62a8a4858bb37c043e8de442",
"docs/public-claims.json": "73e41adf3c8ae7b6946145f65d80950842b16cef2350edca3d0936b9b6b21f93",
"docs/evidence-engineered-coding.md": "db352248a0efe1377741c85efdfde05e98fc35ea6c298475781e85eba0122bff",
"docs/generated-files.md": "040149341dceb192ba240edc250f8d3e4124b9b9444d0628df42dab667192db6",
"docs/getting-started.md": "432b64d3de11ffe56204f6eb12712c714eca31620d51afead482be70c76a2f35",
"docs/public-claims.json": "61180ebde073ff37becb34c7f24067a193d19502daaa84927e9b6107a9c22379",
"docs/public-surface.md": "53d741f04b2928a6ee8c006d647a6d675a215e863412e5862cd67d48433bff76",
"docs/research-and-design.md": "d65c66e323037bda5d45aacef5d48afa6bf93da55901378891d235aca3a5684f",
"docs/safety.md": "7b9b5c515d36e683767ec8d3d9d6d119ac93650b2f629d351deadd4c600ed6a6",
"docs/troubleshooting.md": "67ec380fc24226d6afd1d4fe250a123edd153f88bc1e318ee2ef7635e0ae1520",
"docs/troubleshooting.md": "a9f28e156702a970792421766d38cab3fb99a6a9ce497bd058ee4026608798ff",
"docs/validation-and-evidence.md": "a9fe9274f3dc22b152094a307feda5d8c3ab099755100aef77bda13024cc3166",
"docs/why-these-steps.md": "c45092ed7b4c8a913a83b4fcfa22494c76d864fb32ff5943febd6abe1f7de81f",
"docs/why-these-steps.md": "dc633f3edcc0c9d94ee7ea3feb57220987ad63ee8fb08b3df6e438dec866cacd",
"examples/diagram-json/README.md": "061b583180e43bbd26618bbd9d3d79af4b75d7c8f37c66475640745a97328fbc",
"examples/diagram-json/approval.md": "bc421a825349923512d5cb0ce489310d3a4d7cbac35e661a693b4a32eec263d1",
"examples/diagram-json/compiled/evidence.md": "1ba1c989ade070a8ef9a508fbd788d100d7292f2dbacbb2bce895468019f619d",
"examples/diagram-json/compiled/tasks.json": "f040696f1f8bcedc4a8ed9816a61a49edbda970ec0cc3b28175ba37b73bbc896",
"examples/diagram-json/compiled/test-matrix.json": "6c6895c509271e4337f3c91d9f62ee3a2b34e768e78513784cb012506a328ecf",
"examples/diagram-json/plan.lock.json": "b10ea959364285f9ed551a31283f7690c19a921c25d291afb4fa354ae5c7f0aa",
"examples/diagram-json/plan.lock.json": "abceab49b917f84aabd17a4ae2bd8e31fc12b2ca4ed97e55de992b5e49232f3d",
"examples/diagram-json/plan.md": "3ad35cc3cbe48306e7ee401bd9e9047d25e46c8a6fe9679aa1b3f5e96ceea292",
"examples/diagram-json/questions.md": "1a0050041cac0a8d53e6ebfe04cbec4a298cdc8c50efeeb6fa15aeb663c5ec76",
"examples/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
"examples/diagram-json/source-plan.md": "e10593ddaa7522ab80cc991d0a09399257139799e37f737794cd49d68a39985b",
"examples/diagram-json/spec.md": "a943c81cf2a88d23d5b300e6b9dc1dafc80923a9b6b9ab5297a67b4e2054b9d5",
"install.ps1": "c81f2f8eb6032ea82c36ebe98bd015ba4dabb8f4825b3c1bb89baea2a808690c",
"install.sh": "c9caf1eb0554715d189e4183478dfb3ae7e5c0a8187ea44229cbf268276652f8",
"install.ps1": "960b2b20b406bb2878a560e9ace53fe7226bc510be6ee8466ce4e608beb5625a",
"install.sh": "939e604aa153b454e7fa1cbbe50a88be17782ea9df35d1bbb5615c737ed6f86e",
"project.example.json": "d1f7aa3cff0b55ede79500bd2ca710bb99cb2ae579f0a058dc00934accf03d33"
},
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
"schema_version": 1,
"source": {
"commit": "d37975f8c3960b03c701f029d4815f6d6814ed7c",
"commit": "4bc614dd6355dcc408e2a49955cb53b868d5dee8",
"path": "examples/12-product-engineering-loop",
"repository": "operatorstack/intelligence-flow"
}
Expand Down
17 changes: 16 additions & 1 deletion boatstack/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: boatstack
description: Turn a product request into a question-led, specification-first implementation with test, review, and ship gates, then learn from the evidence without silently changing project rules. Use when planning or building a feature, creating an implementation PR, reviewing work against product intent, diagnosing repeated coding-agent failures, or exporting the same engineering loop to Cursor, Claude Code, Codex, and GitHub.
description: Turn a product request into a question-led, specification-first implementation with test, review, and ship gates, then learn from the evidence without silently changing project rules. Use when planning or building a feature, creating an implementation PR, reviewing work against product intent, diagnosing repeated coding-agent failures, updating Boatstack itself, or exporting the same engineering loop to Cursor, Claude Code, Codex, and GitHub.
---

# Boatstack
Expand All @@ -18,6 +18,7 @@ Map the request to one operation:
- `test-gate`: test requirements and relevant regressions using independent evidence.
- `review-gate`: review the diff against the spec, project invariants, risks, and known gaps.
- `ship-gate`: preview, then explicitly open or update, a reviewer-ready PR grounded in the approved diff and evidence.
- `boatstack-update`: check for a stable Boatstack release and prepare its infrastructure-only update branch and PR after explicit confirmation.
- `retro`: classify failures, propose a harness move, and gate it before promotion.
- `export`: generate thin Cursor, Claude Code, Codex, and GitHub adapters.

Expand Down Expand Up @@ -156,11 +157,25 @@ Do not branch the workflow on model brand, price, or a guessed capability tier.
- Show the exact title and rendered body before any GitHub mutation. If no PR exists, make `Reply open PR` the one next action; if one exists, use `Reply update PR`.
- After that exact confirmation, commit only the reviewed `pr.md`, rerun the preview check, require the same preview fingerprint, then invoke the internal publisher with the selected open/update action. It rechecks the current committed diff, approval, lock, and evidence and performs only a normal push. Any intervening change invalidates the preview and requires regeneration; never force-push.
- Keep model attribution inside collapsed provenance. Create or update the PR, but keep merge and deploy as separate authorized actions.
- Only after successful PR publication, perform the bounded cached release check. If a newer stable Boatstack release should be announced, keep `Review the PR` as the one next action and put the no-mutation update notice in collapsed details. Release lookup failure never changes the ship result.
- Never hide failed experiments, skipped checks, or `PASS_WITH_GAPS` behind a green summary.
- If a required check also fails on the base branch, record that comparison and recommend a separate repair PR. Do not edit unrelated code in the approved feature branch. A bypass is valid only when repository policy permits it and the human explicitly authorizes it; otherwise return to planning for any scope expansion.

Gate statuses are `PASS`, `PASS_WITH_GAPS`, and `BLOCKED`. Critical safety, correctness, or product-acceptance gaps always produce `BLOCKED`.

## Update Boatstack separately

Treat `boatstack-update` as infrastructure maintenance, never as feature work:

1. Run the current local helper's `doctor`, then force the cached stable-release check. If Boatstack is current, return **Boatstack is current** with no action required.
2. Fetch the configured default branch without editing product files. Require that branch to be current and clean; otherwise return **Update postponed** and change nothing.
3. Create only `chore/update-boatstack-v<version>`. Run the installer fetched from the exact release tag in update mode with the exact version, repository path, and non-interactive preview acceptance.
4. Preserve `.boatstack-project.json`, all portable adapters, optional integration selections, and unrelated host settings. Block on generated drift, collisions, missing provenance, a failed checksum, a failed `doctor`, or any product-file change.
5. Show the version transition, release notes, integration state, changed infrastructure paths, exact diff, checksums, rollout, and rollback. Respond **Boatstack update ready** with exactly `Reply open update PR` as the next action.
6. Only that exact reply authorizes staging the reviewed infrastructure paths, committing, normally pushing, and opening the update PR. Never merge it. If GitHub publication is unavailable, retain the prepared branch and provide one manual action.

Natural requests such as “Update Boatstack” use this operation. `doctor` may display a cached notice but must remain offline. Do not perform release discovery during planning, approval, build, test, review, or PR preview.

## Improve an existing PR without a public command

When the user naturally asks Boatstack to prepare, improve, summarize, or update a PR and no managed feature package is available:
Expand Down
43 changes: 42 additions & 1 deletion boatstack/cmd/boatstack-helper/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,37 @@ func initCommand(arguments []string) int {
return 0
}

func updateCommand(arguments []string) int {
flags := flag.NewFlagSet("update", flag.ContinueOnError)
repo := flags.String("repo", ".", "repository to update")
binary := flags.String("binary", "", "verified replacement helper binary")
yes := flags.Bool("yes", false, "accept the generated-file preview")
if err := flags.Parse(arguments); err != nil {
return 2
}
err := boatstack.RunUpdate(boatstack.InitOptions{Repo: *repo, BinaryPath: *binary, Yes: *yes})
if err != nil {
return fail(err)
}
return 0
}

func checkUpdateCommand(arguments []string) int {
flags := flag.NewFlagSet("check-update", flag.ContinueOnError)
repo := flags.String("repo", ".", "repository whose Boatstack release should be checked")
force := flags.Bool("force", false, "ignore the 24-hour release cache")
notify := flags.Bool("notify", false, "record a bounded post-ship notification")
if err := flags.Parse(arguments); err != nil {
return 2
}
result, err := boatstack.CheckForUpdate(boatstack.UpdateCheckOptions{Repo: *repo, Force: *force, Notify: *notify})
if err != nil {
return fail(err)
}
fmt.Printf("UPDATE_STATUS=%s\nCURRENT_VERSION=%s\nLATEST_VERSION=%s\nRELEASE_NAME=%q\nRELEASE_NOTES=%q\nRELEASE_URL=%s\nUPDATE_NOTIFY=%t\nUPDATE_FROM_CACHE=%t\n", result.Status, result.CurrentVersion, result.LatestVersion, result.ReleaseName, result.ReleaseNotes, result.ReleaseURL, result.ShouldNotify, result.FromCache)
return 0
}

func exportCommand(arguments []string) int {
flags := flag.NewFlagSet("export", flag.ContinueOnError)
repo := flags.String("repo", "", "repository to export into")
Expand Down Expand Up @@ -205,6 +236,9 @@ func doctorCommand(arguments []string) int {
return fail(err)
}
fmt.Printf("PASS: Boatstack %s installation and generated adapters are healthy\n", boatstack.Version)
if update, ok := boatstack.CachedUpdate(*repo); ok {
fmt.Printf("UPDATE_AVAILABLE=%s\nRELEASE_URL=%s\n", update.LatestVersion, update.ReleaseURL)
}
return 0
}

Expand Down Expand Up @@ -324,17 +358,24 @@ func publishPRCommand(arguments []string) int {
verb = "updated"
}
fmt.Printf("PASS: PR %s without merge authorization\nPR_URL=%s\n", verb, url)
if update, ok := boatstack.PostShipUpdateNotice(*repo); ok {
fmt.Printf("UPDATE_AVAILABLE=%s\nUPDATE_RELEASE_URL=%s\n", update.LatestVersion, update.ReleaseURL)
}
return 0
}

func run() int {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "usage: boatstack-helper <init|export|check-source-plan|planning-write|check-plan|record-approval|activate-plan|check-safety|safety-hook|pr-context|check-pr|publish-pr|doctor|version>")
fmt.Fprintln(os.Stderr, "usage: boatstack-helper <init|update|check-update|export|check-source-plan|planning-write|check-plan|record-approval|activate-plan|check-safety|safety-hook|pr-context|check-pr|publish-pr|doctor|version>")
return 2
}
switch os.Args[1] {
case "init":
return initCommand(os.Args[2:])
case "update":
return updateCommand(os.Args[2:])
case "check-update":
return checkUpdateCommand(os.Args[2:])
case "export":
return exportCommand(os.Args[2:])
case "check-source-plan":
Expand Down
Loading
Loading