Skip to content

Production - #5

Open
yerayalfageme-glitch wants to merge 40 commits into
CairnMP:productionfrom
yerayalfageme-glitch:production
Open

Production#5
yerayalfageme-glitch wants to merge 40 commits into
CairnMP:productionfrom
yerayalfageme-glitch:production

Conversation

@yerayalfageme-glitch

Copy link
Copy Markdown

No description provided.

yerayalfageme-glitch and others added 30 commits August 12, 2026 10:14
AI agents working in this repo had no instructions, so each session
rediscovered the same non-obvious facts and some of them wrong. The block
records only what the code cannot say: that building the mod project is
also a deploy into the live Cairn Mods folder, that three version
constants are generated from versions.json by sync-versions.js, and that
the protocol tests run without game-refs while the solution-wide test run
does not.

Everything the repo already states first-hand stays out - build commands,
the game-refs setup and the packet-numbering rules are read from README,
.gitignore and Protocol.cs, where they cannot drift out of sync.

Also fixes two instructions that contradicted reality:

- scripts/check.sh claimed a .githooks/pre-push hook invoked it
  automatically. No such hook exists and core.hooksPath is unset, so the
  header now says to run it manually. Translated to English while there,
  per the convention 9fb3336 established.
- README's layout table omitted CairnMultiplayerMod.Tests, which is in
  the .slnx.

Ignore the local BMad install (.claude/, _bmad/) and its generated output
so tooling does not appear in diffs against upstream.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The BMad rules treated every _bmad-output/ file as disposable local output.
That also hid the spec contract and the research it derives from, so the
reasoning behind planned work existed on one machine only, with no history
and no remote copy. Narrow the rule to _bmad-output/* so specs/ and
planning-artifacts/ can be re-included; git never descends into an excluded
directory, so the negations do not work against a bare _bmad-output/.
Generated output such as implementation-artifacts/ stays ignored.

Also fold the three .bmad-loop/* entries written by `bmad-loop init` into a
single directory ignore, matching how _bmad/ and .claude/ are already
treated, and drop the redundant _bmad/render/ line. Personal editor
workspace files join the existing .vscode/ and .idea/ rules.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Records why net6.0 is a pin rather than technical debt: MelonLoader v0.7.3
hosts IL2CPP mods on the .NET 6 Desktop Runtime, which in turn puts xunit v3
out of reach and makes Il2CppInterop and HarmonyX loader-supplied rather than
chosen. Five dimensions, held to a two-source bar, with a semantic citation
check that corrected six of twenty-eight citations.

Kept because the spec added next derives from it, and because its staleness
map is what tells a future reader which version claims to re-check first.
Committed now that _bmad-output/planning-artifacts/ is tracked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Distils the research into the contract the implementation work derives from:
four capabilities, seven constraints, five non-goals, with the pinned
dependency chain and the accepted risks split into companions so the kernel
stays readable.

The load-bearing conclusion is that verification, not version currency, is
the reachable goal. The packet-parsing code carrying the unpatched-runtime
exposure is also the only project that builds without game assemblies, so CI
on CairnMultiplayerShared.Tests guards the highest-risk surface at no legal
risk and with no technology change.

Closes the two questions the research left gated. xunit.runner.visualstudio's
net6.0 ceiling is 3.0.2, not the 2.8.2 currently pinned -- 3.1.0 moved its
explicit targets to net8.0 -- and the xunit v2 line has shipped nothing since
2.9.3. Two of the three test packages therefore drop net6.0 the same way, via
AssetTargetFallback: they restore cleanly and then fail at runtime with
"Could not find testhost". That makes the pins the durable deliverable and
the version bumps the one-off, which is why stories.yaml orders CI first so
it verifies the bump rather than the bump landing unverified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sprint-status.yaml is the tracking file every implementation agent reads and
updates, so leaving it local-only meant the record of what was built, and in
what order, could not survive a machine loss or be reviewed alongside the
spec it implements. It lands in implementation-artifacts/, which the previous
commit left ignored.

Accepts some churn: the file changes as stories complete, so expect status
updates in the log. That is the cost of having the sprint state reviewable
next to the contract it derives from. Other generated output -- test
artifacts, brainstorming, rendered skills -- stays ignored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The build loop reads sprint-status.yaml (policy.toml pins stories.source =
"sprint-status"), so the spec's four stories needed a board before any of them
could be driven. Generation is deterministic, but the generator parses epic
markdown and this spec shipped a typed stories.yaml instead -- so epics.md
projects that breakdown into the headings it reads, one epic over the four
stories, and carries a header saying stories.yaml stays the source of truth.

The readiness gate passes: every story traces to a capability, and the repo
still shows all four undone -- no .github/workflows, no CheckSdkVulnerabilities,
test packages at 17.11.1 / 2.9.2 / 2.8.2, and generate-il2cpp-refs.ps1:97 still
telling contributors to commit game-refs.

One assumption is recorded in epics.md rather than assumed silently: story 1.4
bumps CairnMultiplayerMod.Tests alongside the Shared suite. CAP-4's success
criterion names only Shared, but the Mod suite carries the same three pins and
leaving it behind reintroduces exactly the drift the pins prevent. Only Shared
is verifiable on a runner, so only Shared gets the dotnet test check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Switches tracking_system from file-system to github and points project_key at
the fork, yerayalfageme-glitch/cairnmp-mod. Issues #1-#4 mirror the four story
keys; #1 (CI) is named as the blocker on #4 (package bump), since a clean
restore cannot verify that bump and only the CI job can.

Issues were disabled on the fork -- GitHub's default for forks -- so they had to
be enabled first. Every gh call names the fork explicitly: the default repo
resolves to the CairnMP upstream, where none of this belongs.

The story-to-issue map lives in a custom story_issues key. The generator
round-trips unknown top-level keys, so a sprint-planning refresh preserves it,
but it does NOT preserve a comment anchored there -- the explanatory block
written alongside it was dropped on the very next regenerate, which is why the
map now stands bare and this message carries the explanation instead. Statuses
stay in development_status alone; story_issues records identity, not state.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CairnMultiplayerShared parses untrusted packets from remote peers on a .NET 6
runtime that stopped receiving security patches in November 2024, and nothing
verified it on any push. The runtime pin belongs to MelonLoader and is not ours
to move, so automated verification is the only mitigation within reach.

Scoped to CairnMultiplayerShared.Tests because it is the one suite whose project
graph terminates without the proprietary game assemblies in git-ignored
game-refs/. The job installs a .NET 6 SDK explicitly: runner images ship .NET
8/9/10 only, and while net6.0 would still build there, the testhost requests
Microsoft.NETCore.App 6.0.0 and roll-forward never crosses a major, so the run
would die at test-host launch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Temporary. The new workflow is only worth trusting if it fails when the
protocol breaks, so this falsifies one assertion in ClientPingPlaced_RoundTrips
to watch the check go red and name that test. Reverted in the next commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The comment explained the scoping by naming the excluded project and the
git-ignored reference directory. The workflow is meant to be auditable by
reading it — a grep for either name should come back empty — so the rationale
now describes them rather than spelling them out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cancellation applied to every event, so a second push to an integration branch
cancelled the in-flight run for the previous SHA. A cancelled run is neither a
pass nor a failure, which meant a commit could land verified by nothing. Limit
cancellation to pull requests, where only the head SHA matters.

Also bound the job at 15 minutes so a hung restore or testhost cannot hold a
runner for the six-hour default, and add next/feature-framework to both branch
filters: it is long-lived on both remotes, so pull requests targeting it were
getting no verification at all.

The trigger rationale moves above `on:`, where the behaviour it explains
actually lives, and the concurrency comment now describes the concurrency.

Spec: correct two Code Map facts, record the green/red/green run evidence behind
the ticked boxes, and state the pass expectation as a property rather than a
test count that goes stale on the next test added.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Marks the story spec done and moves the board to review. The workflow itself
landed in 41607e3; this commit carries the artifacts that explain it -- the spec
with its evidence and suggested review order, the compiled epic context, and the
deferred-work ledger the review produced.

Six findings were patched into 41607e3. The load-bearing one: cancel-in-progress
applied to every event, so a second push to an integration branch would cancel
the previous SHA's verification, and a cancelled run is neither a pass nor a
failure -- a commit could land verified by nothing. Cancellation is now confined
to pull requests, where only the head SHA matters.

Six more are deferred rather than done, and one of them qualifies the story's
own success: the check is advisory. Neither develop nor production has branch
protection or a ruleset, so a red run does not block a merge. Story 1.1 proves
CI can turn red; making red stop anything is a repo-settings change nobody has
made yet.

One review claim was rejected on evidence rather than judgement: a reviewer
asserted actions/checkout@v7 and setup-dotnet@v6 do not exist and the job would
die at setup, which would have invalidated every proof in the spec. The run logs
show both resolving to real SHAs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ci: verify the protocol test suite on every push
PR #5 merged, so the workflow is on the integration branch rather than only on a
topic branch. That closes the one gap the story could not prove before merging:
the push trigger had never fired, only pull_request. It has now -- run
31780031548 on develop, event=push, 63/63 green.

Marked done rather than routed through bmad-code-review. The story already ran
three adversarial review layers inside build, and the merge is the stronger
signal. Issue #1 closed with the run evidence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…refs

generate-il2cpp-refs.ps1 ended with "You can now commit these files" -- the
files being proprietary Cairn, Unity and MelonLoader assemblies. That instructed
the one action .gitignore:2, the README and AGENTS.md all forbid, and it was the
last line on screen at the moment someone would act on it.

The replacement states why rather than only what, so the next person to edit the
block knows what it is protecting, and the same constraint now sits in the file
header where it is read before anyone spends five minutes launching the game.

Two review findings landed on the first attempt and were corrected. The note was
Yellow, which in this script is the error colour -- every other Yellow line
precedes a throw -- so a clean run ended looking like a warning; it is DarkGray
now. It also printed before "Done!", announcing a caution before the success it
qualifies.

Comments translated to English per AGENTS.md:30, which asks for it in any French
file you touch. Verified the script still parses and stayed pure ASCII.

Audit for the story's second half: line 97 was the only contradicting line here.
The same false "(versioned)" claim exists in package-mod.ps1 and
Directory.Build.props, both outside this story's scope and both recorded in
deferred-work.md rather than fixed silently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Raise Microsoft.NET.Test.Sdk to 17.13.0, xunit to 2.9.3 and
xunit.runner.visualstudio to 3.0.2 in both test projects -- the highest
versions that still target net6.0 explicitly.

Two of the three do not fail loudly when crossed: Test.Sdk above 17.13.0
and the runner above 3.0.2 restore cleanly via AssetTargetFallback and
then die at runtime with "Could not find testhost". So the durable
deliverable here is not the numbers but the comment recording each
ceiling at the exact line someone would edit, pointing at stack.md.

Exact-version ranges ([17.13.0], [2.9.3], [3.0.2]) keep the resolved
version from drifting upward on its own; restore stays warning-free.

Verified by execution, not restore: dotnet test CairnMultiplayerShared.Tests
-c Release passes 63/63 on a .NET 6 runtime. CairnMultiplayerMod.Tests
gets the identical three lines for parity but ships unexecuted -- its
graph needs the gitignored game-refs/ and cannot build on a runner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both verification legs are now evidenced in the spec: the local run
(63/63, exit 0) and PR #7's green CI check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review turned up six accuracy defects, four of them in claims rather
than in code.

The csproj block comment generalised wrongly: it attached the
"restores cleanly, then fails at runtime with Could not find testhost"
warning to all three packages. That is true of Microsoft.NET.Test.Sdk
and xunit.runner.visualstudio only. xunit's ceiling is a different
thing entirely -- 2.9.3 ends the v2 line and v3 floors at net8.0. Since
this comment is the story's durable deliverable, a wrong generalisation
in it defeats the purpose of writing it down. The two reasons are now
separated.

stack.md's "CairnMP has" column still read 2.9.2 / 17.11.1 / 2.8.2. The
csproj comment points readers at that table, so the pointer contradicted
the tree it was shipped with.

The mod test project was described as impossible to verify anywhere.
scripts/check.sh:21 runs dotnet test across the solution and AGENTS.md:26
documents it as the pre-push check, so a developer holding game-refs/
does exercise it. The honest claim is that it cannot be verified in CI,
or without those assemblies.

Also: real CI evidence (both run ids with the sha each ran against, PR
qualified by repo because gh resolves a bare #7 against upstream, and
the project.assets.json netcoreapp3.1 finding that proves
AssetTargetFallback never engaged) replaces a duration that matched no
run; stale :11-13 code-map anchors now point at 20, 22, 24; and a design
note records that the pins stop transitive drift but not a human editing
the number, at the cost of a hard NU1107/NU1608 restore failure when a
future package genuinely needs a higher Test.Sdk.

Comment-only change to both csprojs: 63/63 still pass locally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The evidence block called 7b9d10a "the PR head", which the review-patch
commit immediately falsified -- the same class of staleness the review
flagged in the first place. Record the per-commit run invariant instead
of a sha that goes stale on the next push, and add the run for 63bddbc.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Marks the spec done with its review order, and files the four findings the
review surfaced that this story deliberately did not fix.

Two of the six patches applied in 0e6e0cc corrected the spec rather than the
code. It claimed the mod test project "cannot be built or verified anywhere",
which scripts/check.sh:21 disproves -- solution-wide dotnet test does exercise
it on a machine holding game-refs/, so the accurate claim was "not in CI". And
the csproj comment told the reader that raising any of the three fails at
runtime rather than at restore; that is true of Test.Sdk and the runner, but
xunit v3 hard-floors at net8.0 and fails differently. A wrong generalisation in
the one artifact whose entire purpose is to teach the next person.

The deferred entries include one this story did not cause: sprint-status.yaml is
being edited on three branches at once, so PRs #6 and #7 both touch it against a
develop that has moved. Story 1.1 reads done on the 1.2 branch and review on
develop. That needs a decision about where the board is allowed to change, not a
fix inside any one story.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…commit-instruction

fix(scripts): stop telling contributors to commit the generated game-refs
Resolves the board collision the review predicted. sprint-status.yaml and
deferred-work.md were both edited on three story branches at once, so this is
the conflict that was filed as deferred work rather than a surprise.

development_status auto-merged correctly and needed no hand resolution. Only
last_updated collided; kept the later stamp. Story 1.2 is also moved to done
here, since PR #6 merged while this branch was open.

deferred-work.md is append-only, so both blocks are kept in full -- story 1.2's
five entries ahead of story 1.4's four, chronologically. All 15 entries survive;
nothing was dropped in favour of either side.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…es-net6-ceilings

chore(deps): pin test packages at their net6.0 ceilings
Bookkeeping only, committed directly on develop rather than through a branch:
the fact it records -- that the pins are merged -- is already true here, and
routing a two-line status change through another PR would edit the same board
lines that just caused a merge conflict.

That is one of the two answers to the open question filed in deferred-work.md:
either the board changes only on develop after merge, or every story branch
edits it and the conflicts get resolved by hand. This commit follows the first,
but the decision is still open.

Epic 1 is now 3 of 4 done, with only story 1.3 left in backlog.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…upstream codes

CAP-3 asks for a signal when the SDK compiling this repo goes out of
support. The property that produces it exists only in dotnet/sdk main
(.NET 11, still preview), so setting it now buys nothing today and
everything at the moment the toolchain moves - with no migration to
remember. The comment is the load-bearing part of the change: an
undocumented inert flag reads as a guard that is watching, which is worse
than no flag at all, so the file itself says it is inert until .NET 11 and
that even then the check no-ops when its support-policy cache is absent.

NoWarn was written in overwrite form, silently discarding any code the SDK
or an outer props file had set before this file is evaluated. The append
form costs nothing and removes a trap that would only ever surface as a
warning that mysteriously came back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The evidence a reviewer needs here is unusual: the property emits nothing
on any SDK that exists, so a green build proves only that it did no harm.
What actually distinguishes a working inert flag from a misspelled one is
the -getProperty read, and what proves the NoWarn fix is a scratch import
that sets NoWarn upstream first - both recorded, because neither is
reproducible from the diff alone.

Also corrects the comment's "the net6.0 pin below": TargetFramework is set
in the csproj files, not in this props file, so "below" pointed at nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The evidence named only the first commit's run, but the PR head had moved
past it; a reader checking the claim would have verified a sha that is no
longer what merges.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review found the documentation, which is this story's whole deliverable,
claiming more than the evidence supported.

The SDK claim was the serious one. CI installs 6.0.428, but with no
global.json MSBuild takes the highest SDK on the runner and the image
preinstalls 10.x, so which SDK compiles is undetermined - and unknowable
from the logs, because the one diagnostic that would hint at it is
suppressed by this very file. The local 6.0.428 rebuild reproduces the
installed SDK, not the building one, and now says so. That ignorance is
also the argument for keeping the NETSDK1138 suppression, so the reason
now sits on the suppression itself.

"Inert until .NET 11" had no citation a reader could check, and the Learn
page for NETSDK1239 carries no version moniker - read alone it suggests
the opposite. What settles it is that SDK 6.0.428 and 8.0.424 contain no
trace of the property at all; that search is now the recorded evidence,
the clean 8.0.424 build is explicitly marked as proving nothing (in-support
SDKs stay silent either way), and the comment cites the docs page.

Also: "no later migration to remember" was wrong, since a preview-only
property can be renamed or dropped before GA and leave dead text reading
as armed; the comment now says what 1238 and 1240 cover and why a property
named for vulnerabilities carries an end-of-support signal; and the
translated group header no longer calls a support tripwire "code style".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Marks the spec done and files the five findings the review surfaced that this
story deliberately did not fix.

The review corrected the story's own evidence, not just its prose. The earlier
"clean build on SDK 8.0.424 with the property set" was presented as proof the
property is inert; it proves nothing, because .NET 8 is supported until November
2026, so NETSDK1239 would stay silent there even if the feature were fully
implemented. The real evidence is a string search: CheckSdkVulnerabilities and
SdkVulnerability* appear in zero files across the installed 6.0.428 and 8.0.424
SDKs, while CheckEolTargetFramework is found in 8.0.424 as a positive control
proving the search method works.

Also settled which SDK CI uses, which the reviewers and the implementation
disagreed on. setup-dotnet installs SDK 6.0.428, but there is no global.json and
the runner preinstalls 10.x, so the building SDK is undetermined and most likely
10.x. Recorded as undetermined rather than asserted -- the logs cannot settle it,
since NETSDK1138 is suppressed either way. That ambiguity is precisely why the
suppression was kept rather than removed.

CAP-3 closes half-discharged: the property is set, but no shipping SDK can emit
NETSDK1239, so the capability's second clause is recorded unmet-by-toolchain.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
yerayalfageme-glitch and others added 10 commits August 14, 2026 10:50
…rabilities

chore(build): arm CheckSdkVulnerabilities and fix NoWarn overwrite form
All four stories are merged to develop, so story 1.3 moves to done and epic-1
with it. Only the optional retrospective remains open.

Routed through a pull request rather than pushed directly, because develop is
now protected and required status checks block direct pushes -- including this
kind of bookkeeping. That is the answer to the open question deferred-work.md
raised about where the board may change, settled by the protection rather than
by preference.

Epic 1 delivered three capabilities fully and one half. CAP-3 is set but inert:
no shipping SDK implements CheckSdkVulnerabilities, so its second clause is
recorded unmet-by-toolchain rather than claimed. Left visible on purpose.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Verdict: accepted-with-open-items, against declared criteria (SPEC.md's four
capability success clauses). All four stories done, so nothing forced a machine
rejection; CAP-3 ships half-met because no shipping SDK implements
CheckSdkVulnerabilities, surfaced before implementation and shipped knowingly.

Six seam findings -- defects no story review could see, because no session saw
both sides. Each re-verified against its primary source before being routed.

The consequential one: origin/production carries none of the epic. It is 33
commits behind, has no workflow file, and its copy of generate-il2cpp-refs.ps1
still tells contributors to commit game-refs. So SPEC's success signal -- nothing
left in the repo instructs a contributor to commit game-refs -- is false on the
release branch, and ci.yml lists production in push.branches even though push
events resolve workflows from the pushed ref, where the file does not exist.

Also found: the red proof is superseded evidence, describing a tree from before
the package pins and the props change; two Code Map anchors in spec-1-1 that
later stories invalidated; a note in spec-1-1 calling the push trigger
unexercised when eight push runs have since gone green; and spec-1-3 still
reading review while the board says done -- a sed for 'in-review' that matched
nothing against a value of 'review', with the no-op never checked.

Fixes are proposed, not applied, per the skill's contract. Seven action items
recorded in sprint-status with ids and a ref back to the document.

Routed through a PR because develop is protected -- including for this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ective

docs(retro): epic 1 retrospective
The retrospective left three open questions for a human and proposed fixes
without applying them. All three are now answered, so the seven action items
are unblocked.

production is in scope: promote develop into it, so ci.yml and the corrected
generate-il2cpp-refs.ps1 reach the release branch and CAP-2's success signal
becomes true repo-wide rather than on develop alone.

next/feature-framework stays and gets the workflow: merge develop into it so
the trigger entries added in 41607e3 describe real coverage instead of a push
leg that cannot fire. This makes spec-1-1:54 stale a second way -- its frozen
task text still says push on develop/production -- which item 4's refresh now
has to cover.

CAP-2's success clause gets amended to name the branches it binds, so a future
epic is falsifiable per-branch. That is new work, recorded as item 8 and
sequenced after item 1 so the wording describes the post-promotion tree.

The decisions live in a new decisions block, each pointing at the action item
it resolves via `resolves`; items 1 and 5 gained a `resolved_by` pointing back.
The retro's action-item text is left verbatim -- it is the frozen record, so
the decisions settle the either/or rather than rewriting it.

Two pre-flight findings are captured in the notes on decision 1 because they
are expensive to re-derive. production is protected -- required check, admins
enforced, conversation resolution required -- which supersedes the
deferred-work entry claiming neither branch is protected. And the required
check will report on a develop -> production PR: production is listed under
pull_request.branches, and a pull_request run resolves its workflow from the
merge commit, which carries ci.yml from develop even though the base branch
has none. A required check that could never run would have locked the branch.

Left undecided, and stated as such: the promotion carries 31 files and +1799
lines, most of it the _bmad-output tree and a .memlog.md. Whether the release
branch should hold BMad workflow artifacts is a separate call from whether it
should hold ci.yml and the fixed script.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ecisions

chore(sprint): record the epic 1 retrospective decisions
…e decisions

.gitignore already states the policy -- BMad scratch and rendered output stay
local, while the spec contract, the research behind it and the sprint state are
project records and belong in history. The two per-session .memlog.md logs were
tracked against that policy, not by it: `!_bmad-output/specs/` and its siblings
re-include each subtree wholesale, dotfiles included, so the scratch rode in
with the records. Last match wins, so the new rule sits after the negations.

Both files stay on disk; only history stops carrying them. Verified with
check-ignore that the rule matches both paths and that SPEC.md and its
companions remain tracked.

Sequenced deliberately. Doing this before the production promotion means that
branch never receives the files at all, rather than receiving them and needing
a removal commit after.

Also records the two decisions behind this and behind the promotion's shape:

- q4: the promotion carries everything, as a straight merge. production becomes
  an exact mirror of develop, so the ignore policy reads the same on both
  branches, an empty production...develop diff keeps meaning fully promoted, and
  future promotions stay plain merges. The rejected alternative -- pruning
  _bmad-output on production -- would leave the two branches permanently
  divergent and need repeating by hand every time.

- q5: this change. Not a retro action item; it surfaced while sizing the
  promotion diff.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-scratch

chore(sprint): untrack the .memlog.md scratch logs
chore(release): promote epic 1 to production
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant