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
11 changes: 5 additions & 6 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,12 @@ are in the `master` branch protection rule alongside `cert-gate` (see above).
### Faster multi-PR merges (process + optional admin)

`strict: true` makes every merge leave every other open PR BEHIND, so a fan-out of
readiness-touching PRs pays the heavy matrix once per tip. Prefer:
readiness-touching PRs pays the heavy matrix once per tip update. Prefer:

1. **Stack** core-path series (each PR’s base is the previous tip) so CI runs once.
2. **Split** the queue: land non-`READINESS_PATHS` PRs first (~1 min Readiness), then one stack.
3. **One settled tip** before waiting — conflicts, knowledge-graph regen, PR-body tokens — every
`synchronize` restarts the matrix.
4. **Squash-merge into `master`** unless history must be preserved (SPEC series may use merge commits).
1. **Split** the queue: land non-`READINESS_PATHS` PRs first (~1 min Readiness).
2. **One settled tip** before waiting — conflicts, knowledge-graph regen, PR-body tokens — every
`synchronize` restarts the matrix (~30–40 min when core paths changed).
3. **Squash-merge into `master`** by default.

**Merge queue (admin):** the readiness `changes` job already handles `merge_group`. Enabling a
GitHub merge queue on `master` (Settings → Rules → Ruleset / merge queue, require the same five
Expand Down
23 changes: 15 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,21 @@ the version on nuget.org, which is why it trails `VERSION` between releases rath

### Added

- **CI: Full Platform Readiness no longer push-triggers on `cursor/**`.** Branch protection uses the PR
`Readiness summary` check; tip pushes on agent branches had been starting a second heavy matrix. Also:
`scripts/knowledge-graph/resolve-rebase-conflict.sh` for mid-rebase KG conflicts, two shell-lint gates that pin
the push-branch list and the helper, and a more race-tolerant `doctor-container-truthful` UAT probe.

- **SPEC-007 PR 4.5: subject producers, still report-only.** The self-extend runner enters `agent:<id>` at
`SystemHigh` around the cycle and the post-cycle admission and auto-share. Egress records for that cycle go from
`no-subject` to `subject:agent:<id>` at `SystemHigh`. Nothing refuses, and no send changes. `ToolCallingAgent`
begins a read around each tool call. Only a tool that implements `IEgressLabelledTool` may report; `RAGTool` is
the only one, and it reports each hit's canonical label, or `Public` when the search read nothing. Any other tool,
and a tool that throws, counts as `SystemHigh`. A `peer:` chat response is observed as `SystemHigh` after it
returns. A model response is not a read. An open read still counts only when the scope ends, which is a known
limit when a runner's floor is below `SystemHigh` (the owner can reverse it). The labelled-tool marker is recorded
in `PublicAPI.Unshipped.txt`.
returns. A model response is not a read. An open read still counts only when the scope ends (PR 4.4 rule); the
owner decided on 2026-10-06 that an open unreported scope should decide at `SystemHigh` (Scenario B →
`SystemHighData`) — not yet implemented, tracked in PR 4.5b. The labelled-tool marker is recorded in
`PublicAPI.Unshipped.txt`.

- **`Ashlar.Abstractions.Security`: Bell-LaPadula security labels and reference-monitor decisions.**
`SecurityLevel` orders `Public < Internal < Confidential < Secret < TopSecret`, with the names and
Expand Down Expand Up @@ -169,10 +175,10 @@ the version on nuget.org, which is why it trails `VERSION` between releases rath
subject; a task, timer, registration or continuation the publisher created and the callback starts
or triggers keeps the publisher's frame, since each captures the flow where it is created, and a
thread or `System.Timers.Timer` the callback created and the publisher starts runs in the
publisher's frame, since it captures the flow where it is started. Still report-only, and no production code enters a frame
or begins a read yet, so no recorded decision changes; the agent producers come in PR 4.5. The new
public API is in `src/Ashlar.Abstractions/PublicAPI.Unshipped.txt`, and the behaviour is pinned by
cert-gate tests listed in `ci/cert-gate-assertions.md`.
publisher's frame, since it captures the flow where it is started. Still report-only. Until PR 4.5
no production code entered a frame or began a read, so no recorded decision changed then; the agent
producers are in PR 4.5. The new public API is in `src/Ashlar.Abstractions/PublicAPI.Unshipped.txt`,
and the behaviour is pinned by cert-gate tests listed in `ci/cert-gate-assertions.md`.
- **A Claude Code cloud session sets docker up by itself.** A new SessionStart hook,
`.claude/hooks/session-start.sh` (registered in `.claude/settings.json`), runs only when
`CLAUDE_CODE_REMOTE=true`: it starts `dockerd` if it is not running, writes a session-local
Expand Down Expand Up @@ -236,7 +242,8 @@ the version on nuget.org, which is why it trails `VERSION` between releases rath
- MCP over HTTP fails boot on SecureWorkstation. Stdio still boots. AirGapped still refuses an enabled MCP
server. Hosts select HTTP with `WithAshlarHttpTransport` (it registers the marker, then `WithHttpTransport`).
- On AirGapped and SecureWorkstation, API urls (`ASPNETCORE_URLS` and `Kestrel:Endpoints:*:Url`) and mesh serve
must bind loopback or boot fails. `127.0.0.1`, `localhost` and `::1` succeed; `0.0.0.0`, `+` and `*` fail.
must bind loopback or boot fails. `127.0.0.1`, `localhost` and `[::1]` succeed (bare `::1` is refused by
URI parsing); `0.0.0.0`, `+` and `*` fail.
An empty url list is the host default and is allowed. Mesh serve reads optional `ASHLAR_MESH_SERVE_BIND`;
unset on these profiles is any-interface and fails boot rather than being rewritten.

Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Read automatically by Claude Code at the start of every session in this reposito
- **Five required checks**, with `strict` and `enforce_admins` on master: `cert-gate`, `build-core`,
`shell-lint`, `lychee (README + docs)`, `Readiness summary`. Every merge makes every other open PR
BEHIND, so merges are serial; a day-one red blocks every PR in the repository. For multi-PR
sweeps: stack readiness-touching series (base = previous tip), land non-core-path PRs first, push
one settled tip then wait. Full Platform Readiness does **not** push-trigger on `cursor/**` (PR
only) — see `CONTRIBUTING.md` ("Landing several PRs…").
sweeps: land non-core-path PRs first, push one settled tip then wait (every tip update restarts
Readiness). Full Platform Readiness does **not** push-trigger on `cursor/**` (PR only) — see
`CONTRIBUTING.md` ("Landing several PRs…").
- `shell-lint` runs `scripts/ci/run-repo-gates.sh`, which **auto-discovers** `tests/scripts/*.test.sh`,
`scripts/ci/test-*.{sh,py}`, `scripts/ci/verify-*.{sh,py}` and
`scripts/knowledge-graph/verify-*-current.py` and runs each one **bare**, with no arguments. A script
Expand Down
21 changes: 11 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@ These five checks run on every PR and always report a status, so they are safe a
- Branch from the latest `master`, keep branches short-lived (days, not weeks), one concern per branch.
- Name branches `<type>/<topic>` using the same types as Conventional Commits: `feat/…`, `fix/…`, `docs/…`, `chore/…`, `ci/…`, `refactor/…`, `test/…`. For multi-PR efforts, put the epic name at the front of the topic so related branches sort together: `feat/trust-loop-hot-swap`, `feat/trust-loop-fence-probe`. Do **not** name a head branch `application/*` when it targets `master` (the layer-boundary gate rejects that pairing).
- Everything lands through a PR into `master`. Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/) **by convention** — `type(scope): subject`, WHY in the body — there is no commitlint hook or workflow enforcing it; `scripts/changelog-snippet-for-release.sh` relies on the convention to draft release notes. Merged head branches are deleted automatically.
- **Merge into `master` with squash** unless a series needs preserved merge commits. Prefer one method per sweep so rebases stay boring.
- **Merge into `master` with squash** by default. Prefer one method per sweep so rebases stay boring.

### Landing several PRs without paying Readiness N times

Branch protection is `strict` (must be up to date with `master`) and `enforce_admins`, so each
merge makes every other open PR BEHIND and forces another CI cycle. The expensive part is usually
the Full Platform Readiness heavy lanes (~40 minutes when a core path changed), not `cert-gate`.

1. **Stack core-path series.** For SPEC / kernel / hosting / CLI work, open PRs as a chain: PR N+1’s
base is PR N’s head branch (not `master`). CI runs on the tip once; merges become fast-forwards
or cheap updates instead of N full readiness matrices.
2. **Split by cost.** Merge PRs that do not touch readiness core paths first (`Readiness summary`
passes in ~1 minute). Save readiness-touching work for one stacked series.
3. **Push once, then wait.** Resolve conflicts, regenerate `docs/knowledge-graph.{json,md}`
the Full Platform Readiness heavy lanes (~30–40 minutes when a core path changed), not `cert-gate`.
With `strict`, updating a tip onto the post-merge `master` re-fires the matrix — stacking alone does
not skip that cost.

1. **Split by cost.** Merge PRs that do not touch readiness core paths first (`Readiness summary`
passes in ~1 minute). Save readiness-touching work for later in the sweep.
2. **Push once, then wait.** Resolve conflicts, regenerate `docs/knowledge-graph.{json,md}`
(`scripts/knowledge-graph/resolve-rebase-conflict.sh` during a rebase), settle PR-body tokens
(`[coordinated-integration]`, `[skip-prod-style]`), then one push. Every tip update restarts the
platform matrix.
4. **Do not expect a second readiness run on `cursor/**` pushes.** Branch protection uses the PR
3. **Do not expect a second readiness run on `cursor/**` pushes.** Branch protection uses the PR
check; the workflow’s `push:` trigger is `master`/`main` only so agent tips do not double-fire.
4. **Optional: merge queue (admin).** A GitHub merge queue on `master` rebases and re-checks once per
entry; the readiness `changes` job already handles `merge_group`.
- Spikes that should not merge get an `archive/spike-<name>` tag on their tip, then the branch is deleted — the work stays reachable without cluttering the branch list.
- Releases are tags on `master`: bump `VERSION`, move the `[Unreleased]` notes in `CHANGELOG.md` under the new version heading, tag `vX.Y.Z`, and publish a GitHub Release (`scripts/changelog-snippet-for-release.sh` drafts the notes). Release branches (`release/x.y`) only appear if an old version ever needs long-term patch support.

Expand Down
Loading
Loading