Stage 0 Wave C: continuous integration - #4
Merged
Merged
Conversation
Records seven brainstorming decisions: checksummed development artifact, a CI secret-scanning job alongside the already-enabled native scanning, validity checks, Windows runners for .NET jobs, a discovered-test-count assertion, C#-only formatting, and one SBOM generator covering both ecosystems. Also records the three repository settings changes this wave needs, so the footprint outside the repository tree is visible up front. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Six tasks: the correctness jobs, the security and release jobs, pushing and driving every job green, recording the required checks, the approval-gated repository settings and branch protection, and integration verification with independent Codex review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Injun Lee <2006ijlee@gmail.com>
The test step asserts a minimum discovered-test count because dotnet test exits 0 both when no tests exist and when discovery is broken. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
gitleaks is version-pinned and downloaded directly rather than through a marketplace action with licensing conditions. It runs with full history, redacted output, and a failing exit code on any finding. Pinned to v8.30.1; uses the `git` subcommand rather than the deprecated `detect` subcommand per that release's README. The artifact job publishes the three executables, checksums the archive, and uploads it with a CycloneDX SBOM. Per D-018 the checksum is integrity evidence only; it is not publisher authentication. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
pwsh does not treat a non-zero exit from a native command as a terminating error, and the runner only fails a pwsh step on an uncaught PowerShell exception or explicit exit. Without a check, a failing dotnet publish (e.g. McpBridge fails to compile) would let the loop continue, leaving a partial artifacts/publish/ directory that Compress-Archive and Get-FileHash would happily process into a consistent-looking but incomplete, misleading package. Add an explicit $LASTEXITCODE check after each publish call, so a failure in the first iteration aborts before the second one runs. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Push/pull_request triggers only fire for main, so pushing a feature branch produces no run and this task is forbidden from opening a PR. workflow_dispatch lets the workflow be run manually against this branch to get real execution evidence, without widening the push/pull_request trigger scope. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
workflow_dispatch requires the workflow to already exist on the default branch, so it cannot dispatch a run for this branch before it merges to main. All work in this repo happens on codex/* branches before merging (see codex/stage0-wave-a, -b, -c), so extending the push trigger to that pattern lets CI actually execute and be verified pre-merge, which is the only way to get runtime proof without opening a pull request. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Wave B's files were never format-checked by CI. dotnet format --verify-no-changes failed on windows-latest with ENDOFLINE errors across every .cs file, because .gitattributes forced eol=lf for all text files while .editorconfig requires eol=crlf for .cs/.csproj/ .props/.targets. Running dotnet format locally fixed the working tree, but committing it as-is would have git silently renormalize the line endings back to LF on the next checkout (per .gitattributes), reproducing the same CI failure in a loop. Fixed by adding eol=crlf entries to .gitattributes for .cs/.csproj/.props/.targets, matching the extensions .editorconfig already treats as crlf, then renormalizing the tree. The only content diff (not just whitespace) is a stray UTF-8 BOM that dotnet format stripped from three Program.cs files; no logic or member reordering. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Step 4's end-to-end check (download the artifact, run sha256sum -c on it) failed: Out-File on windows-latest wrote openmemory-dev.zip.sha256 with a trailing CRLF, so sha256sum read the filename as 'openmemory-dev.zip\r', which does not match the actual extracted file, and reported FAILED open or read instead of OK. Write the file directly via File.WriteAllText with an explicit LF so the checksum file is consumable by the standard sha256sum -c tool regardless of which OS produced it. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Names the six job names branch protection will require, and states that renaming a job silently un-enforces it unless both files change. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
…ral reason Finding 1: Replace internal task number reference with durable condition. Status now says enablement is pending repository owner approval, not Task 5. Finding 2: Rewrite section to resolve contradiction with status. Clarify that the original reason for deferral (no checks) is now resolved. State that the remaining gate is owner approval, not missing prerequisites. Confirm that main is protected by process until enablement, and codex exec review remains the operative control. Rename section from "Why it is deferred" to "Enablement is pending repository owner approval" to reflect current state. Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Fix A: drop the codex/** push trigger. A codex/* branch with an open PR fired both push and pull_request events; the concurrency group keys on github.ref, which differs between the two, so it never deduplicated. gh pr checks 4 showed twelve entries for six jobs, with dependency-review reporting fail and skipping simultaneously. pull_request now covers CI on every push to this branch since PR #4 is open. Fix B: bump actions/checkout v4->v7, actions/setup-node v4->v7, actions/setup-dotnet v4->v6, actions/upload-artifact v4->v7, and actions/dependency-review-action v4->v5 (anchore/sbom-action stays at v0, already current). All were several majors behind and the old majors declare Node 20, which GitHub has deprecated. Verified each bumped action's action.yml at the new tag still accepts every input this workflow passes, unchanged in meaning: setup-dotnet's global-json-file, setup-node's node-version, upload-artifact's name/path/if-no-files-found, checkout's fetch-depth, and dependency-review-action's zero inputs. Fix C: add .github/dependabot.yml for the github-actions ecosystem only, so pinned actions rotting silently (as just happened) gets caught going forward instead of discovered incidentally in an unrelated log. Created the missing "dependencies" label (gh label create) rather than leave the file referencing one that doesn't exist. Fix D: amend the wave design spec's out-of-scope list, which forbade Dependabot version-update config, to mark that exclusion superseded rather than silently contradicting it by adding Fix C. Original rationale kept visible per AGENTS.md's record-superseded-don't-rewrite rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Injun Lee <2006ijlee@gmail.com>
Non-provider patterns and validity checks are GitHub Secret Protection features. The advanced_security field is absent from this repository's security_and_analysis response, so the tier is not provisioned: the API accepts a PATCH with HTTP 200 and changes nothing, and the toggles do not render in settings. The detection gap is covered by C-2's gitleaks job rather than by a native setting, which makes that decision load-bearing rather than redundant. Also records the dependency graph as a fourth settings change the original list missed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Injun Lee <2006ijlee@gmail.com>
…act assertion, docs Applies the controller's adjudicated corrections from the independent Codex review (task-6-report.md): 1. Plan now agrees with the spec: non-provider patterns and validity checks are marked superseded/unavailable in Task 5 and the completion criteria, instead of instructing executors to enable them. Original text preserved as superseded per AGENTS.md. 2. Pin anchore/sbom-action's Syft version explicitly (syft-version: v1.51.0) so the SBOM generator can't drift silently under a pinned action wrapper. 3. The artifact job's "Package and checksum" step now asserts all three publish directories exist and are non-empty before Compress-Archive, throwing (non-zero exit) if not — closing the gap where a partial publish could still be zipped, checksummed, and uploaded green. 4. branch-protection.md's dependency-review description no longer claims licence checking; the action has no allow-licenses/ deny-licenses inputs configured, and choosing a licence policy is a product decision that hasn't been made. 5. Corrects the backwards "silently un-enforces" claim in branch-protection.md, the Wave C spec, and the Wave C plan: GitHub fails closed on a required check that never reports (the PR blocks indefinitely), unlike a job that reports skipped (treated as passing). The job-rename-must-update-both-files rule is unchanged. 6. Moves the spec's misplaced "Availability note" paragraph to after the complete decisions table in §3, instead of splitting the table in two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Injun Lee <2006ijlee@gmail.com>
A fourth occurrence of the fail-open claim survived at line 37, phrased as "silently stops being enforced" rather than "un-enforces", which is why the verification grep passed. GitHub fails closed: an unreported required context blocks every merge rather than silently passing. Also corrects two licence-enforcement overstatements: the plan's required-check template, which would have reintroduced the very wording an earlier fix removed from branch-protection.md, and the troubleshooting table. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Injun Lee <2006ijlee@gmail.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed and why
Stage 0 Wave C — continuous integration. Wave A established governance and records; Wave B created the toolchain pins and the solution's dependency graph; this wave makes both enforceable.
Adds
.github/workflows/ci.ymlwith six jobs, and records their names as the required checks branch protection will gate on.build-and-testplugindocssecret-scandependency-reviewartifact.NET jobs run on Windows because
D-003fixes Windows 11 x64 as the only supported platform and the Stage 0 gate requires a clean Windows build. Jobs that do not touch the build run on Ubuntu.Requirements and decisions satisfied
D-091— the branch-protection ruleset was documented in Wave A and its "Required checks" section left explicitly to be filled in by Wave C. It now names six real, verified-green job names.D-018— the artifact carries a SHA-256 file. This is integrity evidence only. A checksum published on the same channel as the file it describes proves the bytes were not corrupted; it proves nothing about who produced them. Automatic installation requires a signature or signed attestation anchored to a pinned project identity, which arrives at Stage 8. The artifact here is explicitly a development artifact: unsigned, manual-install only.D-003— Windows runners for everything that compiles or tests.Security and privacy effects
This changes the trust surface, in the direction of more enforcement.
secret-scanjob closes that gap. It runs withfetch-depth: 0so a secret introduced and later removed is still caught,--exit-code 1so a finding fails the job rather than being reported and ignored, and--redactso detected values never reach the world-readable log.contents: readthroughout.No secret value appears anywhere in this branch. The gitleaks scan over full history is clean.
Verification
The workflow is green on this branch's head commit, with all five push-applicable jobs passing and
dependency-reviewcorrectly skipped on a push event (the action only operates on a pull-request diff).Runtime execution found three defects that two careful static reviews could not. Both reviews read the YAML closely and one caught a real bug, but these three were only findable by running it:
push: [main]pluspull_request: [main], so pushing a feature branch triggered nothing at all — it was unverifiable by construction. The push trigger now also matchescodex/**..gitattributesand.editorconfigdisagreed about line endings. The former declaredeol=lffor all text; the latter declaredcrlffor.cs,.csproj,.props, and.targets. Invisible until a formatter ran, then roughly a hundredENDOFLINEerrors..gitattributeswas incomplete and now matches the convention.editorconfigalready established and that.slnalready followed. The only content change was stripping a stray UTF-8 BOM from threeProgram.csfiles — no logic changed.Out-Filewrote CRLF, so the filename field becameopenmemory-dev.zip\randsha256sum -creportedFAILED open or read. The step now writes explicit LF. This is why the plan required downloading the artifact and checking the hash rather than asserting the file exists — a checksum nobody has verified is decoration.A fourth defect was caught by review before it ran: the artifact job's
dotnet publishloop had no exit-code check, and PowerShell does not treat a native command's non-zero exit as terminating. A failure in one project would have let the loop continue,Compress-Archivewould have succeeded on the partial set, and the job would have gone green with a valid checksum over an incomplete package.Checksum round-trip: the artifact was downloaded from the completed run and
sha256sum -creturnedopenmemory-dev.zip: OK.Independent review: every task received a spec-and-quality review, and the completed branch was reviewed by
codex exec.Remaining limitations or deferred work
.github/branch-protection.mdsays so plainly rather than claiming a capability that does not exist.pushmatchingcodex/**andpull_requesttargetingmain, a PR from acodex/*branch fires both events. The concurrency group keys ongithub.ref, which differs between them, so it does not deduplicate. Two runs post identically-named checks against the same commit. This costs Actions minutes and could make required-check resolution ambiguous, which is why check behaviour on a real pull request should be observed before protection is enabled.dependency-reviewis skipped on push events and GitHub treats a skipped required check as passing. That is correct here — the action is meaningless without a pull-request diff — but it is a deliberate choice, not an accident.dotnet formatcovers C# without a new dependency; adding Prettier for one seven-line stub file belongs to Stage 6, when the plugin is real.D-018andF-007..github/branch-protection.mdstill reads as a forward reference to a milestone now effectively passed. Left for whichever change next touches that document.git commit -s), per the Developer Certificate of Origin.