diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0e3bf9..605d81c 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/a854eed90b15a57e3923ffcc4365dbc4d1ab755f/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/2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a/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/UPSTREAM.json b/UPSTREAM.json index feff5a8..2c24888 100644 --- a/UPSTREAM.json +++ b/UPSTREAM.json @@ -12,7 +12,7 @@ }, "files": { ".gitignore": "a7079e923a776f14f1bb3a6aa0a11a133a8e1dfb35af020f327623357b7e3957", - "CONTRIBUTING.md": "05e474b0512b03545620fe479b8f40ddb48bd328d61629048361debcfbd6ec45", + "CONTRIBUTING.md": "eec90e3cfed059652742e45da9a4b56a92bec14377983801198058a10258e9e3", "README.md": "83ea436685782c5c2d2d375ceae21cb95c72a5f6608eb8187a5efc817350e081", "assets/boatstack-journey.svg": "c1f7fe2741f5e9ca66bb3fe9b103e6364ba5acbca8b7a8054768ffd85cf325ea", "assets/boatstack-mark.svg": "ec96165583b15cfd446c27049d49217973f3e9b1defa5771cc08eec0c9542ce4", @@ -31,7 +31,7 @@ "boatstack/assets/templates/test-plan.md": "6db8a9f27dd171fb80222a501cae50eb051e7278c04703fa43b5ff86dd4d2df4", "boatstack/atomic_unix.go": "89f2723361591de2bb8bd22ce7e34ec529d3278509f0df78fd5c4a7d4140fbe9", "boatstack/atomic_windows.go": "cefd775cbe7e7c3bd8a3f5673b11cdd784c6d3ebd6de7dcb8f39406b0bee511f", - "boatstack/cmd/boatstack-helper/main.go": "eb618ae01a7950276b347bc379ebd2b7be257ba9a09470ca8129cc32732bec96", + "boatstack/cmd/boatstack-helper/main.go": "dbb8cb4bb403aa36a47bd9317e9a34845cabfa5b8e4152a7fb57ded1591d8957", "boatstack/delivery.go": "bfdce7dd3bc1357a614bd458f2f6b4b8570015c117d1f7638c7a1bf3110e1a48", "boatstack/delivery_test.go": "a8a5a7e6e8dcfee1538367d49c76c531e04211876c1685265884cff26ae04497", "boatstack/export.go": "ce583075b0edce83ceeed4eed4184f7f92603a21cce87ff95854961206ebd3a2", @@ -53,6 +53,8 @@ "boatstack/references/irreversible-operation-boundary.md": "2a695f2d7de95cfc8750f107bef9c86581712aa1f02e7233b69b850d8c2af42e", "boatstack/references/portability.md": "fb683095991bb0cb06ec56fb8884c49038b283172a7d2f8b203483b7cacb4bae", "boatstack/references/workflow.md": "9430d093d89da88890993785ed0f1ec9ff328221940e3e4fdaaf4d91c41b994b", + "boatstack/release.go": "fa2ac926df89c90c5844e938a2e02d4b8dbbaefbf85bb7a1a89fc51690bea520", + "boatstack/release_test.go": "5cf2d76fe9b836a91ca68eba53d5585e2c4be5b9421aaf939ea0723063a24690", "boatstack/runtime.go": "b988d57ec14e15fc6a57949a995879fc0e0d6bfa9a7b62935e7754df0b85d87a", "boatstack/runtime_cache.go": "ab0fbb7f8a2eb8d8428e928fbc3d8866c84104e7cb330a901c121dfec82cddb3", "boatstack/runtime_cache_test.go": "4cbca9dec7800d7df6e3ec0d74c7ecbe1508e5c5a288d863f35fc8d22986c308", @@ -66,10 +68,10 @@ "docs/account-recovery-walkthrough.md": "acd3558a95f48004f18a0590670de496e1cc9f0cd1d187f924615497f57e1d6f", "docs/benchmark-corpus-audit.md": "f2d206fe8579a514f9da82b2c96c19b343ac004be67617e1bd34f0f8e0e5e6c6", "docs/benchmark-submission-audit.md": "9518abdd17690729c6423f87cab20418ed47b0915b5faa44b9ef975e9e9c3b79", - "docs/evidence-engineered-coding.md": "1c74d9a8d222c3260e972938d475a3878ad341c5a911124954a7868af6979f29", + "docs/evidence-engineered-coding.md": "5cbb20efdf3e58b6f4ed99be3d772f2284b348541f33d73212c50fbc0b85fcd8", "docs/generated-files.md": "7b2e8c10a35aa351fb87753492ed3cadb05011002d2fd6ffeb1951c356f6b286", "docs/getting-started.md": "9ecd9e543862e4bcf139be52de113c548708a2a5707c3c09233fd1605eda86d0", - "docs/public-claims.json": "e3d228e5d78434e10ec21788c41c9451d69f3dce1f00c5a371bb40924fb18924", + "docs/public-claims.json": "3dc96991a37fa768a6f268262caa3f4456f8a49c22609635b8ecbef2f68fd422", "docs/public-surface.md": "713f7a050b5f339cf948299103ef3800417dccfecf2cc1a4166397ea6f978907", "docs/research-and-design.md": "d65c66e323037bda5d45aacef5d48afa6bf93da55901378891d235aca3a5684f", "docs/safety.md": "7b9b5c515d36e683767ec8d3d9d6d119ac93650b2f629d351deadd4c600ed6a6", @@ -81,7 +83,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": "97386aea5c532218552a6097dbc2075254bb618e5383b04c0872b38cd4d3c811", + "examples/diagram-json/plan.lock.json": "b4affc03fc123caba1070d3992f11869d740765d5e439d9ee8e10ae0cddbca1b", "examples/diagram-json/plan.md": "3ad35cc3cbe48306e7ee401bd9e9047d25e46c8a6fe9679aa1b3f5e96ceea292", "examples/diagram-json/questions.md": "1a0050041cac0a8d53e6ebfe04cbec4a298cdc8c50efeeb6fa15aeb663c5ec76", "examples/diagram-json/request.md": "0808fc41c36779c404f4a3a121167da6e76cac56df526e70f9ed6d3e0d4c02ed", @@ -93,12 +95,13 @@ "release-notes/2026-07-17-delivery-harness-framing.md": "6fccbe7efdb288f5eca7e824ee5e44ad6b30a34f312eb997dca6aa44c55b26cb", "release-notes/2026-07-17-phase-scoped-delivery.md": "bfc8edd30a67daf5940ad4ceceebf81d01d62914ebeabb7073985c53f13df2ff", "release-notes/2026-07-17-visible-release-messages.md": "c93e8c812528a983502263e35d66c86a265d6ccba8203f393788c069b3fa6606", + "release-notes/2026-07-18-automated-releases.md": "6571eec442a27bd1a55667567f0659993c516171ef10ae71046cce80f7fd29fa", "release-notes/2026-07-18-stacked-bar-mark.md": "c4d5bd5fb89c280d7fba015384fd795fcb8c31ffe501078aa55a90cbcf66ba7b" }, "generator": "operatorstack/intelligence-flow:boatstack-distribution", "schema_version": 1, "source": { - "commit": "a854eed90b15a57e3923ffcc4365dbc4d1ab755f", + "commit": "2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a", "path": "examples/12-product-engineering-loop", "repository": "operatorstack/intelligence-flow" } diff --git a/boatstack/cmd/boatstack-helper/main.go b/boatstack/cmd/boatstack-helper/main.go index 96086e8..291bd33 100644 --- a/boatstack/cmd/boatstack-helper/main.go +++ b/boatstack/cmd/boatstack-helper/main.go @@ -63,6 +63,36 @@ func checkUpdateCommand(arguments []string) int { return 0 } +func releaseClassifyCommand(arguments []string) int { + flags := flag.NewFlagSet("release-classify", flag.ContinueOnError) + repo := flags.String("repo", ".", "projected Boatstack repository") + base := flags.String("base", "", "latest released tag or commit") + head := flags.String("head", "HEAD", "candidate release commit") + if err := flags.Parse(arguments); err != nil { + return 2 + } + classification, err := boatstack.ClassifyReleaseDiff(*repo, *base, *head) + if err != nil { + return fail(err) + } + fmt.Printf("release_required=%t\nrelease_paths=%s\n", classification.Required, strings.Join(classification.Paths, ",")) + return 0 +} + +func nextPatchCommand(arguments []string) int { + flags := flag.NewFlagSet("next-patch", flag.ContinueOnError) + version := flags.String("version", "", "current stable vMAJOR.MINOR.PATCH version") + if err := flags.Parse(arguments); err != nil { + return 2 + } + next, err := boatstack.NextPatchVersion(*version) + if err != nil { + return fail(err) + } + fmt.Println(next) + return 0 +} + func exportCommand(arguments []string) int { flags := flag.NewFlagSet("export", flag.ContinueOnError) repo := flags.String("repo", "", "repository to export into") @@ -434,7 +464,7 @@ func publishPRCommand(arguments []string) int { func run() int { if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "usage: boatstack-helper ") + fmt.Fprintln(os.Stderr, "usage: boatstack-helper ") return 2 } switch os.Args[1] { @@ -444,6 +474,10 @@ func run() int { return updateCommand(os.Args[2:]) case "check-update": return checkUpdateCommand(os.Args[2:]) + case "release-classify": + return releaseClassifyCommand(os.Args[2:]) + case "next-patch": + return nextPatchCommand(os.Args[2:]) case "export": return exportCommand(os.Args[2:]) case "check-source-plan": diff --git a/boatstack/release.go b/boatstack/release.go new file mode 100644 index 0000000..be0b751 --- /dev/null +++ b/boatstack/release.go @@ -0,0 +1,94 @@ +package boatstack + +import ( + "fmt" + "os/exec" + "path/filepath" + "regexp" + "sort" + "strconv" + "strings" +) + +var stableReleaseVersion = regexp.MustCompile(`^v(\d+)\.(\d+)\.(\d+)$`) + +// ReleaseClassification separates a projected documentation sync from a +// change that alters the installed Boatstack delivery harness. +type ReleaseClassification struct { + Required bool + Paths []string +} + +func normalizedReleasePath(value string) string { + return filepath.ToSlash(filepath.Clean(strings.TrimSpace(value))) +} + +func isReleaseBearingPath(value string) bool { + path := normalizedReleasePath(value) + if path == "." || path == "" { + return false + } + for _, exact := range []string{ + ".gitignore", "CONTRIBUTING.md", "README.md", "UPSTREAM.json", + "project.example.json", + } { + if path == exact { + return false + } + } + for _, prefix := range []string{ + ".github/", "assets/", "automation/", "docs/", "examples/", "release-notes/", + } { + if strings.HasPrefix(path, prefix) { + return false + } + } + if strings.HasPrefix(path, "boatstack/testdata/") || strings.HasSuffix(path, "_test.go") { + return false + } + return true +} + +// ClassifyReleasePaths is conservative: unknown projected product paths are +// release-bearing, while known presentation, provenance, test, and control +// plane paths are not. +func ClassifyReleasePaths(paths []string) ReleaseClassification { + releasePaths := make([]string, 0, len(paths)) + seen := map[string]bool{} + for _, value := range paths { + path := normalizedReleasePath(value) + if !seen[path] && isReleaseBearingPath(path) { + seen[path] = true + releasePaths = append(releasePaths, path) + } + } + sort.Strings(releasePaths) + return ReleaseClassification{Required: len(releasePaths) > 0, Paths: releasePaths} +} + +// ClassifyReleaseDiff reads the exact projected Git diff used by the release +// workflow and applies the same deterministic path policy as unit tests. +func ClassifyReleaseDiff(repo, base, head string) (ReleaseClassification, error) { + if strings.TrimSpace(base) == "" || strings.TrimSpace(head) == "" { + return ReleaseClassification{}, fmt.Errorf("release classification requires base and head revisions") + } + command := exec.Command("git", "-C", repo, "diff", "--name-only", "--no-renames", base, head) + output, err := command.CombinedOutput() + if err != nil { + return ReleaseClassification{}, fmt.Errorf("release diff failed: %s", strings.TrimSpace(string(output))) + } + return ClassifyReleasePaths(strings.Split(strings.TrimSpace(string(output)), "\n")), nil +} + +// NextPatchVersion returns the next stable patch version. Minor and major +// releases remain deliberate changes rather than being inferred from commits. +func NextPatchVersion(current string) (string, error) { + matches := stableReleaseVersion.FindStringSubmatch(strings.TrimSpace(current)) + if matches == nil { + return "", fmt.Errorf("release version must match vMAJOR.MINOR.PATCH: %s", current) + } + major, _ := strconv.Atoi(matches[1]) + minor, _ := strconv.Atoi(matches[2]) + patch, _ := strconv.Atoi(matches[3]) + return fmt.Sprintf("v%d.%d.%d", major, minor, patch+1), nil +} diff --git a/boatstack/release_test.go b/boatstack/release_test.go new file mode 100644 index 0000000..3aff5df --- /dev/null +++ b/boatstack/release_test.go @@ -0,0 +1,72 @@ +package boatstack + +import ( + "os" + "path/filepath" + "reflect" + "testing" +) + +func TestClassifyReleasePaths(t *testing.T) { + documentation := []string{ + "README.md", "docs/getting-started.md", "assets/boatstack-mark.svg", + "release-notes/2026-07-18-copy.md", "UPSTREAM.json", + "boatstack/export_test.go", "boatstack/testdata/example.txt", + ".github/workflows/sync-upstream.yml", "automation/release-policy.md", + } + if got := ClassifyReleasePaths(documentation); got.Required || len(got.Paths) != 0 { + t.Fatalf("documentation-only projection requested a release: %#v", got) + } + + runtime := append(documentation, + "boatstack/safety.go", "boatstack/SKILL.md", "install.sh", "new-runtime-path", + ) + want := []string{"boatstack/SKILL.md", "boatstack/safety.go", "install.sh", "new-runtime-path"} + got := ClassifyReleasePaths(runtime) + if !got.Required || !reflect.DeepEqual(got.Paths, want) { + t.Fatalf("runtime classification = %#v, want %#v", got, want) + } +} + +func TestClassifyReleaseDiff(t *testing.T) { + repo := t.TempDir() + runGit(t, repo, "init", "-b", "main") + runGit(t, repo, "config", "user.name", "Boatstack Test") + runGit(t, repo, "config", "user.email", "boatstack@example.invalid") + if err := os.WriteFile(filepath.Join(repo, "README.md"), []byte("one\n"), 0o644); err != nil { + t.Fatal(err) + } + runGit(t, repo, "add", ".") + runGit(t, repo, "commit", "-m", "base") + base := runGit(t, repo, "rev-parse", "HEAD") + if err := os.WriteFile(filepath.Join(repo, "README.md"), []byte("two\n"), 0o644); err != nil { + t.Fatal(err) + } + runGit(t, repo, "add", ".") + runGit(t, repo, "commit", "-m", "docs") + docsHead := runGit(t, repo, "rev-parse", "HEAD") + if got, err := ClassifyReleaseDiff(repo, base, docsHead); err != nil || got.Required { + t.Fatalf("documentation diff = %#v, %v", got, err) + } + if err := os.MkdirAll(filepath.Join(repo, "boatstack"), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(repo, "boatstack", "runtime.go"), []byte("package boatstack\n"), 0o644); err != nil { + t.Fatal(err) + } + runGit(t, repo, "add", ".") + runGit(t, repo, "commit", "-m", "runtime") + runtimeHead := runGit(t, repo, "rev-parse", "HEAD") + if got, err := ClassifyReleaseDiff(repo, docsHead, runtimeHead); err != nil || !got.Required { + t.Fatalf("runtime diff = %#v, %v", got, err) + } +} + +func TestNextPatchVersion(t *testing.T) { + if got, err := NextPatchVersion("v0.7.0"); err != nil || got != "v0.7.1" { + t.Fatalf("next patch = %q, %v", got, err) + } + if _, err := NextPatchVersion("latest"); err == nil { + t.Fatal("invalid release version was accepted") + } +} diff --git a/docs/evidence-engineered-coding.md b/docs/evidence-engineered-coding.md index feb2991..d9c248f 100644 --- a/docs/evidence-engineered-coding.md +++ b/docs/evidence-engineered-coding.md @@ -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 [`a854eed90b15a57e3923ffcc4365dbc4d1ab755f`](https://github.com/operatorstack/intelligence-flow/tree/a854eed90b15a57e3923ffcc4365dbc4d1ab755f/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 [`2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a`](https://github.com/operatorstack/intelligence-flow/tree/2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a/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/public-claims.json b/docs/public-claims.json index 4be7163..212b0c6 100644 --- a/docs/public-claims.json +++ b/docs/public-claims.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "source_commit": "a854eed90b15a57e3923ffcc4365dbc4d1ab755f", + "source_commit": "2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a", "statuses": ["verified", "observed", "still_being_evaluated"], "claims": [ { @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "human-decisions", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "validation-provenance", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "irreversible-operations", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "reviewer-ready-pr", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "phase-scoped-delivery", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "model-neutral-contract", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "cross-model-failures", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "lower-cost-outcomes", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "git-worktree-activation", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" }, { "id": "visible-updates", @@ -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:a854eed90b15a57e3923ffcc4365dbc4d1ab755f" + "last_verified_version": "source:2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a" } ] } diff --git a/examples/diagram-json/plan.lock.json b/examples/diagram-json/plan.lock.json index 876fd09..27d3280 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": "a854eed90b15a57e3923ffcc4365dbc4d1ab755f", + "source_commit": "2d8a19db2fc0c2a6adf970830e9d8fc3bf70c93a", "source_plan_path": "examples/diagram-json/source-plan.md", "source_plan_sha256": "e10593ddaa7522ab80cc991d0a09399257139799e37f737794cd49d68a39985b", "spec_path": "examples/diagram-json/spec.md", diff --git a/release-notes/2026-07-18-automated-releases.md b/release-notes/2026-07-18-automated-releases.md new file mode 100644 index 0000000..830f52d --- /dev/null +++ b/release-notes/2026-07-18-automated-releases.md @@ -0,0 +1,3 @@ +### Intelligence Flow merges now publish Boatstack automatically + +Boatstack now receives an immediate projection after relevant Intelligence Flow merges. Generated changes still pass the downstream pull-request and cross-platform test gates, while runtime changes receive the next patch release automatically and documentation-only changes sync without publishing unnecessary binaries.