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/f740356bfc30b59038162ed3c7ca849f77c76e7f/labs/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/e2ba11f185aa370ec4302ffcd1f4f7e622f60105/labs/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
17 changes: 9 additions & 8 deletions UPSTREAM.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"files": {
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
"CONTRIBUTING.md": "9d31155e08bf2ec29b66a839c0a320e1e30f2c1f69448b89622b74ade3b0c5ed",
"CONTRIBUTING.md": "fe36d1fcccd0042e51ae8c590f21ec49d9fdb9a367ddfd31803a6fc1db1f0f24",
"README.md": "3ce3e95e511089b44e946a44b8d5f4f81d019ece5336db65b2cab1f9dc4d4dad",
"assets/boatstack-journey.svg": "e465befc50c8ce30f3e07e8fd97012931beeb053392c8fbf38ad645023b3cc63",
"assets/boatstack-mark.svg": "be1f984da1bfa69fa5d1f986d8343d21f7e20921b71db888c928b4d2e54b09b5",
Expand Down Expand Up @@ -54,7 +54,7 @@
"boatstack/decision.go": "257ca328da6ae19ab252f10ee5d06bd7daf49dd8141d083ab1b32f106ea7a94c",
"boatstack/decision_test.go": "1a92ff832610f9559bd47ccac7fc1755a8b4f8261c35bc72a092830dff05f7c0",
"boatstack/delivery.go": "1cbc917eaa7df569f09c71352db157dff743827d5310dccb63acb7be72ccf9d5",
"boatstack/delivery_boundary_conformance_test.go": "c374eddf49b4597db78c0621f65f87199de9a26f1872ed88d9d790edf21fe3f2",
"boatstack/delivery_boundary_conformance_test.go": "53dde765046420b9119e82034d137742e600019938ed908c608f725d8a0c84c6",
"boatstack/delivery_migrate.go": "7566e49f9c1838d4d563866e941c7aacd61ac918c9e886222282398d287ca780",
"boatstack/delivery_migrate_conformance_test.go": "b8ba53681e1d0361ac62b06586c62b7763d55a65b5427976b5289e1fb1503bdc",
"boatstack/delivery_reactivation_test.go": "573a2dba0034bc4290478414e3bdd8670b06a326128eb0295d77e748ecc8689e",
Expand Down Expand Up @@ -160,7 +160,7 @@
"boatstack/runtime_cache.go": "e026ffc1906f7e1e98b768bae63e6658164d2826c07169c9121ce0f23c73faf8",
"boatstack/runtime_cache_test.go": "b981467ddc9f0f562da6bff5de7a80a9fe5a433a0317541d1e48df268546ac85",
"boatstack/runtime_provenance_test.go": "1d52f1e6b0691cf4667729cc9b9f3c55c128f0aa3321f3a2843a9aa6fd0e73dc",
"boatstack/safety.go": "56055f93cd9fe0f308b244111f2282d191c3ed522731047a194b06f21df64247",
"boatstack/safety.go": "b68ea12b2ee4c1f1782c1a6a8540fff908ef8ef6d80f0b391c2933a5f2fecb38",
"boatstack/safety_test.go": "02260654d0b93ad48585c40391b310810876a6abcafc3d6c074f1f4e4e633f76",
"boatstack/safety_update_publisher_test.go": "ed3f8187036623694dfe7c395cdae00fdae14609bab6124d1fdfc6fe73fa2196",
"boatstack/skill_frontmatter.go": "73364df463ce828c2d005aab55f72bb92f7a34d99cf3f53d4e0cd5a4da9dbd0e",
Expand All @@ -187,10 +187,10 @@
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
"docs/configuration.md": "060775c73431f28bd16066bdf9e0f89034d2855c7ca0f5544f660d24b91211d0",
"docs/evidence-engineered-coding.md": "c3301e5ef81642029935970eb4270c3667eeeacba3d7994d98407f65409dcac4",
"docs/evidence-engineered-coding.md": "525a3fd0cc83ad45ce494a10a94432c534283bbd0be424d320f4351cb78faad5",
"docs/generated-files.md": "437791765b0a4015032ae21d1a6618563cad92b7402819e4f963bf5ae16284a3",
"docs/getting-started.md": "51c2823f21e35140d31e6d5083dc4b89fddd24721ac6acc474154a4da53ee9f8",
"docs/public-claims.json": "6c631d91ce3579a4a4fcf09a0d5c902a102de62b9793136e18e94032f67f73aa",
"docs/public-claims.json": "d1e8ae99275098ed44ac52322fc0fece3c8091a2a43e7bdf10de78a00a3649ba",
"docs/public-surface.md": "713f7a050b5f339cf948299103ef3800417dccfecf2cc1a4166397ea6f978907",
"docs/research-and-design.md": "8d78678108f0a6c924e1ff9b32c0f81aae9d1f779e0082843b6f99ad993ae2b6",
"docs/safety.md": "7b9b5c515d36e683767ec8d3d9d6d119ac93650b2f629d351deadd4c600ed6a6",
Expand All @@ -204,7 +204,7 @@
"labs/diagram-json/compiled/evidence.md": "1ba1c989ade070a8ef9a508fbd788d100d7292f2dbacbb2bce895468019f619d",
"labs/diagram-json/compiled/tasks.json": "88f60851abf79d851e9fccc754ff3040034ae595306bc87d64784c19eb403e71",
"labs/diagram-json/compiled/test-matrix.json": "424657ff505768e50fa113801fd8363364a18269d5297480907a993d44063a39",
"labs/diagram-json/plan.lock.json": "e059bbc4a5ab29c1dc16a3ae00a1486b57a245e767e2ebaef4cd572002e959a7",
"labs/diagram-json/plan.lock.json": "b404cd373f8b5c33cd6c3de992e2db9e94d34367a2e7681d08de5a1561263faa",
"labs/diagram-json/plan.md": "3cc4f533b8d69386deff16b3a594a3ba09d4c0c3db636cccd8c4380084ce6a51",
"labs/diagram-json/questions.md": "74733b015002c8a6777c558e7e997fa48c94850b9bd39054fe9366c97ecf728d",
"labs/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
Expand Down Expand Up @@ -318,12 +318,13 @@
"release-notes/2026-07-26-guard-hydrate-double-check.md": "83a5591aba6bf30c9f4008ba8d26bf1994ef3fd61145f46fcdd1678912b9990b",
"release-notes/2026-07-26-hidden-jflow-design-note.md": "f60ed9dbbfb46a172ac9d33dd758a3166f820007b1673029f29f0fbefa0e5c0a",
"release-notes/2026-07-26-workspace-reap.md": "e691d6a1c232cf218157880655413005fcb2c4f3113ededffdb80899a5054bb8",
"release-notes/2026-07-27-coreachable-recovery.md": "6ffc6b0e9a7d46c0f99a64112813c33d19571c73d02e98ac5573924f1663fd54"
"release-notes/2026-07-27-coreachable-recovery.md": "6ffc6b0e9a7d46c0f99a64112813c33d19571c73d02e98ac5573924f1663fd54",
"release-notes/2026-07-27-invalid-delivery-block-actionable.md": "8fac8e3921e2285291703efa46e624b72cb5bac1b8492beca4c4b633abb5ba16"
},
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
"schema_version": 1,
"source": {
"commit": "f740356bfc30b59038162ed3c7ca849f77c76e7f",
"commit": "e2ba11f185aa370ec4302ffcd1f4f7e622f60105",
"path": "labs/12-product-engineering-loop",
"repository": "operatorstack/intelligence-flow"
}
Expand Down
31 changes: 31 additions & 0 deletions boatstack/delivery_boundary_conformance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,37 @@ func TestActiveManagedDeliveriesStaysFailClosedOnInvalid(t *testing.T) {
}
}

// Same-Relation-Same-Law + Coreachability at the MUTATION boundary: invalid
// delivery state fails closed even when ignored (no laundering corrupt state), but
// the block is actionable — it prescribes discard-delivery (a reachable verb that
// clears it), not the opaque error or a verb that refuses. Ignoring quiets status;
// discarding unblocks mutation. This is the mutation-path twin of the read-only
// ResolveNext discard-remedy conformance above.
func TestPreActivationBlockOnInvalidDeliveryPrescribesDiscard(t *testing.T) {
repo := nextTestRepo(t)
writeInvalidDelivery(t, repo, "stale-one")
if _, err := IgnoreDelivery(repo, "stale-one"); err != nil {
t.Fatal(err)
}
finding, blocked := preActivationFinding(repo, "product.go")
if !blocked {
t.Fatal("invalid delivery state did not block mutation")
}
if finding.NextOperation != "discard-delivery" {
t.Fatalf("block prescribed %q, want the reachable discard-delivery", finding.NextOperation)
}
if !controlledPhaseTransition("boatstack-helper discard-delivery --repo . --feature stale-one", finding.WorkflowStage) {
t.Fatal("prescribed discard-delivery is not admitted for the block it was prescribed for")
}
// The prescribed verb clears the state, and mutation is then unblocked.
if _, err := DiscardDelivery(repo, "stale-one", true); err != nil {
t.Fatalf("discard-delivery refused the invalid delivery it was prescribed for: %v", err)
}
if _, stillBlocked := preActivationFinding(repo, "product.go"); stillBlocked {
t.Fatal("mutation still blocked after discarding the invalid delivery")
}
}

// Failure-state conformance: ResolveNext is read-only. A blocking decision must
// leave the offending state file byte-for-byte unchanged (no partial repair).
func TestResolveNextLeavesInvalidStateUntouched(t *testing.T) {
Expand Down
14 changes: 14 additions & 0 deletions boatstack/safety.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,20 @@ func planningMarkdownPath(path string) bool {
func preActivationFinding(repo, attemptedPath string) (SafetyFinding, bool) {
active, err := ActiveManagedDeliveries(repo)
if err != nil {
// Same-Relation-Same-Law: the mutation boundary FAILS CLOSED on invalid
// delivery state — ignoring a delivery quiets status but never launders corrupt
// state into a mutation (TestActiveManagedDeliveriesStaysFailClosedOnInvalid).
// But the block must be Coreachable: distinguish a corrupt-delivery *plant*
// fault (a verb clears it — discard-delivery, named) from an *observation*
// (channel) fault (doctor to diagnose). Naming discard-delivery is what tells
// the operator how to actually unblock mutation, since ignoring will not.
if _, invalid, scanErr := scanManagedDeliveries(repo); scanErr == nil && len(invalid) > 0 {
return SafetyFinding{
Category: "workflow-state-invalid", Source: "delivery-state",
Reason: "invalid managed delivery state blocks all mutation; ignoring it only quiets status — clear it with discard-delivery to continue",
NextOperation: "discard-delivery", BlockingFeature: invalid[0], AttemptedPath: attemptedPath,
}, true
}
return SafetyFinding{Category: "workflow-observation-fault", Reason: "managed delivery state cannot be verified; diagnose the channel with doctor", Source: "delivery-state", NextOperation: "doctor"}, true
}
if len(active) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion docs/evidence-engineered-coding.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,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 [`f740356bfc30b59038162ed3c7ca849f77c76e7f`](https://github.com/operatorstack/intelligence-flow/tree/f740356bfc30b59038162ed3c7ca849f77c76e7f/labs/12-product-engineering-loop).
The current moves were derived from the Intelligence Flow benchmark corpus and product-repository studies. The generated source commit is [`e2ba11f185aa370ec4302ffcd1f4f7e622f60105`](https://github.com/operatorstack/intelligence-flow/tree/e2ba11f185aa370ec4302ffcd1f4f7e622f60105/labs/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.
24 changes: 12 additions & 12 deletions docs/public-claims.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema_version": 1,
"source_commit": "f740356bfc30b59038162ed3c7ca849f77c76e7f",
"source_commit": "e2ba11f185aa370ec4302ffcd1f4f7e622f60105",
"statuses": ["verified", "observed", "still_being_evaluated"],
"claims": [
{
Expand All @@ -12,7 +12,7 @@
"readable_evidence": "why-these-steps.md#portable-workflow-and-state",
"implementation": ["../boatstack/export.go", "../boatstack/references/artifacts.md", "../boatstack/references/workflow.md"],
"verification": ["../boatstack/export_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "human-decisions",
Expand All @@ -23,7 +23,7 @@
"readable_evidence": "why-these-steps.md#human-decisions",
"implementation": ["../boatstack/references/workflow.md", "../boatstack/plan.go"],
"verification": ["../boatstack/plan_test.go", "../boatstack/planning_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "validation-provenance",
Expand All @@ -34,7 +34,7 @@
"readable_evidence": "why-these-steps.md#validation-provenance",
"implementation": ["validation-and-evidence.md", "../boatstack/plan.go"],
"verification": ["../boatstack/plan_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "irreversible-operations",
Expand All @@ -46,7 +46,7 @@
"readable_evidence": "why-these-steps.md#irreversible-operations",
"implementation": ["safety.md", "../boatstack/safety.go", "../boatstack/hooks.go"],
"verification": ["../boatstack/safety_test.go", "../boatstack/hooks_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "reviewer-ready-pr",
Expand All @@ -57,7 +57,7 @@
"readable_evidence": "why-these-steps.md#reviewer-ready-pr",
"implementation": ["../boatstack/pr.go", "getting-started.md"],
"verification": ["../boatstack/pr_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "phase-scoped-delivery",
Expand All @@ -68,7 +68,7 @@
"readable_evidence": "why-these-steps.md#phase-scoped-delivery",
"implementation": ["../boatstack/delivery.go", "../boatstack/safety.go", "../boatstack/hooks.go", "../boatstack/references/workflow.md"],
"verification": ["../boatstack/delivery_test.go", "../boatstack/pr_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "model-neutral-contract",
Expand All @@ -79,7 +79,7 @@
"readable_evidence": "why-these-steps.md#model-choice-and-budget",
"implementation": ["research-and-design.md", "../boatstack/references/workflow.md"],
"verification": ["../boatstack/export_test.go", "../boatstack/planning_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "cross-model-failures",
Expand All @@ -90,7 +90,7 @@
"readable_evidence": "why-these-steps.md#model-choice-and-budget",
"implementation": ["research-and-design.md"],
"verification": ["benchmark-corpus-audit.md", "benchmark-submission-audit.md"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "lower-cost-outcomes",
Expand All @@ -101,7 +101,7 @@
"readable_evidence": "why-these-steps.md#model-choice-and-budget",
"implementation": ["research-and-design.md"],
"verification": ["benchmark-corpus-audit.md", "benchmark-submission-audit.md"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "git-worktree-activation",
Expand All @@ -112,7 +112,7 @@
"readable_evidence": "why-these-steps.md#git-worktree-activation",
"implementation": ["../boatstack/runtime_cache.go", "../boatstack/hooks.go"],
"verification": ["../boatstack/runtime_cache_test.go", "../boatstack/hooks_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
},
{
"id": "visible-updates",
Expand All @@ -123,7 +123,7 @@
"readable_evidence": "why-these-steps.md#visible-updates",
"implementation": ["../boatstack/update.go", "../boatstack/init.go"],
"verification": ["../boatstack/update_test.go", "../boatstack/init_test.go", "../boatstack/export_test.go"],
"last_verified_version": "source:f740356bfc30b59038162ed3c7ca849f77c76e7f"
"last_verified_version": "source:e2ba11f185aa370ec4302ffcd1f4f7e622f60105"
}
]
}
2 changes: 1 addition & 1 deletion labs/diagram-json/plan.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"plan_path": "labs/diagram-json/plan.md",
"plan_sha256": "3cc4f533b8d69386deff16b3a594a3ba09d4c0c3db636cccd8c4380084ce6a51",
"schema_version": 1,
"source_commit": "f740356bfc30b59038162ed3c7ca849f77c76e7f",
"source_commit": "e2ba11f185aa370ec4302ffcd1f4f7e622f60105",
"source_plan_path": "labs/diagram-json/source-plan.md",
"source_plan_sha256": "e10593ddaa7522ab80cc991d0a09399257139799e37f737794cd49d68a39985b",
"spec_path": "labs/diagram-json/spec.md",
Expand Down
16 changes: 16 additions & 0 deletions release-notes/2026-07-27-invalid-delivery-block-actionable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### A mutation blocked by invalid delivery state now names the step that clears it

Invalid managed delivery state blocks all product mutation. This is deliberate: adding a delivery to
the ignore list quiets the status report, but it does not let corrupt state pass the mutation guard,
so bad state can never be laundered into a change. That protection stays.

What was missing was a way forward. The block reported an opaque verification error and did not say how
to unblock work, and the operator's ignore action did not help on this path. The step to run was not
named.

The block is now actionable. When invalid delivery state stops a mutation, the guard names
`discard-delivery` — the reachable step that archives the corrupt state reversibly and lets work
continue. It also separates a corrupt-state fault, which a step can clear, from a sensing fault such as
an unreadable store or a broken configuration, which is diagnosed by the read-only `doctor` because no
mutation step can repair a channel. The read-only status path keeps tolerating an ignored delivery; the
mutation path keeps failing closed — the same rule, each boundary in its own role.
Loading