From 2294cbdbd7752b7f3bf83f756739bf1b9d1cb660 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 16 Jul 2026 23:35:59 +0000
Subject: [PATCH] Sync Boatstack from Intelligence Flow 46be4fd2d8eb
---
CONTRIBUTING.md | 2 +-
README.md | 4 +-
UPSTREAM.json | 24 +++++------
boatstack/SKILL.md | 6 +++
boatstack/export.go | 26 +++++++-----
boatstack/export_test.go | 43 ++++++++++++++++++++
boatstack/references/workflow.md | 37 +++++++++++++++++
docs/evidence-engineered-coding.md | 4 +-
docs/getting-started.md | 59 +++++++++++++++++++++++++++-
examples/diagram-json/plan.lock.json | 2 +-
10 files changed, 177 insertions(+), 30 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fb66ee3..9eb46d7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -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/f0e2e942835de000a96d6e2530cc8dc16999728c/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/46be4fd2d8ebbc00e28c10e78685b721b2c62fe8/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.
diff --git a/README.md b/README.md
index e989ee8..b096e4e 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
Build freely. Prove it. Ship.
-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 `f0e2e942835de000a96d6e2530cc8dc16999728c`](https://github.com/operatorstack/intelligence-flow/tree/f0e2e942835de000a96d6e2530cc8dc16999728c/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 `46be4fd2d8ebbc00e28c10e78685b721b2c62fe8`](https://github.com/operatorstack/intelligence-flow/tree/46be4fd2d8ebbc00e28c10e78685b721b2c62fe8/examples/12-product-engineering-loop).
> **You are free in how you build. Only claims of completion require evidence.**
@@ -313,7 +313,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 **4625 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 **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.
## Status
diff --git a/UPSTREAM.json b/UPSTREAM.json
index b8cf738..ca17445 100644
--- a/UPSTREAM.json
+++ b/UPSTREAM.json
@@ -1,7 +1,7 @@
{
"canonical_context": {
- "characters": 18498,
- "estimated_tokens": 4625,
+ "characters": 21000,
+ "estimated_tokens": 5250,
"estimator": "ceil(total characters / 4); compactness signal, not provider billing",
"files": [
"product-engineering-loop/references/workflow.md",
@@ -11,10 +11,10 @@
},
"files": {
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
- "CONTRIBUTING.md": "5e4505bd14de4737b776653a6056bc60c52e5197f9e50865300bb61c68bd1a87",
- "README.md": "962c4d534c4a6d95fd4e0a912cf9bcfc11acea5530f10b454ceae703f8779763",
+ "CONTRIBUTING.md": "d6611d54de720531ad55cbb4a711fedfc8cb4a545c580077785a871db7edfcd1",
+ "README.md": "e3bd6393e0e1d01e57275085598ddb89e7a317ef41e1b56cf0e3ab0783172e00",
"assets/boatstack-mark.svg": "c46e935f06fcfde3b37abfd579c1963b765b2337a0fa993f9538c9b652297e39",
- "boatstack/SKILL.md": "724dddef577576fb4c26e871422a4304fea3dc1d8b0f9324da200f20cd93078c",
+ "boatstack/SKILL.md": "7452435698e962a50162aa22563465c6f8bdf0857646ea0a2aa508f6e7a68fa3",
"boatstack/agents/openai.yaml": "68a30a60859556c5a26e16d184594ca243a6043d99c8cf7d66b5dd6d50a93cd1",
"boatstack/assets/templates/adr.md": "c577a3c1c1319061f61deb053597e6e853657022185fe28b8f733327e2a78565",
"boatstack/assets/templates/approval.md": "74b0b816703a6dce3c96c8f95f981af910b020b6908e7f76cf5630778637e9f5",
@@ -29,8 +29,8 @@
"boatstack/atomic_unix.go": "89f2723361591de2bb8bd22ce7e34ec529d3278509f0df78fd5c4a7d4140fbe9",
"boatstack/atomic_windows.go": "cefd775cbe7e7c3bd8a3f5673b11cdd784c6d3ebd6de7dcb8f39406b0bee511f",
"boatstack/cmd/boatstack-helper/main.go": "e21101b8df6170c01a98bff71f8a2e9d7ac9ef92b883ec50020eb3a011a7737d",
- "boatstack/export.go": "75e21e6602f7410bd332c2651097e77463976adc6977edd5b0415e33a25067e8",
- "boatstack/export_test.go": "33c4d0754e59cfb6fc92938ffb3547f267a5dfdd6e8d5f8c359bef349b2862d4",
+ "boatstack/export.go": "16b3d7a88668f374d73db58d87e48207151d39578309ca44efc46ed4b1605c69",
+ "boatstack/export_test.go": "28cac84532a7ee4dbe9a5f58ea9560db6f978fd3deded4eea76327121a8a0084",
"boatstack/go.mod": "daf262a00abfe961d8ca266d4b26eea09a6aee73e4c53baaa537a809eaef59f6",
"boatstack/init.go": "40e62f3502fe704e98dfbb0017e8869fd6aed3011d508a8448d882fe9ed6b52c",
"boatstack/init_test.go": "282451f7abd03c32c536512568f0cfcb858754835523d16706ac1de4f5fc6419",
@@ -42,14 +42,14 @@
"boatstack/references/artifacts.md": "22b6cc596b65c8c2a22b0f3a692ca16a808fa495dad0b4453d23ea734978a2b7",
"boatstack/references/failure-moves.md": "2d7d3988c70718e9cc02104f9899a00208173e2f654d1046edd22079f4d46f41",
"boatstack/references/portability.md": "fb683095991bb0cb06ec56fb8884c49038b283172a7d2f8b203483b7cacb4bae",
- "boatstack/references/workflow.md": "2829b34cb5d62cca4c8a59e6ac3a62e75b5c6d6b3196005b36c3769e94ba262b",
+ "boatstack/references/workflow.md": "8f8624c88a7f61fdb28baa5f1c24e285c14a0e25a122c6fda3572e7d0d6a56cf",
"boatstack/runtime.go": "b988d57ec14e15fc6a57949a995879fc0e0d6bfa9a7b62935e7754df0b85d87a",
"docs/account-recovery-walkthrough.md": "912edec85d930750c044bcd6117df9d03491a8c91f139af3ee82ab853452f1b7",
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
- "docs/evidence-engineered-coding.md": "4f2f4fe0e2d3396020ae273a8380d83b07bc35f04c1f725a19d9d4d777844b7b",
+ "docs/evidence-engineered-coding.md": "fb63e822926fb07cec95b836a2cb7ac2ad6c17f95f54d7e5cdd4cf782ba0fd2a",
"docs/generated-files.md": "0ca73d52bb286b86324c6bcf0ef1c5aee5dc831e35b826b8a9e8cce65c311505",
- "docs/getting-started.md": "4607ed828b6aa372a350046021bc8c2f6a758927554864a20b2e4a445ee7b57b",
+ "docs/getting-started.md": "4e32193555d10c070edbbb58fc90cbec8a4f141ae73ba45809cb74424b794b7c",
"docs/research-and-design.md": "67dc454f0d13e0e2809f49e910f7847457fa78f03c4cef6fb0138f6039a57c4f",
"docs/troubleshooting.md": "6a2f8483d6f1fb7e0ae6265f3a07af05583e8c5585b8b887d307702bd9b14705",
"docs/validation-and-evidence.md": "3b5ed588bd44c5568f0c313be0dfaa411e959dc184fe886dfd0a81aee9fd25cc",
@@ -58,7 +58,7 @@
"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": "5a7e4c898cfd6474248641da69da383203b365153c57d858addfc1a8cc81232c",
+ "examples/diagram-json/plan.lock.json": "b477e561d295bf762daf6b631bab01896420eb25aa51b49ca0efdc369bd1611b",
"examples/diagram-json/plan.md": "3ad35cc3cbe48306e7ee401bd9e9047d25e46c8a6fe9679aa1b3f5e96ceea292",
"examples/diagram-json/questions.md": "1a0050041cac0a8d53e6ebfe04cbec4a298cdc8c50efeeb6fa15aeb663c5ec76",
"examples/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
@@ -71,7 +71,7 @@
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
"schema_version": 1,
"source": {
- "commit": "f0e2e942835de000a96d6e2530cc8dc16999728c",
+ "commit": "46be4fd2d8ebbc00e28c10e78685b721b2c62fe8",
"path": "examples/12-product-engineering-loop",
"repository": "operatorstack/intelligence-flow"
}
diff --git a/boatstack/SKILL.md b/boatstack/SKILL.md
index 0a1938f..f0246c0 100644
--- a/boatstack/SKILL.md
+++ b/boatstack/SKILL.md
@@ -51,6 +51,12 @@ Inspect only the minimal relevant code and documentation. Look for:
Do not scan the entire repository by default. Record discovered paths and commands in `.product-loop/project.json`; preserve existing host configuration rather than replacing it.
+## Respond to the developer
+
+Follow the **User-facing response contract** in `references/workflow.md` for every operation. Lead with the mapped plain-language outcome, show only decision-relevant content, end with one `### Next step`, and put machine status, helper output, fingerprints, artifact paths, receipts, and locks inside collapsed **Technical details**. Internal operations such as `check-plan`, `record-approval`, and `activate-plan` must not appear in the primary response.
+
+Normal approval is simply `approve`. Use an explicit supplied identity first; otherwise use the authenticated GitHub login when available. Ask once for a name or handle only when no trustworthy identity can be resolved. Never infer the approver from the filesystem username, commit history, or agent identity. If identity is missing after approval, preserve the current approval intent and ask only for identity; do not make the human approve the unchanged plan again.
+
## Run `auto-plan`
0. Require exactly one saved plan file created in the active host's Plan mode. First use the active plan path exposed in host/system conversation context, when available, and validate it with `.product-loop/bin/boatstack-helper check-source-plan --repo . --plan `. Otherwise run `check-source-plan --repo .` to search only `.product-loop/intake/` and bounded repo-local host plan directories. If the result is missing or ambiguous, return `BLOCKED`; never choose by recency alone. An explicit `/auto-plan ` is only the ambiguity fallback. Do not write the missing source plan inside `auto-plan`.
diff --git a/boatstack/export.go b/boatstack/export.go
index 0975027..5baf367 100644
--- a/boatstack/export.go
+++ b/boatstack/export.go
@@ -89,7 +89,9 @@ Run the %s operation from @.product-loop/workflow.md.
Read @.product-loop/project.json, @.product-loop/artifacts.md, and only the minimal repository context relevant to the current feature. %s
-Use the gate semantics in the canonical workflow. Do not redefine them in this adapter. Auto-plan and plan-gate may create or update Markdown only. Classify authoritative repository facts as DISCOVERED, agent suggestions as PROPOSED, and only explicit human responses as ANSWERED. Every material proposal remains in blocking_questions; never label an agent default as answered. If a structured question tool is unavailable, ask 1-3 plain-text questions, return WAITING_FOR_INPUT, and never silently choose a default. Boatstack leaves implementation tactics open, but completion, approval, and shipping claims require current evidence.
+Use the gate semantics in the canonical workflow. Do not redefine them in this adapter. Auto-plan and plan-gate may create or update Markdown only. Classify authoritative repository facts as DISCOVERED, agent suggestions as PROPOSED, and only explicit human responses as ANSWERED. Every material proposal remains in blocking_questions; never label an agent default as answered. If a structured question tool is unavailable, ask 1-3 plain-text questions, return WAITING_FOR_INPUT internally, and never silently choose a default. Boatstack leaves implementation tactics open, but completion, approval, and shipping claims require current evidence.
+
+Follow the User-facing response contract in @.product-loop/workflow.md. Lead with its mapped plain-language outcome, show only decision-relevant content, end with exactly one `+"`### Next step`"+`, and put machine status, helper output, fingerprints, artifact paths, receipts, and locks inside collapsed `+"`Technical details`"+`. Treat helper names in this command as internal control machinery; do not expose them in the primary response.
`, operation, operation, preflight, extra)
}
@@ -148,15 +150,15 @@ func BuildExportBundle(configPath string, config ProjectConfig, rawConfig []byte
}
operations := map[string]string{
- "auto-plan": "Discover exactly one saved Plan-mode file and refine it into a Markdown-only draft feature package whose canonical structured artifact is plan.md. Run check-plan read-only. Do not implement, create JSON or locks, or imply acceptance.",
- "plan-gate": "Run check-plan read-only, present its fingerprint and all open decisions, and require explicit human approval. On approval invoke record-approval with the named human, RFC3339 timestamp, and exact displayed fingerprint so it writes only approval.md. Remain in Plan mode; do not compile or request an early mode switch.",
- "build": "First confirm the host is in an execution-capable mode. If the mode transition is rejected or product-code writes remain unavailable, return READY_FOR_BUILD without activating the plan, compiling JSON, or writing a lock. Only then locate plan.md and approval.md and run activate-plan before the first product-code edit. Stop if it reports BLOCKED. Implementation tactics remain open inside the approved boundary.",
- "test-gate": "Build a requirement-to-evidence matrix and treat self-authored tests as evidence rather than the sole oracle.",
- "review-gate": "Review the actual diff against approved intent, invariants, risks, gaps, and test evidence.",
- "ship-gate": "Prepare a PR only; do not merge or deploy without separate authorization. If a required check fails on the base branch too, record the evidence and recommend a separate repair PR. Never edit unrelated code in this approved feature branch; a policy-approved bypass requires explicit human authorization.",
- "review": "Alias of review-gate: review the actual diff against approved intent, invariants, risks, gaps, and test evidence.",
- "ship": "Alias of ship-gate: prepare a PR only; do not merge or deploy without separate authorization. Keep pre-existing unrelated failures out of the approved feature branch.",
- "retro": "Classify evidence and propose a move; never promote it or change durable rules without a paired gate.",
+ "auto-plan": "Discover exactly one saved Plan-mode file and refine it into a Markdown-only draft feature package whose canonical structured artifact is plan.md. Run check-plan read-only. Do not implement, create JSON or locks, or imply acceptance. If ready, respond with Plan ready and make Run /plan-gate the one next action. If decisions remain, respond with I need your input and ask only 1-3 material questions.",
+ "plan-gate": "Run check-plan read-only, present its fingerprint and all open decisions, and require explicit human approval. The normal user action is simply approve. Resolve approved_by from an explicit supplied identity, otherwise from the authenticated GitHub login when available; ask one short identity follow-up only when neither exists, and never infer it from a filesystem username, commit history, or agent identity. On approval invoke record-approval with the resolved human, RFC3339 timestamp, and exact displayed fingerprint so it writes only approval.md. While pending, respond Ready for your approval with Reply approve as the one next action. After recording, respond Approved — ready to build and make entering the host execution mode and running /build the one next action. Remain in Plan mode; do not compile or request an early mode switch.",
+ "build": "First confirm the host is in an execution-capable mode. If the mode transition is rejected or product-code writes remain unavailable, return READY_FOR_BUILD internally without activating the plan, compiling JSON, or writing a lock. Only then locate plan.md and approval.md and run activate-plan before the first product-code edit. Stop if it reports BLOCKED. Implementation tactics remain open inside the approved boundary. On success respond Build complete and make Run /test-gate the one next action. When a new product decision blocks work, respond Build needs a decision and ask only that question.",
+ "test-gate": "Build a requirement-to-evidence matrix and treat self-authored tests as evidence rather than the sole oracle. On pass respond Tests passed and make Run /review-gate the one next action. On failure respond Testing found a problem and make the required repair or authorization the one next action.",
+ "review-gate": "Review the actual diff against approved intent, invariants, risks, gaps, and test evidence. On pass respond Review passed and make Run /ship-gate the one next action. When blocked respond Changes required and make the highest-priority blocking repair the one next action.",
+ "ship-gate": "Prepare a PR only; do not merge or deploy without separate authorization. If a required check fails on the base branch too, record the evidence and recommend a separate repair PR. Never edit unrelated code in this approved feature branch; a policy-approved bypass requires explicit human authorization. On success respond PR ready or PR opened and make Review the PR the one next action; never imply merge authorization.",
+ "review": "Alias of review-gate: review the actual diff against approved intent, invariants, risks, gaps, and test evidence. Use Review passed or Changes required and the same single-action routing as review-gate.",
+ "ship": "Alias of ship-gate: prepare a PR only; do not merge or deploy without separate authorization. Keep pre-existing unrelated failures out of the approved feature branch. Use PR ready or PR opened and make Review the PR the one next action.",
+ "retro": "Classify evidence and propose a move; never promote it or change durable rules without a paired gate. Respond Improvement proposed and make reviewing or authorizing the experiment the one next action.",
}
if contains(adapters, "cursor") {
@@ -191,8 +193,12 @@ description: Run Boatstack's evidence-engineered coding node for question-led pl
Read .product-loop/project.json and .product-loop/workflow.md. The requested operation is supplied by the user; valid operations are auto-plan, plan-gate, build, test-gate, review-gate/review, ship-gate/ship, and retro.
+Follow the User-facing response contract in .product-loop/workflow.md for every operation. Lead with the mapped plain-language outcome, show only decision-relevant content, end with exactly one Next step, and move machine statuses, helper output, fingerprints, artifact paths, receipts, and locks into collapsed Technical details. Internal helper names must not appear in the primary response.
+
Ordinary product intent must first be explored in the host's Plan mode and saved as a file, preferably under .product-loop/intake/. Auto-plan runs bounded discovery before inspecting the repository and records the single result as source_plan_path. If no file exists or multiple candidates remain, auto-plan is BLOCKED; it must not guess or create a substitute. An explicit path is only an ambiguity override. Auto-plan and plan-gate write Markdown only: plan.md remains canonical and approval.md records explicit acceptance. If the host blocks its normal Markdown writer, use the bounded planning-write helper and never arbitrary shell redirection. Repository facts are DISCOVERED, agent suggestions are PROPOSED, and only human responses are ANSWERED; every material proposal remains blocking. At build, confirm the host can edit product code before activating the plan. A rejected mode transition returns READY_FOR_BUILD and creates no machine artifacts or lock. Once execution is available, activation compiles machine artifacts and the lock before the first product-code edit. The source plan remains required and hash-current through build. Test, review, and ship gates operate from the approved lock, diff, and evidence after build.
+Normal approval is simply approve. Use an explicit supplied identity first; otherwise use the authenticated GitHub login when the repository is on GitHub and it is available. Ask once for a name or handle only when no trustworthy identity can be resolved. Never infer the approver from a filesystem username, commit history, or the coding agent. If identity is unavailable after approve, preserve the current approval intent, create no receipt, and ask only for identity; do not require approval again when the unchanged plan and identity are available.
+
Use .product-loop/artifacts.md for document boundaries and .product-loop/failure-moves.md for improvement experiments. If a structured question tool is unavailable, ask 1-3 plain-text questions and return WAITING_FOR_INPUT; never select defaults on the user's behalf. Do not implement from an unapproved or stale plan. Implementation tactics are open; completion, approval, and shipping claims require current evidence. Do not branch on model identity; use observable state and gate evidence.
At ship, prove whether a failing check is pre-existing by checking the base branch. Keep unrelated repairs in a separate PR; do not modify unrelated code under the approved feature lock. A repository-policy bypass requires explicit human authorization and recorded evidence.
diff --git a/boatstack/export_test.go b/boatstack/export_test.go
index 7afc199..b85e5c8 100644
--- a/boatstack/export_test.go
+++ b/boatstack/export_test.go
@@ -61,12 +61,41 @@ func TestExportAndDriftCheck(t *testing.T) {
autoPlan := string(bundle.Files[".cursor/commands/auto-plan.md"])
planGate := string(bundle.Files[".cursor/commands/plan-gate.md"])
build := string(bundle.Files[".cursor/commands/build.md"])
+ responseOutcomes := map[string][]string{
+ "auto-plan": {"Plan ready", "I need your input"},
+ "plan-gate": {"Ready for your approval", "Approved — ready to build"},
+ "build": {"Build complete", "Build needs a decision"},
+ "test-gate": {"Tests passed", "Testing found a problem"},
+ "review-gate": {"Review passed", "Changes required"},
+ "review": {"Review passed", "Changes required"},
+ "ship-gate": {"PR ready", "PR opened"},
+ "ship": {"PR ready", "PR opened"},
+ "retro": {"Improvement proposed"},
+ }
+ for operation, outcomes := range responseOutcomes {
+ command := string(bundle.Files[".cursor/commands/"+operation+".md"])
+ for _, expected := range []string{"User-facing response contract", "### Next step", "Technical details", "do not expose them in the primary response"} {
+ if !strings.Contains(command, expected) {
+ t.Fatalf("%s adapter is missing response-DX rule %q", operation, expected)
+ }
+ }
+ for _, outcome := range outcomes {
+ if !strings.Contains(command, outcome) {
+ t.Fatalf("%s adapter is missing outcome %q", operation, outcome)
+ }
+ }
+ }
if !strings.Contains(autoPlan, "Markdown-only") || !strings.Contains(autoPlan, "never silently choose a default") || !strings.Contains(autoPlan, "planning-write") || !strings.Contains(autoPlan, "PROPOSED") {
t.Fatal("auto-plan adapter does not enforce the Markdown and question boundaries")
}
if !strings.Contains(planGate, "approval.md") || !strings.Contains(planGate, "Remain in Plan mode") || !strings.Contains(planGate, "record-approval") {
t.Fatal("plan-gate adapter does not keep approval in Plan mode")
}
+ for _, expected := range []string{"normal user action is simply approve", "authenticated GitHub login", "never infer it from a filesystem username"} {
+ if !strings.Contains(planGate, expected) {
+ t.Fatalf("plan-gate adapter is missing approval identity rule %q", expected)
+ }
+ }
if !strings.Contains(build, "activate-plan") || !strings.Contains(build, "READY_FOR_BUILD") || !strings.Contains(build, "without activating") || strings.Contains(build, "compile-plan") {
t.Fatal("build adapter must activate the Markdown plan exactly once")
}
@@ -78,6 +107,20 @@ func TestExportAndDriftCheck(t *testing.T) {
if !strings.Contains(lock, `"source_commit"`) || !strings.Contains(lock, `"integrations"`) {
t.Fatal("generated lock must record runtime provenance and integrations")
}
+ workflow := string(bundle.Files[".product-loop/workflow.md"])
+ for _, expected := range []string{"## User-facing response contract", "Exactly one primary action", "gh api user --jq .login", "Never infer the approver"} {
+ if !strings.Contains(workflow, expected) {
+ t.Fatalf("canonical workflow is missing response contract %q", expected)
+ }
+ }
+ for _, path := range []string{".agents/skills/boatstack/SKILL.md", ".claude/skills/boatstack/SKILL.md"} {
+ adapter := string(bundle.Files[path])
+ for _, expected := range []string{"User-facing response contract", "exactly one Next step", "Normal approval is simply approve", "filesystem username"} {
+ if !strings.Contains(adapter, expected) {
+ t.Fatalf("%s is missing response-DX rule %q", path, expected)
+ }
+ }
+ }
}
func TestExportRefusesUserOwnedCollision(t *testing.T) {
diff --git a/boatstack/references/workflow.md b/boatstack/references/workflow.md
index ec2cad6..2862656 100644
--- a/boatstack/references/workflow.md
+++ b/boatstack/references/workflow.md
@@ -25,6 +25,43 @@ Each transition emits an artifact and evidence. A host adapter may change how a
The `SOURCE_PLAN` file is required from entry through completion of `BUILD`. After build, its path and hash remain recorded for provenance, but `TEST_GATE`, `REVIEW_GATE`, and `SHIP_GATE` do not require the original file to be present.
+## User-facing response contract
+
+Helper commands and state labels are internal control machinery. Every normal response uses:
+
+```markdown
+##
+
+
+
+
+
+### Next step
+
+
+
+
+Technical details
+
+Machine status, helper output, fingerprints, paths, receipts, and locks.
+
+
+```
+
+Lead with a plain outcome, never a machine code such as `PASS`, `PLAN_APPROVED`, `BLOCKED`, `READY_FOR_BUILD`, `PASS_WITH_GAPS`, or `WAITING_FOR_INPUT`. Keep approval-relevant scope, non-goals, decisions, risks, and gaps visible. Move internal operations (`check-plan`, `record-approval`, `activate-plan`), hashes, paths, tables, receipts, locks, and raw output into **Technical details**. **Exactly one primary action:** end with the action that advances or unblocks the current state; a secondary option gets one short sentence. Never route past a blocked state.
+
+| State | Outcome -> one next action |
+|---|---|
+| `auto-plan` ready / needs answers | **Plan ready** -> run `/plan-gate`; **I need your input** -> answer 1-3 material questions |
+| `plan-gate` pending / approved | **Ready for your approval** -> reply `approve`; **Approved — ready to build** -> enter execution mode and run `/build` |
+| `build` success / paused | **Build complete** -> run `/test-gate`; **Build needs a decision** -> answer the blocking question |
+| `test-gate` pass / blocked | **Tests passed** -> run `/review-gate`; **Testing found a problem** -> perform or authorize the repair |
+| `review-gate` pass / blocked | **Review passed** -> run `/ship-gate`; **Changes required** -> address the blocking finding |
+| `ship-gate` success | **PR ready** or **PR opened** -> review the PR; never imply merge authorization |
+| `retro` | **Improvement proposed** -> review or authorize the experiment |
+
+Normal approval is `approve`. Resolve `approved_by` from (1) an identity supplied with approval, (2) the authenticated GitHub login from `gh api user --jq .login` when available, or (3) one short identity follow-up. Never infer the approver from a filesystem username, commit history, or the coding agent. If identity is missing after approval, preserve the current fingerprint and approval intent, create no receipt, and ask only for identity; once resolved against the unchanged plan, do not require another `approve`. Keep identity and receipt data inside **Technical details**.
+
## State contracts
### `INTENT -> SOURCE_PLAN`
diff --git a/docs/evidence-engineered-coding.md b/docs/evidence-engineered-coding.md
index 7f9238e..f4b4ffd 100644
--- a/docs/evidence-engineered-coding.md
+++ b/docs/evidence-engineered-coding.md
@@ -90,7 +90,7 @@ subject to acceptance criteria pass
approval is current
```
-That is why context trimming is not automatically an optimization. If removing state increases rework or false acceptance, total cost rises. The canonical runtime references are approximately **4625 estimated tokens**, while host adapters point to one operation at a time.
+That is why context trimming is not automatically an optimization. If removing state increases rework or false acceptance, total cost rises. The canonical runtime references are approximately **5250 estimated tokens**, while host adapters point to one operation at a time.
## Control appears at transitions
@@ -140,6 +140,6 @@ Delivery and system improvement also remain separate. A failed task may suggest
## What is evidence-backed
-The current moves were derived from the Intelligence Flow benchmark corpus and product-repository studies. The generated source commit is [`f0e2e942835de000a96d6e2530cc8dc16999728c`](https://github.com/operatorstack/intelligence-flow/tree/f0e2e942835de000a96d6e2530cc8dc16999728c/examples/12-product-engineering-loop).
+The current moves were derived from the Intelligence Flow benchmark corpus and product-repository studies. The generated source commit is [`46be4fd2d8ebbc00e28c10e78685b721b2c62fe8`](https://github.com/operatorstack/intelligence-flow/tree/46be4fd2d8ebbc00e28c10e78685b721b2c62fe8/examples/12-product-engineering-loop).
The evidence supports specific failure mechanisms and guardrails. It does not establish that Boatstack is optimal, that control-theory notation proves software quality, or that one workflow dominates every team. Those are evaluation questions, so the distribution preserves measurements, provenance, gaps, and negative results.
diff --git a/docs/getting-started.md b/docs/getting-started.md
index dfbc9ec..05cfa3c 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -55,7 +55,7 @@ Run:
/auto-plan
```
-`/auto-plan` may answer discoverable repository facts, but it cannot answer product decisions for you. If it asks questions, answer them in plain text. Material agent suggestions stay `PROPOSED`; only your responses become `ANSWERED`. Re-run `/auto-plan` until `check-plan` passes and the draft is ready.
+`/auto-plan` may answer discoverable repository facts, but it cannot answer product decisions for you. If it asks questions, answer them in plain text. Material agent suggestions stay `PROPOSED`; only your responses become `ANSWERED`. Re-run `/auto-plan` until the draft is ready.
## 3. Review and approve the exact plan
@@ -65,7 +65,62 @@ Run:
/plan-gate
```
-Boatstack presents the intended outcome, non-goals, decisions, known gaps, validation origins, and an exact fingerprint. Request changes or explicitly reply `approve`. Approval records a named human and the displayed fingerprint in `approval.md`; it does not build code.
+Boatstack presents the intended outcome, non-goals, decisions, known gaps, and validation plan. Request changes or explicitly reply `approve`. When available, Boatstack uses your authenticated GitHub username for the internal approval record; it asks for a name or handle only when no trustworthy identity is available. Approval does not build code.
+
+### What Boatstack responses look like
+
+Boatstack leads with the outcome and one action. Internal status codes, helper operations, fingerprints, and artifact paths remain available under **Technical details** instead of dominating the response.
+
+After a successful `/auto-plan`:
+
+```markdown
+## Plan ready
+
+The feature plan is complete, with scope, decisions, and known gaps recorded.
+
+### Next step
+
+Run `/plan-gate`.
+
+
+Technical details
+Plan paths, validation output, and fingerprint.
+
+```
+
+When `/plan-gate` needs approval:
+
+```markdown
+## Ready for your approval
+
+This plan builds the agreed slice and keeps the listed non-goals and gaps outside it.
+
+### Next step
+
+Reply `approve`. If something is wrong, describe the change instead.
+
+
+Technical details
+Machine status, fingerprint, and artifact paths.
+
+```
+
+After approval:
+
+```markdown
+## Approved — ready to build
+
+The reviewed plan is approved. No product code has changed yet.
+
+### Next step
+
+Enter your host's execution mode and run `/build`.
+
+
+Technical details
+Approver, timestamp, fingerprint, and approval-record path.
+
+```
## 4. Enter the host's execution surface and build
diff --git a/examples/diagram-json/plan.lock.json b/examples/diagram-json/plan.lock.json
index 12500ec..82cb50c 100644
--- a/examples/diagram-json/plan.lock.json
+++ b/examples/diagram-json/plan.lock.json
@@ -6,7 +6,7 @@
"plan_path": "examples/diagram-json/plan.md",
"plan_sha256": "3ad35cc3cbe48306e7ee401bd9e9047d25e46c8a6fe9679aa1b3f5e96ceea292",
"schema_version": 1,
- "source_commit": "f0e2e942835de000a96d6e2530cc8dc16999728c",
+ "source_commit": "46be4fd2d8ebbc00e28c10e78685b721b2c62fe8",
"source_plan_path": "examples/diagram-json/source-plan.md",
"source_plan_sha256": "e10593ddaa7522ab80cc991d0a09399257139799e37f737794cd49d68a39985b",
"spec_path": "examples/diagram-json/spec.md",