Skip to content

Commit f3a232e

Browse files
Sync Boatstack from Intelligence Flow Labs @ 3c770b5db125 (#127)
Co-authored-by: operator-stack-publisher[bot] <operator-stack-publisher[bot]@users.noreply.github.com>
1 parent 282516a commit f3a232e

8 files changed

Lines changed: 70 additions & 24 deletions

File tree

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/06cd7f767374488a0ba95f92c9286c856be63649/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/3c770b5db125ad5f28515380c59c4d1718e3a020/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

UPSTREAM.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"files": {
1414
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
15-
"CONTRIBUTING.md": "b032cbd59890e2095138d640b5ca56456c840487951896e5c47457dd53f65acf",
15+
"CONTRIBUTING.md": "57832885d79ec4dc777699fd52028e297bf787041a927299b38cbf3d51bb5a21",
1616
"README.md": "3ce3e95e511089b44e946a44b8d5f4f81d019ece5336db65b2cab1f9dc4d4dad",
1717
"assets/boatstack-journey.svg": "e465befc50c8ce30f3e07e8fd97012931beeb053392c8fbf38ad645023b3cc63",
1818
"assets/boatstack-mark.svg": "be1f984da1bfa69fa5d1f986d8343d21f7e20921b71db888c928b4d2e54b09b5",
@@ -130,8 +130,8 @@
130130
"boatstack/plan_test.go": "53477515165a910910b9175bfa33574548cf0d0f3be48e175ec3a775a12d30bb",
131131
"boatstack/plan_validation.go": "99e40806fd579ff72de53f391cd6124acc9ff18707ecf9676c5e507b738d87d0",
132132
"boatstack/plan_validation_test.go": "6cbde4ac719baef6b73aa569515d6a9daadcbf14b33f76fa78159826954e20fa",
133-
"boatstack/planning.go": "d33b661f448d5c009454f012f16e3dd3daa6756d26b855c93d3066b1aaf923c8",
134-
"boatstack/planning_test.go": "c105a9c78c342be06614bf54d0bc1b661b0f7af64d63b79e43bd1fcc2769edd5",
133+
"boatstack/planning.go": "7e5def2fa4edff78f9164a9f117cff65dd8280b3173cdf01d4429b21a3407bb0",
134+
"boatstack/planning_test.go": "06ec7022222d926040c3ae28b84ab50c3d2f804ae6473e61b303804dd992d884",
135135
"boatstack/pr.go": "b6df3e000dd6d34ecb6575385e44b2f6ee84a8f35ad5696e299177a7cddd7629",
136136
"boatstack/pr_test.go": "2e7709e2f163489a29ea3e7eb4bc932cfe6829b30d168f1aea9e942acbc3b4e7",
137137
"boatstack/provenance.go": "d44dcd5421306269326f1202ba1d52df8c252490550270ef9d022e8ec2b65210",
@@ -187,10 +187,10 @@
187187
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
188188
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
189189
"docs/configuration.md": "060775c73431f28bd16066bdf9e0f89034d2855c7ca0f5544f660d24b91211d0",
190-
"docs/evidence-engineered-coding.md": "273f96676c8f11d00a3eb172d05c6fe551ea5bda343fa46d14c70c6f729910b6",
190+
"docs/evidence-engineered-coding.md": "0c0e344f5eae535c5b406ed1bff51c807fd31aa7768668491888d3f9f84df293",
191191
"docs/generated-files.md": "437791765b0a4015032ae21d1a6618563cad92b7402819e4f963bf5ae16284a3",
192192
"docs/getting-started.md": "51c2823f21e35140d31e6d5083dc4b89fddd24721ac6acc474154a4da53ee9f8",
193-
"docs/public-claims.json": "4f11f552a9c337fd40c4460a37878fc4f2f3d74cefae75149ebb784d3dfe4685",
193+
"docs/public-claims.json": "1cf62f1ffa0d5fadd49c7c4843143a09ffa38a1d78309de590378542a5a8ea78",
194194
"docs/public-surface.md": "713f7a050b5f339cf948299103ef3800417dccfecf2cc1a4166397ea6f978907",
195195
"docs/research-and-design.md": "8d78678108f0a6c924e1ff9b32c0f81aae9d1f779e0082843b6f99ad993ae2b6",
196196
"docs/safety.md": "7b9b5c515d36e683767ec8d3d9d6d119ac93650b2f629d351deadd4c600ed6a6",
@@ -204,7 +204,7 @@
204204
"labs/diagram-json/compiled/evidence.md": "1ba1c989ade070a8ef9a508fbd788d100d7292f2dbacbb2bce895468019f619d",
205205
"labs/diagram-json/compiled/tasks.json": "88f60851abf79d851e9fccc754ff3040034ae595306bc87d64784c19eb403e71",
206206
"labs/diagram-json/compiled/test-matrix.json": "424657ff505768e50fa113801fd8363364a18269d5297480907a993d44063a39",
207-
"labs/diagram-json/plan.lock.json": "fd56e5b7f054ecb78051703e42577820999f3527ab9242b0b63632173bf205c3",
207+
"labs/diagram-json/plan.lock.json": "dc95b0ece06634bae69a6f010a0d1fb49c6b2c43659031a29b78c891466deade",
208208
"labs/diagram-json/plan.md": "3cc4f533b8d69386deff16b3a594a3ba09d4c0c3db636cccd8c4380084ce6a51",
209209
"labs/diagram-json/questions.md": "74733b015002c8a6777c558e7e997fa48c94850b9bd39054fe9366c97ecf728d",
210210
"labs/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
@@ -319,13 +319,14 @@
319319
"release-notes/2026-07-26-hidden-jflow-design-note.md": "f60ed9dbbfb46a172ac9d33dd758a3166f820007b1673029f29f0fbefa0e5c0a",
320320
"release-notes/2026-07-26-workspace-reap.md": "e691d6a1c232cf218157880655413005fcb2c4f3113ededffdb80899a5054bb8",
321321
"release-notes/2026-07-27-coreachable-recovery.md": "6ffc6b0e9a7d46c0f99a64112813c33d19571c73d02e98ac5573924f1663fd54",
322+
"release-notes/2026-07-27-discoverable-planning-errors.md": "d8099d1a6cd1805c3fcd446d9fa95739dec93e57ff421ecf4f99562b143c9966",
322323
"release-notes/2026-07-27-invalid-delivery-block-actionable.md": "8fac8e3921e2285291703efa46e624b72cb5bac1b8492beca4c4b633abb5ba16",
323324
"release-notes/2026-07-27-read-only-inspection-pipelines.md": "0963286371e9a12592915c23a958dd013bf2a35e9fca6921691bc8bb3c3d8dc8"
324325
},
325326
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
326327
"schema_version": 1,
327328
"source": {
328-
"commit": "06cd7f767374488a0ba95f92c9286c856be63649",
329+
"commit": "3c770b5db125ad5f28515380c59c4d1718e3a020",
329330
"path": "labs/12-product-engineering-loop",
330331
"repository": "operatorstack/intelligence-flow"
331332
}

boatstack/planning.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ var planningArtifacts = map[string]bool{
2424
"plan.md": true,
2525
}
2626

27+
// planningArtifactNames returns the accepted artifact tokens, sorted, for error
28+
// messages. Discoverability: a rejection that gates on a closed domain must name
29+
// the accepted set at the point of failure. The tokens are filenames carrying a
30+
// .md suffix, so the natural guess ("plan") is always wrong — listing them (and the
31+
// suffix) is what turns a dead-end rejection into an actionable one.
32+
func planningArtifactNames() []string {
33+
names := make([]string, 0, len(planningArtifacts))
34+
for name := range planningArtifacts {
35+
names = append(names, name)
36+
}
37+
sort.Strings(names)
38+
return names
39+
}
40+
2741
type PlanningWriteOptions struct {
2842
Repo string
2943
Feature string
@@ -212,7 +226,7 @@ func WritePlanningArtifact(options PlanningWriteOptions) (string, error) {
212226
return "", fmt.Errorf("feature must be a lowercase kebab-case slug")
213227
}
214228
if !planningArtifacts[options.Artifact] {
215-
return "", fmt.Errorf("unsupported planning artifact: %s", options.Artifact)
229+
return "", fmt.Errorf("unsupported planning artifact %q; use one of: %s (note the .md suffix)", options.Artifact, strings.Join(planningArtifactNames(), ", "))
216230
}
217231
if !utf8.Valid(options.Content) {
218232
return "", fmt.Errorf("planning artifact must be valid UTF-8 Markdown")
@@ -251,7 +265,7 @@ func RecordApproval(options ApprovalRecordOptions) error {
251265
return err
252266
}
253267
if options.Fingerprint != check.Fingerprint {
254-
return fmt.Errorf("approval fingerprint does not match the current plan")
268+
return fmt.Errorf("approval fingerprint does not match the current plan; the plan now fingerprints as %s — re-approve against that value (run check-plan to confirm)", check.Fingerprint)
255269
}
256270
repo, err := ResolveRepository(filepath.Dir(options.PlanPath))
257271
if err != nil {

boatstack/planning_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@ func TestPlanningWriteIsBoundedMarkdownOnly(t *testing.T) {
5050
}
5151
}
5252

53+
// Discoverability: the natural guess for an artifact token is "plan" — but the
54+
// tokens carry a .md suffix, so it is always wrong. The rejection must name the
55+
// accepted set and the transform at the point of failure, so the caller is not
56+
// forced to discover them out of band (the failure that burned a planning session).
57+
func TestPlanningWriteUnsupportedArtifactErrorIsDiscoverable(t *testing.T) {
58+
repo := planningRepo(t)
59+
_, err := WritePlanningArtifact(PlanningWriteOptions{
60+
Repo: repo, Feature: "account-recovery", Artifact: "plan", Content: []byte("# Plan\n"),
61+
})
62+
if err == nil {
63+
t.Fatal("expected the bare token to be rejected")
64+
}
65+
for _, want := range []string{"plan.md", "source-plan.md", "test-plan.md", ".md suffix"} {
66+
if !strings.Contains(err.Error(), want) {
67+
t.Fatalf("unsupported-artifact error omitted %q: %v", want, err)
68+
}
69+
}
70+
}
71+
5372
func TestPlanningWriteRejectsSymlinksAndPreservesExistingContentOnFailure(t *testing.T) {
5473
if runtime.GOOS == "windows" {
5574
t.Skip("symlink creation needs elevated Windows permissions")

docs/evidence-engineered-coding.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,6 @@ Delivery and system improvement also remain separate. A failed task may suggest
146146

147147
## What is evidence-backed
148148

149-
The current moves were derived from the Intelligence Flow benchmark corpus and product-repository studies. The generated source commit is [`06cd7f767374488a0ba95f92c9286c856be63649`](https://github.com/operatorstack/intelligence-flow/tree/06cd7f767374488a0ba95f92c9286c856be63649/labs/12-product-engineering-loop).
149+
The current moves were derived from the Intelligence Flow benchmark corpus and product-repository studies. The generated source commit is [`3c770b5db125ad5f28515380c59c4d1718e3a020`](https://github.com/operatorstack/intelligence-flow/tree/3c770b5db125ad5f28515380c59c4d1718e3a020/labs/12-product-engineering-loop).
150150

151151
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.

docs/public-claims.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schema_version": 1,
3-
"source_commit": "06cd7f767374488a0ba95f92c9286c856be63649",
3+
"source_commit": "3c770b5db125ad5f28515380c59c4d1718e3a020",
44
"statuses": ["verified", "observed", "still_being_evaluated"],
55
"claims": [
66
{
@@ -12,7 +12,7 @@
1212
"readable_evidence": "why-these-steps.md#portable-workflow-and-state",
1313
"implementation": ["../boatstack/export.go", "../boatstack/references/artifacts.md", "../boatstack/references/workflow.md"],
1414
"verification": ["../boatstack/export_test.go"],
15-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
15+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
1616
},
1717
{
1818
"id": "human-decisions",
@@ -23,7 +23,7 @@
2323
"readable_evidence": "why-these-steps.md#human-decisions",
2424
"implementation": ["../boatstack/references/workflow.md", "../boatstack/plan.go"],
2525
"verification": ["../boatstack/plan_test.go", "../boatstack/planning_test.go"],
26-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
26+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
2727
},
2828
{
2929
"id": "validation-provenance",
@@ -34,7 +34,7 @@
3434
"readable_evidence": "why-these-steps.md#validation-provenance",
3535
"implementation": ["validation-and-evidence.md", "../boatstack/plan.go"],
3636
"verification": ["../boatstack/plan_test.go"],
37-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
37+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
3838
},
3939
{
4040
"id": "irreversible-operations",
@@ -46,7 +46,7 @@
4646
"readable_evidence": "why-these-steps.md#irreversible-operations",
4747
"implementation": ["safety.md", "../boatstack/safety.go", "../boatstack/hooks.go"],
4848
"verification": ["../boatstack/safety_test.go", "../boatstack/hooks_test.go"],
49-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
49+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
5050
},
5151
{
5252
"id": "reviewer-ready-pr",
@@ -57,7 +57,7 @@
5757
"readable_evidence": "why-these-steps.md#reviewer-ready-pr",
5858
"implementation": ["../boatstack/pr.go", "getting-started.md"],
5959
"verification": ["../boatstack/pr_test.go"],
60-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
60+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
6161
},
6262
{
6363
"id": "phase-scoped-delivery",
@@ -68,7 +68,7 @@
6868
"readable_evidence": "why-these-steps.md#phase-scoped-delivery",
6969
"implementation": ["../boatstack/delivery.go", "../boatstack/safety.go", "../boatstack/hooks.go", "../boatstack/references/workflow.md"],
7070
"verification": ["../boatstack/delivery_test.go", "../boatstack/pr_test.go"],
71-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
71+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
7272
},
7373
{
7474
"id": "model-neutral-contract",
@@ -79,7 +79,7 @@
7979
"readable_evidence": "why-these-steps.md#model-choice-and-budget",
8080
"implementation": ["research-and-design.md", "../boatstack/references/workflow.md"],
8181
"verification": ["../boatstack/export_test.go", "../boatstack/planning_test.go"],
82-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
82+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
8383
},
8484
{
8585
"id": "cross-model-failures",
@@ -90,7 +90,7 @@
9090
"readable_evidence": "why-these-steps.md#model-choice-and-budget",
9191
"implementation": ["research-and-design.md"],
9292
"verification": ["benchmark-corpus-audit.md", "benchmark-submission-audit.md"],
93-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
93+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
9494
},
9595
{
9696
"id": "lower-cost-outcomes",
@@ -101,7 +101,7 @@
101101
"readable_evidence": "why-these-steps.md#model-choice-and-budget",
102102
"implementation": ["research-and-design.md"],
103103
"verification": ["benchmark-corpus-audit.md", "benchmark-submission-audit.md"],
104-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
104+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
105105
},
106106
{
107107
"id": "git-worktree-activation",
@@ -112,7 +112,7 @@
112112
"readable_evidence": "why-these-steps.md#git-worktree-activation",
113113
"implementation": ["../boatstack/runtime_cache.go", "../boatstack/hooks.go"],
114114
"verification": ["../boatstack/runtime_cache_test.go", "../boatstack/hooks_test.go"],
115-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
115+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
116116
},
117117
{
118118
"id": "visible-updates",
@@ -123,7 +123,7 @@
123123
"readable_evidence": "why-these-steps.md#visible-updates",
124124
"implementation": ["../boatstack/update.go", "../boatstack/init.go"],
125125
"verification": ["../boatstack/update_test.go", "../boatstack/init_test.go", "../boatstack/export_test.go"],
126-
"last_verified_version": "source:06cd7f767374488a0ba95f92c9286c856be63649"
126+
"last_verified_version": "source:3c770b5db125ad5f28515380c59c4d1718e3a020"
127127
}
128128
]
129129
}

labs/diagram-json/plan.lock.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"plan_path": "labs/diagram-json/plan.md",
77
"plan_sha256": "3cc4f533b8d69386deff16b3a594a3ba09d4c0c3db636cccd8c4380084ce6a51",
88
"schema_version": 1,
9-
"source_commit": "06cd7f767374488a0ba95f92c9286c856be63649",
9+
"source_commit": "3c770b5db125ad5f28515380c59c4d1718e3a020",
1010
"source_plan_path": "labs/diagram-json/source-plan.md",
1111
"source_plan_sha256": "e10593ddaa7522ab80cc991d0a09399257139799e37f737794cd49d68a39985b",
1212
"spec_path": "labs/diagram-json/spec.md",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
### Rejections name the values you can use
2+
3+
Two errors told you what was wrong but not how to fix it, so you had to discover the answer out of
4+
band. When the bounded planning writer rejected an artifact name, it echoed the name you gave but not
5+
the names it accepts. The accepted names are filenames that end in `.md`, so the natural guess, such as
6+
`plan`, is always wrong. When an approval no longer matched the plan, the error said the fingerprint did
7+
not match but did not say what the current fingerprint is.
8+
9+
Both now carry the answer. The planning writer lists the accepted artifact names and notes the `.md`
10+
suffix, so `plan.md`, `source-plan.md`, and the rest are visible at the point of rejection. The approval
11+
error reports the plan's current fingerprint and points at check-plan to confirm it, so you can
12+
re-approve against the right value without a separate lookup.

0 commit comments

Comments
 (0)