Skip to content

Commit cd21825

Browse files
Sync Boatstack from Intelligence Flow Labs @ b0e65b129cc8 (#61)
Co-authored-by: operator-stack-publisher[bot] <operator-stack-publisher[bot]@users.noreply.github.com>
1 parent dd9413f commit cd21825

11 files changed

Lines changed: 285 additions & 62 deletions

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Contributing
44

5-
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/849cdf48cabc60e5331cc7e8b7668a9f72aff1e6/labs/12-product-engineering-loop).
5+
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/b0e65b129cc80a5cb43543ac4b7f89563b64b45e/labs/12-product-engineering-loop).
66

77
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.
88

README.md

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,48 @@
88

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

11-
## A delivery harness for AI coding agents
11+
## Keep your software delivery process when you change coding agents
1212

13-
<!-- boatstack-claim:portable-product-flow -->An AI coding agent will guess a product decision, call the work "done" on one green check, and lose the reasoning the moment you change tools. Boatstack connects the work from an idea to a reviewed PR so none of that slips: the plan, decisions, gaps, tests, review findings, and project context stay connected along the way. Keep using Cursor, Codex, Claude Code, or Gemini CLI, with the models and specialist skills that fit the work.
13+
Boatstack is a repository-local delivery harness for Cursor, Codex, Claude Code, and Gemini CLI.
1414

15-
The agent remains free to build. Before it says the work is done, Boatstack asks for the approval, tests, review, and recorded evidence appropriate to the change.
15+
AI coding agents can write code quickly, but each tool brings its own planning flow, session state, and definition of “done.” Change agents and your delivery process often disappears with the chat.
1616

17-
**Your product development flow stays with the repository—not the coding agent.** Change tools without rebuilding how you ship or redefining what “done” means. Boatstack carries the workflow and saved project state—not an agent's private chat history or a command already in progress.
17+
<!-- boatstack-claim:portable-product-flow -->Boatstack keeps the delivery process in the repository. Plans, product decisions, tests, review findings, accepted gaps, and completion evidence stay connected from idea to pull request, regardless of which agent or model performs the work. Use Cursor, Codex, Claude Code, or Gemini CLI. Boatstack keeps the same approval, testing, review, and shipping boundaries across them.
18+
19+
**Your product development flow stays with the repository, not the coding agent.** Change agents, models, or specialist skills without rebuilding how your team plans, verifies, reviews, and ships software.
20+
21+
The coding agent executes the work. Boatstack supervises the delivery. Your repository owns the policy and evidence.
1822

1923
<p align="center">
2024
<img src="assets/boatstack-portability.svg" width="900" alt="Change the tools, keep the flow: coding agents, models, and specialist skills feed one repository-owned Boatstack flow that produces a reviewed pull request and useful context for the next feature">
2125
</p>
2226

23-
| You change | Boatstack keeps |
27+
| You change | You keep |
2428
|---|---|
25-
| Cursor, Codex, Claude Code, or Gemini CLI | The same path from planning through PR preparation |
26-
| Lower-cost, general, or frontier model | The same approval, testing, and review requirements |
27-
| React guidance, gstack, Spec Kit, or another skill | Human approval and evidence remain authoritative |
28-
| Session, worktree, or feature | Durable decisions, gaps, evidence, and code state in the repository |
29+
| Cursor, Codex, Claude Code, or Gemini CLI | The same path from approved plan to reviewed PR |
30+
| Lower-cost, general, or frontier model | The same definition of done and proof requirements |
31+
| React guidance, gstack, Spec Kit, or another skill | Human product decisions remain authoritative |
32+
| Session, worktree, or feature | Decisions, open gaps, evidence, and verified delivery state |
33+
34+
## How it works
35+
36+
1. Save a plan in your coding agent.
37+
2. Boatstack validates the plan and pauses for material product decisions.
38+
3. The agent builds freely inside the approved scope.
39+
4. Boatstack checks the promised outcomes against tests and evidence.
40+
5. Review findings, risks, and accepted gaps become a focused PR brief.
41+
6. The resulting context stays in the repository for the next feature.
42+
43+
## Each delivery makes the next one easier
44+
45+
Boatstack does not preserve an agent's private reasoning or replay old chats. It keeps the durable parts of delivery:
46+
- approved product decisions
47+
- unresolved gaps
48+
- validation evidence
49+
- review findings
50+
- verified repository state
51+
52+
That means the next feature starts from recorded project knowledge instead of reconstructing intent from another agent session.
2953

3054
## Install with your coding agent
3155

@@ -76,7 +100,16 @@ Invoke `/repair` in Claude Code, Cursor, or Gemini CLI, or `$boatstack repair` i
76100

77101
Receipts remain as history; published corrections become linked deliveries.
78102

79-
## Features
103+
## What you get
104+
105+
- **Change coding agents without changing how you ship.**
106+
- **Resume work without reconstructing the previous chat.**
107+
- **Stop agents from guessing material product decisions.**
108+
- **Require evidence for every outcome the change claims to deliver.**
109+
- **Create reviewer-ready PRs from the actual scope, changes, risks, and validation.**
110+
111+
<details>
112+
<summary>Technical Features</summary>
80113

81114
- **A guided path from idea to PR.** `/auto-plan` starts a one-action-at-a-time delivery flow.
82115
- **Instant orientation after a break.** `boatstack next` reconstructs the verified stage without treating chat or a running process as workflow evidence, so you resume in seconds instead of re-reading history.
@@ -90,6 +123,8 @@ Receipts remain as history; published corrections become linked deliveries.
90123
- **Portable across your AI stack.** Hosts, models, and skills share one repository-owned delivery contract.
91124
- **Repository-friendly maintenance.** Worktrees restore runtime; updates stay in separate infrastructure PRs.
92125

126+
</details>
127+
93128
### Optional changelog
94129

95130
It is disabled by default. Enable it in `.boatstack-project.json`:
@@ -123,9 +158,9 @@ Boatstack is a repository-local delivery harness.
123158

124159
This does not mean every model performs equally. [See the evidence and paired evaluation design](docs/why-these-steps.md#model-choice-and-budget).
125160

126-
## Why these steps?
161+
## Built from failures observed in real coding work
127162

128-
They derive from coding failures observed in benchmark and product work—not guesses. Each link explains what happened, what Boatstack does, and whether that behavior has actually been tested.
163+
They derive from coding failures observed in benchmark and product work—not guesses. When a failure reveals a reusable delivery problem rather than a project-specific mistake, Boatstack turns it into a boundary future runs can enforce. Each link explains what happened, what Boatstack does, and whether that behavior has actually been tested.
129164

130165
| What happened | What Boatstack does | Current evidence |
131166
|---|---|---|

UPSTREAM.json

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
},
1313
"files": {
1414
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
15-
"CONTRIBUTING.md": "038386f8aa7deeee581c2b5edbfdc3911aea09e7b6e7a5e1ae798e9fa0bcc951",
16-
"README.md": "a90ba7af7a9cbf71c858d99187f66e0f3db305b2a76fc98ba5625f78ac7c23a4",
15+
"CONTRIBUTING.md": "9cf8d9e3f15f2247c5967a189d649392d3edc18d92d2964a30d5069a489ebb52",
16+
"README.md": "8d481f8e395346400726d02f760f831a8b11062de18b7a76fe4cf00e5e12ca08",
1717
"assets/boatstack-journey.svg": "e465befc50c8ce30f3e07e8fd97012931beeb053392c8fbf38ad645023b3cc63",
1818
"assets/boatstack-mark.svg": "be1f984da1bfa69fa5d1f986d8343d21f7e20921b71db888c928b4d2e54b09b5",
1919
"assets/boatstack-portability.svg": "66dfdfa85db857b3bd18b32047a6975f1fbbfc4dc091158e8277193f9969a346",
@@ -36,6 +36,8 @@
3636
"boatstack/changelog_test.go": "ce792f23a7fe1e09fb3096cd1314130a6ab69321d4877b12a8e994027541baf7",
3737
"boatstack/cmd/boatstack-helper/main.go": "3504ea23b4792ac1c3cc1aacbdc245be61217378add98ee52e3dbb342c0240b1",
3838
"boatstack/cmd/boatstack-helper/main_test.go": "ff73003b6a5157202fa09ddf1129fb13c3d79702b2e05a8721ce5a11bf5ab779",
39+
"boatstack/decision.go": "257ca328da6ae19ab252f10ee5d06bd7daf49dd8141d083ab1b32f106ea7a94c",
40+
"boatstack/decision_test.go": "1a92ff832610f9559bd47ccac7fc1755a8b4f8261c35bc72a092830dff05f7c0",
3941
"boatstack/delivery.go": "6ff71b6f4ae4f85a184edaf453b5933a79366e36137802fda056e58f83fe319c",
4042
"boatstack/delivery_test.go": "e0323d4e2ef9c74a07c799cf42df91c90a43d61a0fdfddd8b10c5e3e27d5e492",
4143
"boatstack/evidence.go": "497a31e6ff632cb1d7c3adfc9f269af3f6aa84e948dd5d417c162767542a27df",
@@ -55,8 +57,8 @@
5557
"boatstack/next_test.go": "57828f76257ad7344c383084a97399f6523cbbced28ac2bbe4c14b9da84ccf32",
5658
"boatstack/plan.go": "4ff1b6bf8b187aa26e4851d30c32496a8e979814a5ce2b4b2a1f1d656f7735d0",
5759
"boatstack/plan_test.go": "878dd9086bb583328a7eba1cf45318baeef3d55693be745d5520f07c6ace5e3e",
58-
"boatstack/plan_validation.go": "e601fdcd6ac141aec72819bd95f8411505b81320abbd966e97dfa6cf6d8b771b",
59-
"boatstack/plan_validation_test.go": "7c00279ee271dabaf262e7d6c54d45ee070d1f41ba4ae9d1b5dd146b31ae4070",
60+
"boatstack/plan_validation.go": "848f895e323ae8a428e57f57233e068a8d71c2a7c8716d2ff60e60d23188fd1b",
61+
"boatstack/plan_validation_test.go": "4094b5fdbcb89d7a5a16e4a7595ade88a1f02a13df7824d4c37019b8ca01d860",
6062
"boatstack/planning.go": "4b86ae9dc16393f099ca26812bf3e62909fee42a541b33c33275cc16a80262aa",
6163
"boatstack/planning_test.go": "6b156a64182ed76d4c3d392b4c5a26abe5d8b81cea27ee12ac7c4627c827e186",
6264
"boatstack/pr.go": "28b9c7bd41c0cbe3ec8d05787d868db36b424ecd3489678524fd0f4878262d78",
@@ -89,10 +91,10 @@
8991
"docs/account-recovery-walkthrough.md": "676034974594a7d1a559b24dbed31d7ccc429eb81404b203ca07bbdaa19ec3d3",
9092
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
9193
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
92-
"docs/evidence-engineered-coding.md": "f1a9de99e5d708c469887a3e723a1112df79b504f6732e7631086d2f2ee4ffa6",
94+
"docs/evidence-engineered-coding.md": "4996b3e4639827757734a6fef96a2d6f29ea83d01426292254d1efd73861ab85",
9395
"docs/generated-files.md": "136422baf0c7fc2bd5100cfe0ebdb3d9d0705dfd7e7d54bf745dd1037e63492c",
9496
"docs/getting-started.md": "eacc814fdffdfa3c7d8052b7cd99a79c04da5c75d88d8b44f3fb68d9afec0316",
95-
"docs/public-claims.json": "960de2b346a95f996795420e27dfda0eb3e991433d98581eee2357b0c8b33186",
97+
"docs/public-claims.json": "2f18d8de941840fd6a39661db60120ddfd9e3be391875570086050f94c3d4502",
9698
"docs/public-surface.md": "713f7a050b5f339cf948299103ef3800417dccfecf2cc1a4166397ea6f978907",
9799
"docs/research-and-design.md": "d65c66e323037bda5d45aacef5d48afa6bf93da55901378891d235aca3a5684f",
98100
"docs/safety.md": "7b9b5c515d36e683767ec8d3d9d6d119ac93650b2f629d351deadd4c600ed6a6",
@@ -106,7 +108,7 @@
106108
"labs/diagram-json/compiled/evidence.md": "1ba1c989ade070a8ef9a508fbd788d100d7292f2dbacbb2bce895468019f619d",
107109
"labs/diagram-json/compiled/tasks.json": "88f60851abf79d851e9fccc754ff3040034ae595306bc87d64784c19eb403e71",
108110
"labs/diagram-json/compiled/test-matrix.json": "424657ff505768e50fa113801fd8363364a18269d5297480907a993d44063a39",
109-
"labs/diagram-json/plan.lock.json": "2884dad1e921170c8ee4c8ce279e5dc9ad45e6388ce4dfae0e33db497c002f0c",
111+
"labs/diagram-json/plan.lock.json": "e5541208e20e872bc371459e349656bced442c4de4213f091f108260f961cf82",
110112
"labs/diagram-json/plan.md": "3cc4f533b8d69386deff16b3a594a3ba09d4c0c3db636cccd8c4380084ce6a51",
111113
"labs/diagram-json/questions.md": "74733b015002c8a6777c558e7e997fa48c94850b9bd39054fe9366c97ecf728d",
112114
"labs/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
@@ -148,14 +150,15 @@
148150
"release-notes/2026-07-20-speak-software-standards.md": "a8890ed7eb38868bdf3035572d71785ca89abd3ffc3a314a5dc5315150afe397",
149151
"release-notes/2026-07-21-blueprint-diagrams-value-first-readme.md": "11eb70cb814a99606b4f7761401d3670074fe6bd1af8557f95f573b04a3195af",
150152
"release-notes/2026-07-21-e2e-architecture-grounding.md": "7fa7e99fc6fd4e0688009bb736e6506830bf0216f3fa19757cbd9f5679c7ac3b",
153+
"release-notes/2026-07-21-plan-decision-operator.md": "c2a7416ef17a6042583dd60f1f4e847cb1e0f06b28dbde885479efd566bb5cae",
151154
"release-notes/2026-07-21-prevent-hallucinated-approver-names.md": "a5fd08bc3d8b983340a2ddd67b71c78b2b34a915fdfe6eb7cdffd0f1d52e3427",
152155
"release-notes/2026-07-21-prevent-worktree-dirty-state.md": "d3ebac81a14565461fd7f3c5bd520d881d70b584408ba35a1022cd917c7bf132",
153156
"release-notes/2026-07-21-value-translation-readme.md": "8dd16fd08c1591667a1074fc6825dcbf58beda0faa18ede1526647267418c8ea"
154157
},
155158
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
156159
"schema_version": 1,
157160
"source": {
158-
"commit": "849cdf48cabc60e5331cc7e8b7668a9f72aff1e6",
161+
"commit": "b0e65b129cc80a5cb43543ac4b7f89563b64b45e",
159162
"path": "labs/12-product-engineering-loop",
160163
"repository": "operatorstack/intelligence-flow"
161164
}

boatstack/decision.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package boatstack
2+
3+
type DecisionOperator string
4+
5+
const (
6+
OperatorInfer DecisionOperator = "infer"
7+
OperatorQuery DecisionOperator = "query"
8+
OperatorVerify DecisionOperator = "verify"
9+
OperatorReject DecisionOperator = "reject"
10+
OperatorEscalate DecisionOperator = "escalate"
11+
)
12+
13+
type EvidenceLevel string
14+
15+
const (
16+
EvidenceVerified EvidenceLevel = "verified"
17+
EvidenceSupported EvidenceLevel = "supported"
18+
EvidenceAbsent EvidenceLevel = "absent"
19+
EvidenceConflicting EvidenceLevel = "conflicting"
20+
)
21+
22+
type PremiseStatus string
23+
24+
const (
25+
PremiseUnknown PremiseStatus = "unknown"
26+
PremiseValid PremiseStatus = "valid"
27+
PremiseInvalid PremiseStatus = "invalid"
28+
)
29+
30+
type PlanDecisionInput struct {
31+
DecisionKind string
32+
IsMaterial bool
33+
RepositoryEvidence []EvidenceRecord
34+
EvidenceLevel EvidenceLevel
35+
PremiseStatus PremiseStatus
36+
}
37+
38+
type DecisionResolution struct {
39+
Operator DecisionOperator
40+
RuleID string
41+
Reason string
42+
Evidence []EvidenceRecord
43+
EvidenceLevel EvidenceLevel
44+
PremiseStatus PremiseStatus
45+
}
46+
47+
func ResolvePlanDecision(input PlanDecisionInput) DecisionResolution {
48+
resolution := DecisionResolution{
49+
Evidence: input.RepositoryEvidence,
50+
EvidenceLevel: input.EvidenceLevel,
51+
PremiseStatus: input.PremiseStatus,
52+
}
53+
54+
if input.PremiseStatus == PremiseInvalid {
55+
resolution.Operator = OperatorReject
56+
resolution.RuleID = "invalid-premise-rejected"
57+
resolution.Reason = "planning premise is not supported"
58+
return resolution
59+
}
60+
61+
if input.EvidenceLevel == EvidenceConflicting {
62+
resolution.Operator = OperatorEscalate
63+
resolution.RuleID = "conflicting-evidence-escalated"
64+
resolution.Reason = "repository evidence conflicts"
65+
return resolution
66+
}
67+
68+
if input.EvidenceLevel == EvidenceVerified {
69+
// Assuming verified evidence is sufficient to resolve the decision
70+
resolution.Operator = OperatorInfer
71+
resolution.RuleID = "verified-evidence-inferred"
72+
resolution.Reason = "verified repository evidence resolves the decision"
73+
return resolution
74+
}
75+
76+
if input.EvidenceLevel == EvidenceSupported {
77+
resolution.Operator = OperatorVerify
78+
resolution.RuleID = "supported-evidence-requires-verification"
79+
resolution.Reason = "evidence is supported but requires independent verification"
80+
return resolution
81+
}
82+
83+
if input.IsMaterial && input.EvidenceLevel == EvidenceAbsent {
84+
resolution.Operator = OperatorQuery
85+
resolution.RuleID = "material-intent-requires-human"
86+
resolution.Reason = "material product intent requires human input"
87+
return resolution
88+
}
89+
90+
resolution.Operator = OperatorEscalate
91+
resolution.RuleID = "unresolved-uncertainty-escalated"
92+
resolution.Reason = "unresolved uncertainty requires escalation"
93+
return resolution
94+
}

boatstack/decision_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package boatstack
2+
3+
import "testing"
4+
5+
func TestResolvePlanDecision(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
input PlanDecisionInput
9+
expected DecisionOperator
10+
}{
11+
{
12+
name: "invalid premise rejects",
13+
input: PlanDecisionInput{
14+
PremiseStatus: PremiseInvalid,
15+
},
16+
expected: OperatorReject,
17+
},
18+
{
19+
name: "conflicting evidence escalates",
20+
input: PlanDecisionInput{
21+
PremiseStatus: PremiseValid,
22+
EvidenceLevel: EvidenceConflicting,
23+
},
24+
expected: OperatorEscalate,
25+
},
26+
{
27+
name: "verified evidence infers",
28+
input: PlanDecisionInput{
29+
PremiseStatus: PremiseValid,
30+
EvidenceLevel: EvidenceVerified,
31+
},
32+
expected: OperatorInfer,
33+
},
34+
{
35+
name: "supported evidence verifies",
36+
input: PlanDecisionInput{
37+
PremiseStatus: PremiseValid,
38+
EvidenceLevel: EvidenceSupported,
39+
},
40+
expected: OperatorVerify,
41+
},
42+
{
43+
name: "absent evidence for material intent queries",
44+
input: PlanDecisionInput{
45+
PremiseStatus: PremiseValid,
46+
IsMaterial: true,
47+
EvidenceLevel: EvidenceAbsent,
48+
},
49+
expected: OperatorQuery,
50+
},
51+
{
52+
name: "unknown state escalates",
53+
input: PlanDecisionInput{
54+
PremiseStatus: PremiseUnknown,
55+
EvidenceLevel: EvidenceAbsent,
56+
IsMaterial: false,
57+
},
58+
expected: OperatorEscalate,
59+
},
60+
}
61+
62+
for _, tt := range tests {
63+
t.Run(tt.name, func(t *testing.T) {
64+
resolution := ResolvePlanDecision(tt.input)
65+
if resolution.Operator != tt.expected {
66+
t.Errorf("expected operator %s, got %s", tt.expected, resolution.Operator)
67+
}
68+
})
69+
}
70+
}

0 commit comments

Comments
 (0)