Skip to content

docs(plans): the git probe's security contract, ahead of the code (DRC-4274) - #238

Merged
gcko merged 4 commits into
mainfrom
spacedock-ensign/drc-4274
Aug 28, 2026
Merged

docs(plans): the git probe's security contract, ahead of the code (DRC-4274)#238
gcko merged 4 commits into
mainfrom
spacedock-ensign/drc-4274

Conversation

@gcko

@gcko gcko commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Implements DRC-4274 — Git probe groundwork · SECURITY.md scope section for the end-of-session git probe

Documentation only. One new file, docs/plans/git-probe-security-scope.md, holding the SECURITY.md section for the end-of-session git probe verbatim, ahead of the code that implements it.

DEC-3 (DRC-4122) puts the security amendment before any code, as DEC-1's and DEC-2's were. That shape keeps SECURITY.md describing only shipped behaviour at every commit: a standalone SECURITY.md PR would leave the file documenting a probe that does not exist for the whole window between the two merges, and releases here are cut from main by tag, so that window is real rather than theoretical. Both precedents were traced by commit at both ends — the plan doc added in its own PR (7134a01 in #71, 5ede7d1 in #143), then promoted and deleted in a98bc64 and 3e92d12. DRC-4037 promotes this section into SECURITY.md unchanged and deletes the file.

The section bounds the probe to exactly git -c core.fsmonitor= --no-optional-locks status --porcelain, records that the mechanism is subprocess execution rather than a file open with both flags load-bearing, publishes {dirty: bool | None, changed: int | None} with null meaning not probed and changed counting porcelain entries rather than files, states what is never read, bounds the cadence to session_ended, and specifies --no-git reaching the daemon respawn path.

It also carries an intro-amendment section, which the issue did not originally ask for. Scope's violation sentence enumerates file reads, harness-store writes and network destinations; this probe is subprocess execution, so without naming the two sentences that change, the promoted section would land under a clause that does not reach it. The quota precedent handled exactly this the same way.

Verification

Prose-only diff, so the documented short path in AGENTS.md § Pre-PR Checks applies: validate_plugins.py is the check that matters. That was derived rather than assumed — the CI changes job builds its deny-list by grepping double-quoted "docs/*.md" literals out of the test tree, that list has exactly one entry today (docs/plans/event-driven-session-observation.md), and a file that does not yet exist cannot be in it. Expect code=false, the five measurable jobs skipped, and validate plus version-guard green.

  • python3 scripts/validate_plugins.pyexit 0.
  • The validator was falsified against this exact file, not assumed to cover it. Injecting one unresolvable relative link and one unresolvable heading anchor produced exactly two errors and exit 1, naming docs/plans/git-probe-security-scope.md in both; restoring the file returned exit 0. docs/plans/ is reached through (ROOT / "docs").rglob("*.md") at scripts/validate_plugins.py:1209, a recursive glob rather than a path literal, which is why grepping the script for "plans" finds nothing.
  • No version field moved. git diff $(git merge-base origin/main HEAD)..HEAD -- '*plugin.json' '*marketplace.json' '*gemini-extension.json' | grep -E '^[+-].*"version"' returns nothing. python3 scripts/bump_version.py --current reports 0.18.0.
  • Surface: 1 file, 103 lines added, 0 removed, against a declared estimate of 110 ± 30. Inside tolerance. The diff touches exactly one path, which is what keeps the CI detector on code=false.
  • sync-docs invoked. It was not a no-op: the tone standard bans em dashes in docs/plans/*.md and both promotion precedents carry zero, while the first draft had four. Fixed in 1e4114a, shape only. AGENTS.md's doc map already covers docs/plans/*.md as a glob, so no new row is owed. The docs-synced-through marker is deliberately left alone: sibling worktrees are live and that marker is stamped once from main after the merges.
  • The diff was reviewed in the worktree before this PR opened, which caught four things CI cannot see (9d9059f): the cadence bound said "session-ended edge" in prose where DRC-4037 needs the session_ended identifier; a six-harness name list was dropped because it would go stale inside a verbatim-promoted SECURITY.md; "separates this read" contradicted the sentence establishing the mechanism as execution; and "already" claimed a document order that will not hold, since the cwd rule sits later in SECURITY.md than this section will.

No test is written, and that is deliberate rather than an omission. AC1's falsifier is scripts/validate_plugins.py, a shipped check demonstrated above failing on this file's own injected defects. A test that grepped this document for its own sentences would assert only that the file contains what we put in it.

The full unittest suite was deliberately not run. It measures nothing a prose-only change can affect, and several sibling worktrees are live — AGENTS.md § Parallel Work records that concurrent suites here manufacture failures in test_http_api, test_page, test_lifecycle and test_quota that read as regressions.

🤖 Generated with Claude Code

gcko added 3 commits August 28, 2026 16:06
…C-4274)

DEC-3 (DRC-4122) puts the SECURITY.md amendment before any code, as DEC-1's
and DEC-2's were. Drafting the section here keeps SECURITY.md describing only
shipped behaviour: a standalone SECURITY.md PR would leave the file documenting
a probe that does not exist for the whole window between the two merges, and
releases here are cut from main by tag.

Carries the intro-amendment section the quota precedent used. Scope's violation
sentence enumerates file reads, harness-store writes and network destinations;
this probe is subprocess execution, so without naming the sentence that changes
the promoted section would land under a clause that does not reach it.

DRC-4037 promotes the section into SECURITY.md unchanged and deletes this file.

Signed-off-by: Jared Scott <jared.scott@variable.team>
The tone standard in the sync-docs skill bans em dashes in docs/plans/*.md,
and both promotion precedents carry zero. Shape only: no fact added, removed
or reworded.

Signed-off-by: Jared Scott <jared.scott@variable.team>
Pre-PR review of the diff in the worktree. Four corrections:

- The cadence bound said "session-ended edge" in prose. DRC-4037 has to hook
  an identifier, so the contract names `session_ended`.
- The harness list behind the null rationale is dropped. The count and the
  reason carry the contract; six names would go stale in a SECURITY.md the
  moment an adapter lands.
- "separates this read" contradicted the sentence establishing the mechanism
  as execution rather than a read.
- The cwd rule sits later in SECURITY.md than this section will, so "already"
  claimed an order that will not hold.

Signed-off-by: Jared Scott <jared.scott@variable.team>
gcko added a commit that referenced this pull request Aug 28, 2026
The prior wording said six of ten harnesses can never emit `session_ended`.
Literally true and misleading: only two mappings in event_hook.py produce
`session_ended` (lines 82 and 200), CODEX_EVENTS carries no SessionEnd,
codex-hooks.json registers none, and agy_hook.py emits only store_changed.
Eight rows can never be probed, not four.

A bare corrected count would go stale the moment an adapter gains SessionEnd,
and this section is promoted into SECURITY.md unchanged, so state the property
instead: the probe fires on `session_ended`, most harnesses do not emit it
today, those rows carry `null`.

Signed-off-by: Jared Scott <jared.scott@variable.team>
@gcko

gcko commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correction round 1, head 00444a7. One sentence changed, same one path.

The removed wording ("Six of the ten harnesses have no event adapter and can never emit session_ended at all") is literally true and reads false: it implies the other four can be probed. Only two mappings produce session_ended (event_hook.py:82 and :200); CODEX_EVENTS carries no SessionEnd, cargento/hooks/codex-hooks.json registers none, and agy_hook.py emits only store_changed. Eight of ten rows can never be probed, not four.

A corrected count would go stale the first time an adapter gains SessionEnd, and this section is promoted into SECURITY.md verbatim, so the replacement states the property instead: the probe fires on session_ended, most harnesses do not emit it today, those rows carry null. Same conservative direction, no maintained number.

Verification on the new head: python3 scripts/validate_plugins.py exit 0; the version-field grep over merge-base..HEAD returns nothing; sync-docs re-run produced no further change, with its tone check (a, c, e; b already covered, d not applicable) clean; quality-gate, validate and version-guard green, the five measurable jobs skipped, so the detector still reads code=false.

One stale figure in the body above, left deliberately: the surface line says 103 lines added. The reflow of that paragraph makes it 102. The correction was scoped to the one sentence and the body was out of scope for it.

@gcko
gcko merged commit 701b7f0 into main Aug 28, 2026
9 checks passed
@gcko
gcko deleted the spacedock-ensign/drc-4274 branch August 28, 2026 08:52
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