Skip to content
Merged
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/46be4fd2d8ebbc00e28c10e78685b721b2c62fe8/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/4fee357eb535287be4b172b2af4c2e44939ce196/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
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<p align="center"><strong>Build freely. Prove it. Ship.</strong></p>

Boatstack is **evidence-engineered coding**: a model-neutral coding node that turns product intent and repository context into an explicitly approved, tested, reviewable change. It does not prescribe the model, implementation technique, tools, or document structure. It governs what may be claimed, approved, or shipped. Its behavior is generated from [Intelligence Flow at `46be4fd2d8ebbc00e28c10e78685b721b2c62fe8`](https://github.com/operatorstack/intelligence-flow/tree/46be4fd2d8ebbc00e28c10e78685b721b2c62fe8/examples/12-product-engineering-loop).
Boatstack is **evidence-engineered coding**: a model-neutral coding node that turns product intent and repository context into an explicitly approved, tested, reviewable change. It does not prescribe the model, implementation technique, tools, or document structure. It governs what may be claimed, approved, or shipped. Its behavior is generated from [Intelligence Flow at `4fee357eb535287be4b172b2af4c2e44939ce196`](https://github.com/operatorstack/intelligence-flow/tree/4fee357eb535287be4b172b2af4c2e44939ce196/examples/12-product-engineering-loop).

> **You are free in how you build. Only claims of completion require evidence.**

Expand Down Expand Up @@ -53,9 +53,11 @@ The installer previews the generated paths, verifies the platform helper, asks a
```text
idea -> Plan mode -> /auto-plan -> questions -> /plan-gate
-> approve -> Build -> /build -> /test-gate
-> /review-gate -> /ship-gate -> PR
-> /review-gate -> /ship-gate -> preview -> confirm -> PR
```

At ship, Boatstack compiles the approved intent, actual committed diff, evidence, decisions, gaps, rollout, and rollback into a reviewer-ready title and body. It shows the exact preview first; GitHub changes only after `open PR` or `update PR`. For an existing branch, simply ask **“Use Boatstack to improve this PR.”** There is no extra `/pr-brief` command, and missing workflow evidence is labeled `NOT_VERIFIED` rather than invented.

## Plan first, then auto-plan

Start with ordinary product intent **inside Cursor, Codex, or Claude Plan mode**:
Expand Down Expand Up @@ -313,7 +315,7 @@ Read the [research and design record](docs/research-and-design.md) and [corpus a

## Context has a budget

The three canonical runtime references currently total approximately **5250 estimated tokens** using `ceil(characters / 4)`. That is a stable compactness signal, not provider billing. Host adapters stay thin and load the operation-specific slice on demand.
The three canonical runtime references currently total approximately **6039 estimated tokens** using `ceil(characters / 4)`. That is a stable compactness signal, not provider billing. Host adapters stay thin and load the operation-specific slice on demand.

## Status

Expand Down
37 changes: 20 additions & 17 deletions UPSTREAM.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"canonical_context": {
"characters": 21000,
"estimated_tokens": 5250,
"characters": 24156,
"estimated_tokens": 6039,
"estimator": "ceil(total characters / 4); compactness signal, not provider billing",
"files": [
"product-engineering-loop/references/workflow.md",
Expand All @@ -11,10 +11,10 @@
},
"files": {
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
"CONTRIBUTING.md": "d6611d54de720531ad55cbb4a711fedfc8cb4a545c580077785a871db7edfcd1",
"README.md": "e3bd6393e0e1d01e57275085598ddb89e7a317ef41e1b56cf0e3ab0783172e00",
"CONTRIBUTING.md": "89ac3ca1d81d4a10e433fcf3246413ae4856f47ae9850471717d75623f82914f",
"README.md": "ad6943d05ba387efcfefc99a2f847a2fd45b4d035766e56b69ad85ac70bff866",
"assets/boatstack-mark.svg": "c46e935f06fcfde3b37abfd579c1963b765b2337a0fa993f9538c9b652297e39",
"boatstack/SKILL.md": "7452435698e962a50162aa22563465c6f8bdf0857646ea0a2aa508f6e7a68fa3",
"boatstack/SKILL.md": "ca9f6119c85dc178f7a98bc4dc8fa0b66f1f6d00465381f5489272d7413ea6bc",
"boatstack/agents/openai.yaml": "68a30a60859556c5a26e16d184594ca243a6043d99c8cf7d66b5dd6d50a93cd1",
"boatstack/assets/templates/adr.md": "c577a3c1c1319061f61deb053597e6e853657022185fe28b8f733327e2a78565",
"boatstack/assets/templates/approval.md": "74b0b816703a6dce3c96c8f95f981af910b020b6908e7f76cf5630778637e9f5",
Expand All @@ -28,9 +28,9 @@
"boatstack/assets/templates/test-plan.md": "6db8a9f27dd171fb80222a501cae50eb051e7278c04703fa43b5ff86dd4d2df4",
"boatstack/atomic_unix.go": "89f2723361591de2bb8bd22ce7e34ec529d3278509f0df78fd5c4a7d4140fbe9",
"boatstack/atomic_windows.go": "cefd775cbe7e7c3bd8a3f5673b11cdd784c6d3ebd6de7dcb8f39406b0bee511f",
"boatstack/cmd/boatstack-helper/main.go": "e21101b8df6170c01a98bff71f8a2e9d7ac9ef92b883ec50020eb3a011a7737d",
"boatstack/export.go": "16b3d7a88668f374d73db58d87e48207151d39578309ca44efc46ed4b1605c69",
"boatstack/export_test.go": "28cac84532a7ee4dbe9a5f58ea9560db6f978fd3deded4eea76327121a8a0084",
"boatstack/cmd/boatstack-helper/main.go": "8f63ed355fd9e28d57b04d744ce1369865d875047db0bdfc2add5ea60987a500",
"boatstack/export.go": "f09b39643eba5b96b5f53b5f838a07cd78186524db667319a0f55d9d98b0b6dd",
"boatstack/export_test.go": "2298a48972b30c072005722572d4b45822cad389839834f14629fff3ec43b6f8",
"boatstack/go.mod": "daf262a00abfe961d8ca266d4b26eea09a6aee73e4c53baaa537a809eaef59f6",
"boatstack/init.go": "40e62f3502fe704e98dfbb0017e8869fd6aed3011d508a8448d882fe9ed6b52c",
"boatstack/init_test.go": "282451f7abd03c32c536512568f0cfcb858754835523d16706ac1de4f5fc6419",
Expand All @@ -39,26 +39,29 @@
"boatstack/plan_test.go": "f95ce7a38276f957064ee83901566c84ebf3eec0683e81794f823dc446b2ac54",
"boatstack/planning.go": "d8b0b9842beb37392f0993f273849d45edd9564c1b17afe78d418a8c9c0d8f06",
"boatstack/planning_test.go": "4662908c1ec063aa8ef6f91db52247864303d9b91ef2363a8f68b41082fe383f",
"boatstack/references/artifacts.md": "22b6cc596b65c8c2a22b0f3a692ca16a808fa495dad0b4453d23ea734978a2b7",
"boatstack/pr.go": "3b9c924b5a149230b28d98a849c85788d4ee20c6a8a4af8f83c6aa74b01f73cf",
"boatstack/pr_test.go": "f03d8d4cbb879f6c1cfe4b9daa240bda75b737490540930085cdf719a063701f",
"boatstack/references/artifacts.md": "fc6438b43a6de998fa20da91f1703248ca0b2707b83e4d65898eab9a80cb9aeb",
"boatstack/references/failure-moves.md": "2d7d3988c70718e9cc02104f9899a00208173e2f654d1046edd22079f4d46f41",
"boatstack/references/portability.md": "fb683095991bb0cb06ec56fb8884c49038b283172a7d2f8b203483b7cacb4bae",
"boatstack/references/workflow.md": "8f8624c88a7f61fdb28baa5f1c24e285c14a0e25a122c6fda3572e7d0d6a56cf",
"boatstack/references/workflow.md": "84c9a244d8d8564d4dee1a8c4b38d7bc41685b395dcdebab26233c591b2a2dd2",
"boatstack/runtime.go": "b988d57ec14e15fc6a57949a995879fc0e0d6bfa9a7b62935e7754df0b85d87a",
"boatstack/testdata/reviewer-pr-body.md": "7cf83e5deb07bc1d145266820afd7f58e3d3ec6b8d3ca1eb2f9b353b36925c2e",
"docs/account-recovery-walkthrough.md": "912edec85d930750c044bcd6117df9d03491a8c91f139af3ee82ab853452f1b7",
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
"docs/evidence-engineered-coding.md": "fb63e822926fb07cec95b836a2cb7ac2ad6c17f95f54d7e5cdd4cf782ba0fd2a",
"docs/generated-files.md": "0ca73d52bb286b86324c6bcf0ef1c5aee5dc831e35b826b8a9e8cce65c311505",
"docs/getting-started.md": "4e32193555d10c070edbbb58fc90cbec8a4f141ae73ba45809cb74424b794b7c",
"docs/research-and-design.md": "67dc454f0d13e0e2809f49e910f7847457fa78f03c4cef6fb0138f6039a57c4f",
"docs/troubleshooting.md": "6a2f8483d6f1fb7e0ae6265f3a07af05583e8c5585b8b887d307702bd9b14705",
"docs/evidence-engineered-coding.md": "2249eab16ea28543f077935ef45b9ef336aeeedfbd9fbca89bc537808a67cc40",
"docs/generated-files.md": "6670e6f607ac8a7a4a7201429a944e4fccdbc40c27f0909430aea93c12f5eaa1",
"docs/getting-started.md": "bd943f6e965e2f4fc9be5348cc76574d5d0926f2b18d9d93697155d5f5f9c690",
"docs/research-and-design.md": "84e0eac2b59843c1e9b7a9d8c60ec12cca563e501c9e7306e283cef683795cc1",
"docs/troubleshooting.md": "d961f6f209fb291bf0aec6be3ac41cc0a1eeec4526d0668d67ae2fe71c59c41d",
"docs/validation-and-evidence.md": "3b5ed588bd44c5568f0c313be0dfaa411e959dc184fe886dfd0a81aee9fd25cc",
"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": "b477e561d295bf762daf6b631bab01896420eb25aa51b49ca0efdc369bd1611b",
"examples/diagram-json/plan.lock.json": "7d5274e024ea27231b1f57dcff36465a58b01fc4862bca3d7efad91ebb327041",
"examples/diagram-json/plan.md": "3ad35cc3cbe48306e7ee401bd9e9047d25e46c8a6fe9679aa1b3f5e96ceea292",
"examples/diagram-json/questions.md": "1a0050041cac0a8d53e6ebfe04cbec4a298cdc8c50efeeb6fa15aeb663c5ec76",
"examples/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
Expand All @@ -71,7 +74,7 @@
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
"schema_version": 1,
"source": {
"commit": "46be4fd2d8ebbc00e28c10e78685b721b2c62fe8",
"commit": "4fee357eb535287be4b172b2af4c2e44939ce196",
"path": "examples/12-product-engineering-loop",
"repository": "operatorstack/intelligence-flow"
}
Expand Down
26 changes: 24 additions & 2 deletions boatstack/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Map the request to one operation:
- `build`: activate the approved Markdown plan, then implement its tasks in bounded, reversible slices.
- `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`: prepare a reviewable PR with evidence, rollback notes, and explicit gaps.
- `ship-gate`: preview, then explicitly open or update, a reviewer-ready PR grounded in the approved diff and evidence.
- `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 @@ -140,12 +140,34 @@ Do not branch the workflow on model brand, price, or a guessed capability tier.
### Ship gate

- Require a clean, intentional diff; passing required checks; a filled evidence ledger; explicit known gaps; and rollout/rollback notes.
- Create a PR, but keep merge and deploy as separate authorized actions.
- Project only review-relevant context into `.product-loop/features/<feature>/pr.md`: why, changed behavior, review order, decisions, acceptance evidence, gaps, risks, rollout, rollback, and collapsed provenance.
- Treat the actual committed diff as what changed, approved artifacts as why it changed, and evidence as the only support for completion claims.
- In the visible Evidence table, link each managed claim to the current repository-relative evidence ledger using a readable link label; do not expose hashes or absolute paths.
- Always include why, what changed, review order, evidence, gaps/risks, rollout/rollback, and collapsed provenance. Add UI evidence, security/privacy, migration, or operations sections only when relevant.
- Internally generate the normalized context and preview skeleton with `pr-context --repo . --feature <feature>`, write `pr.md`, and validate it with `check-pr --repo . --preview <pr.md>`. Keep these helper names and their fingerprints out of the primary response.
- Inspect the projected changed files, diff stat, high-risk matches, and actual diff before composing the brief. Commit messages are navigation aids, not proof of what changed.
- 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.
- 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`.

## 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:

1. Do not invent a `/pr-brief` command or require the user to learn another operation.
2. Project the current committed branch diff, commits, observed checks, and relevant repository context into `.product-loop/pr-briefs/<branch>/pr.md`.
3. Use the same reviewer-first title/body contract as `ship-gate`, but label missing approval or gate evidence `NOT_VERIFIED`. Never imply Boatstack approved the plan or passed a gate that did not run.
4. Add conditional security/privacy, migration, UI evidence, or operations sections only when the diff makes them relevant.
5. Preview the exact title and rendered body. Ask for only `Reply open PR` or `Reply update PR`, as appropriate.
6. Internally run `pr-context --repo .` without a feature, validate with `check-pr`, and keep those mechanics out of the primary response.
7. After confirmation, commit only `pr.md`, recheck the exact preview fingerprint and committed diff, then publish with the selected open/update action. If anything changed, regenerate instead of publishing stale text.

This is a two-slice ZCA projection: the reviewer brief minimizes review effort, while collapsed provenance preserves the evidence boundary. The projection must not become a dump of every generated artifact.

## Learn without overfitting

Read [failure-moves.md](references/failure-moves.md) before proposing a loop change.
Expand Down
88 changes: 87 additions & 1 deletion boatstack/cmd/boatstack-helper/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,89 @@ func doctorCommand(arguments []string) int {
return 0
}

func prContextCommand(arguments []string) int {
flags := flag.NewFlagSet("pr-context", flag.ContinueOnError)
repo := flags.String("repo", ".", "repository whose branch should be projected")
feature := flags.String("feature", "", "managed Boatstack feature slug; omit for evidence-limited ad-hoc mode")
base := flags.String("base", "", "base branch; defaults to the Boatstack project configuration")
format := flags.String("format", "json", "json or template")
if err := flags.Parse(arguments); err != nil {
return 2
}
context, err := boatstack.PreparePRContext(boatstack.PRContextOptions{Repo: *repo, Feature: *feature, Base: *base})
if err != nil {
return fail(err)
}
switch *format {
case "json":
value, err := boatstack.PRContextJSON(context)
if err != nil {
return fail(err)
}
fmt.Print(string(value))
case "template":
fmt.Print(boatstack.PRPreviewTemplate(context))
default:
return fail(fmt.Errorf("pr-context format must be json or template"))
}
return 0
}

func checkPRCommand(arguments []string) int {
flags := flag.NewFlagSet("check-pr", flag.ContinueOnError)
repo := flags.String("repo", ".", "repository containing the PR preview")
previewPath := flags.String("preview", "", "reviewed pr.md preview")
if err := flags.Parse(arguments); err != nil {
return 2
}
if *previewPath == "" {
return fail(fmt.Errorf("check-pr requires --preview"))
}
preview, context, err := boatstack.CheckPRPreview(*repo, *previewPath)
if err != nil {
return fail(err)
}
action, url, actionErr := boatstack.RecommendedPRAction(*repo)
fmt.Printf("PASS: exact PR preview matches the current branch and evidence\nPR_ACTION=%s\nPR_TITLE=%s\nPREVIEW_FINGERPRINT=%s\nCONTEXT_FINGERPRINT=%s\n", action, preview.Title, preview.Fingerprint, context.ContextFingerprint)
if url != "" {
fmt.Printf("PR_URL=%s\n", url)
}
if actionErr != nil {
fmt.Printf("PUBLICATION_NOTE=%s\n", actionErr)
}
fmt.Printf("--- PR BODY ---\n%s\n--- END PR BODY ---\n", string(boatstack.PRBody(preview)))
return 0
}

func publishPRCommand(arguments []string) int {
flags := flag.NewFlagSet("publish-pr", flag.ContinueOnError)
repo := flags.String("repo", ".", "repository containing the PR preview")
previewPath := flags.String("preview", "", "reviewed pr.md preview")
fingerprint := flags.String("preview-fingerprint", "", "exact preview fingerprint confirmed by the human")
action := flags.String("action", "", "open or update")
if err := flags.Parse(arguments); err != nil {
return 2
}
if *previewPath == "" || *fingerprint == "" || *action == "" {
return fail(fmt.Errorf("publish-pr requires --preview, --preview-fingerprint, and --action"))
}
url, err := boatstack.PublishPR(boatstack.PRPublishOptions{
Repo: *repo, PreviewPath: *previewPath, ExpectedFingerprint: *fingerprint, Action: *action,
})
if err != nil {
return fail(err)
}
verb := "opened"
if *action == "update" {
verb = "updated"
}
fmt.Printf("PASS: PR %s without merge authorization\nPR_URL=%s\n", verb, url)
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|doctor|version>")
fmt.Fprintln(os.Stderr, "usage: boatstack-helper <init|export|check-source-plan|planning-write|check-plan|record-approval|activate-plan|pr-context|check-pr|publish-pr|doctor|version>")
return 2
}
switch os.Args[1] {
Expand All @@ -219,6 +299,12 @@ func run() int {
return recordApprovalCommand(os.Args[2:])
case "activate-plan":
return activatePlanCommand(os.Args[2:])
case "pr-context":
return prContextCommand(os.Args[2:])
case "check-pr":
return checkPRCommand(os.Args[2:])
case "publish-pr":
return publishPRCommand(os.Args[2:])
case "doctor":
return doctorCommand(os.Args[2:])
case "version":
Expand Down
Loading
Loading