Skip to content

Commit 4b4e7b2

Browse files
Sync Boatstack from Intelligence Flow Labs @ 17376b5e74eb (#43)
Co-authored-by: operator-stack-publisher[bot] <operator-stack-publisher[bot]@users.noreply.github.com> Co-authored-by: bigboateng <bigboateng2011@gmail.com>
1 parent 10fd92f commit 4b4e7b2

12 files changed

Lines changed: 85 additions & 39 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/340059469cf115431f0f91c0a88beb34374d1e5a/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/17376b5e74eb69d341c6df1b69251f2e07d47c4f/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: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"canonical_context": {
3-
"characters": 43677,
4-
"estimated_tokens": 10920,
3+
"characters": 43912,
4+
"estimated_tokens": 10978,
55
"estimator": "ceil(total characters / 4); compactness signal, not provider billing",
66
"files": [
77
"product-engineering-loop/references/workflow.md",
@@ -12,7 +12,7 @@
1212
},
1313
"files": {
1414
".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957",
15-
"CONTRIBUTING.md": "79338a8a60c24719b8618b3ffe5b6112075d4035d9c2aec07a55aa50f09daa4c",
15+
"CONTRIBUTING.md": "f679c93d361def0a2c8903c1b5714d4bf707add3eeeeec88370b8ceef936a8e0",
1616
"README.md": "a840004db57a129ecd361bb0421adfe02065d86751736dd91953c8a8b178e5ef",
1717
"assets/boatstack-journey.svg": "c1f7fe2741f5e9ca66bb3fe9b103e6364ba5acbca8b7a8054768ffd85cf325ea",
1818
"assets/boatstack-mark.svg": "ec96165583b15cfd446c27049d49217973f3e9b1defa5771cc08eec0c9542ce4",
@@ -31,14 +31,14 @@
3131
"boatstack/assets/templates/test-plan.md": "6db8a9f27dd171fb80222a501cae50eb051e7278c04703fa43b5ff86dd4d2df4",
3232
"boatstack/atomic_unix.go": "89f2723361591de2bb8bd22ce7e34ec529d3278509f0df78fd5c4a7d4140fbe9",
3333
"boatstack/atomic_windows.go": "cefd775cbe7e7c3bd8a3f5673b11cdd784c6d3ebd6de7dcb8f39406b0bee511f",
34-
"boatstack/changelog.go": "5f0b1e7a66586c58aad03bfea8126178316f82ff6583bd67d35d6fcf71a6f9bc",
35-
"boatstack/changelog_test.go": "2cee0d580dc2fa0752ee58564d030961b20139008de132ee8abff9e6b6713e28",
34+
"boatstack/changelog.go": "c5e1f31440b44d61e6037ad27af0333540af3545d655e35819a0241cbbebd8ec",
35+
"boatstack/changelog_test.go": "ce792f23a7fe1e09fb3096cd1314130a6ab69321d4877b12a8e994027541baf7",
3636
"boatstack/cmd/boatstack-helper/main.go": "03637dce9ffd5e36355ec8c09bfdf4a9c34769808cdd7d330634e79b5bb9ac77",
3737
"boatstack/cmd/boatstack-helper/main_test.go": "ff73003b6a5157202fa09ddf1129fb13c3d79702b2e05a8721ce5a11bf5ab779",
3838
"boatstack/delivery.go": "565bc8465252a798124a29874e1aeffff16e9027d1a86715e11b3e4bc0743bd2",
3939
"boatstack/delivery_test.go": "2545c26389d330a92c11e7b09fb2342101db5d09a825a2a9e81b4ea9eea9407b",
40-
"boatstack/export.go": "9f4b2b48ea19368232a7d335fc23f632e8a1081736582dab61fd1ba6125850a3",
41-
"boatstack/export_test.go": "9474985bf2aab4f2f14d37dcc3cedc6d7a74db39739fbbfd7615297e35b079b5",
40+
"boatstack/export.go": "786858fbd1a0172371f310937d0f3244cf1f57246e916fdac581e3da8618e67a",
41+
"boatstack/export_test.go": "fbe19b8627c9a66d6e5231aa0e275dccb28f85046a3f2f242a2ca306bb6c2665",
4242
"boatstack/go.mod": "6086ef1b2a83f5696190dca692c653925f27b61f652f659fd3fca43ed54a1641",
4343
"boatstack/go.sum": "26c315c867b11b886f3c9402fce7f341f6a9115a5d61f54afbb5e1b1fb5f6017",
4444
"boatstack/hooks.go": "ed131c526f434d7c3309a388b97f3d28df2a6bdf9bc7322499405d5174ab8518",
@@ -60,7 +60,7 @@
6060
"boatstack/references/host-hook-contracts.md": "1382213ad004389de6da5a03af43ec28ace6329c9e7a3f07148566cf2ea12727",
6161
"boatstack/references/irreversible-operation-boundary.md": "631743991ace65977586e4537f8dd50f8ae88f8e16f27cf7baad93b2791a73df",
6262
"boatstack/references/portability.md": "fb683095991bb0cb06ec56fb8884c49038b283172a7d2f8b203483b7cacb4bae",
63-
"boatstack/references/workflow.md": "b460b647bdd5d0ce4f1bd1015434a9e6c3b8ef525920ed018fb26a22bbc3aa9a",
63+
"boatstack/references/workflow.md": "a342d519f8420f34b9431c4624fc6f823034218eebb520e74d0cf5f4f3d5a382",
6464
"boatstack/release.go": "fa2ac926df89c90c5844e938a2e02d4b8dbbaefbf85bb7a1a89fc51690bea520",
6565
"boatstack/release_test.go": "5cf2d76fe9b836a91ca68eba53d5585e2c4be5b9421aaf939ea0723063a24690",
6666
"boatstack/run.go": "a9afb239c5e2cb80f96dab594f0dc94852f2f16625b1de05c5110ee85f61cfaa",
@@ -80,10 +80,10 @@
8080
"docs/account-recovery-walkthrough.md": "676034974594a7d1a559b24dbed31d7ccc429eb81404b203ca07bbdaa19ec3d3",
8181
"docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6",
8282
"docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79",
83-
"docs/evidence-engineered-coding.md": "3e51926eb4a23d1774b93c59e8cf2b670decabcb746bdd0db1dc2a790fa40f1f",
83+
"docs/evidence-engineered-coding.md": "c418dfc92d3e0a38996162f4b4c120693817c93056be15dfa7828295011457eb",
8484
"docs/generated-files.md": "136422baf0c7fc2bd5100cfe0ebdb3d9d0705dfd7e7d54bf745dd1037e63492c",
85-
"docs/getting-started.md": "d57fa781176321dd25f2917488133f912ec1ef1645a3c43f9630db0485049dd8",
86-
"docs/public-claims.json": "44bb7a014da3f53d627d441d4473262c712fdc80a19d979b8c89f906a4078a6e",
85+
"docs/getting-started.md": "eacc814fdffdfa3c7d8052b7cd99a79c04da5c75d88d8b44f3fb68d9afec0316",
86+
"docs/public-claims.json": "df3d78d6c2a9b20d3a6c20bbea1c3d5eb5d7fbedfad60e34cbb121498e9a7c84",
8787
"docs/public-surface.md": "713f7a050b5f339cf948299103ef3800417dccfecf2cc1a4166397ea6f978907",
8888
"docs/research-and-design.md": "d65c66e323037bda5d45aacef5d48afa6bf93da55901378891d235aca3a5684f",
8989
"docs/safety.md": "7b9b5c515d36e683767ec8d3d9d6d119ac93650b2f629d351deadd4c600ed6a6",
@@ -97,7 +97,7 @@
9797
"labs/diagram-json/compiled/evidence.md": "1ba1c989ade070a8ef9a508fbd788d100d7292f2dbacbb2bce895468019f619d",
9898
"labs/diagram-json/compiled/tasks.json": "88f60851abf79d851e9fccc754ff3040034ae595306bc87d64784c19eb403e71",
9999
"labs/diagram-json/compiled/test-matrix.json": "424657ff505768e50fa113801fd8363364a18269d5297480907a993d44063a39",
100-
"labs/diagram-json/plan.lock.json": "e28185904ad653ccf43858afaf5b17c07f773e22ed21b8d3f88987e753011a99",
100+
"labs/diagram-json/plan.lock.json": "f18205ea54ae03756bd5bb7513a48ac494b9ed6e5bce8015bd72fee7d8b46c42",
101101
"labs/diagram-json/plan.md": "3cc4f533b8d69386deff16b3a594a3ba09d4c0c3db636cccd8c4380084ce6a51",
102102
"labs/diagram-json/questions.md": "74733b015002c8a6777c558e7e997fa48c94850b9bd39054fe9366c97ecf728d",
103103
"labs/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed",
@@ -122,13 +122,14 @@
122122
"release-notes/2026-07-18-stacked-bar-mark.md": "c4d5bd5fb89c280d7fba015384fd795fcb8c31ffe501078aa55a90cbcf66ba7b",
123123
"release-notes/2026-07-18-startup-recovery-routing.md": "c305a1c2b8347e1bc6d7fcbd4a8e629438cdeb4bcf6f181a7d6fc154a88f4318",
124124
"release-notes/2026-07-19-cross-harness-hook-conformance.md": "15dc22cc3b534c6d0bd89f34cd69cabf94a3610d445a039ba111fd8bce727e68",
125+
"release-notes/2026-07-19-minimal-dated-changelogs.md": "6f525e5c5cf26cc72969a161bbdaeb4a5c1f14759c5985335e97e3d3f45b1daf",
125126
"release-notes/2026-07-19-optional-repository-changelog.md": "7ae6bed436c269335ac5055e04438489451bef00836fecb3e5fcb06a18501853",
126127
"release-notes/2026-07-19-valid-skill-frontmatter.md": "a0a002f7891474d7d1eea49e3234cae5ddbd941158726b83555dc48474181a92"
127128
},
128129
"generator": "operatorstack/intelligence-flow:boatstack-distribution",
129130
"schema_version": 1,
130131
"source": {
131-
"commit": "340059469cf115431f0f91c0a88beb34374d1e5a",
132+
"commit": "17376b5e74eb69d341c6df1b69251f2e07d47c4f",
132133
"path": "labs/12-product-engineering-loop",
133134
"repository": "operatorstack/intelligence-flow"
134135
}

boatstack/changelog.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os/exec"
77
"path/filepath"
88
"strings"
9+
"time"
910
)
1011

1112
const changelogPath = "CHANGELOG.md"
@@ -20,6 +21,18 @@ var changelogCategories = map[string]bool{
2021
"Maintenance": true,
2122
}
2223

24+
func isUnreleasedHeading(line string) bool {
25+
if line == "## Unreleased" || line == "## [Unreleased]" {
26+
return true
27+
}
28+
const prefix = "## [Unreleased] - "
29+
if !strings.HasPrefix(line, prefix) {
30+
return false
31+
}
32+
_, err := time.Parse("2006-01-02", strings.TrimPrefix(line, prefix))
33+
return err == nil
34+
}
35+
2336
// changelogEntries returns the categorized bullets in the Unreleased section.
2437
// Historical release sections are intentionally ignored: the policy requires a
2538
// new reader-facing entry for the change being prepared, not rewritten history.
@@ -31,7 +44,7 @@ func changelogEntries(value []byte) (map[string]int, error) {
3144
for _, rawLine := range strings.Split(strings.ReplaceAll(string(value), "\r\n", "\n"), "\n") {
3245
line := strings.TrimSpace(rawLine)
3346
if strings.HasPrefix(line, "## ") {
34-
if line == "## Unreleased" {
47+
if isUnreleasedHeading(line) {
3548
if foundUnreleased {
3649
return nil, fmt.Errorf("%s must contain exactly one ## Unreleased section", changelogPath)
3750
}

boatstack/changelog_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,24 @@ func writeChangelog(t *testing.T, repo, value string) {
2020
}
2121
}
2222

23+
func TestUnreleasedHeadingCompatibility(t *testing.T) {
24+
for _, test := range []struct {
25+
heading string
26+
want bool
27+
}{
28+
{heading: "## Unreleased", want: true},
29+
{heading: "## [Unreleased]", want: true},
30+
{heading: "## [Unreleased] - 2026-07-19", want: true},
31+
{heading: "## [Unreleased] - 2026-7-19", want: false},
32+
{heading: "## [Unreleased] - not-a-date", want: false},
33+
{heading: "## [1.0.0] - 2026-07-19", want: false},
34+
} {
35+
if got := isUnreleasedHeading(test.heading); got != test.want {
36+
t.Errorf("isUnreleasedHeading(%q) = %v, want %v", test.heading, got, test.want)
37+
}
38+
}
39+
}
40+
2341
func TestChangelogPolicyAcceptsExistingAndFirstEntries(t *testing.T) {
2442
for _, test := range []struct {
2543
name string
@@ -32,8 +50,8 @@ func TestChangelogPolicyAcceptsExistingAndFirstEntries(t *testing.T) {
3250
head: "# Changelog\n\n## Unreleased\n\n### Added\n\n- Existing capability.\n- New reader-visible capability.\n\n## 1.0.0\n\n- First release.\n",
3351
},
3452
{
35-
name: "first changelog",
36-
head: "# Changelog\n\n## Unreleased\n\n### Maintenance\n\n- Document the supported delivery workflow.\n",
53+
name: "first dated changelog",
54+
head: "# Changelog\n\n## [Unreleased] - 2026-07-19\n\n### Maintenance\n\n- Document the supported delivery workflow.\n",
3755
},
3856
{
3957
name: "existing legacy changelog adopts policy",

0 commit comments

Comments
 (0)