Skip to content

fix(server): provider spawns drop another harness identity - #108

Merged
donjor merged 2 commits into
hyprwsfrom
t3code/fix-stale-harness-identity
Aug 27, 2026
Merged

fix(server): provider spawns drop another harness identity#108
donjor merged 2 commits into
hyprwsfrom
t3code/fix-stale-harness-identity

Conversation

@donjor-agent

@donjor-agent donjor-agent Bot commented Aug 27, 2026

Copy link
Copy Markdown

A Codex thread spawned by the desktop app inherited the launcher's Claude markers, so tools inside the thread reported Codex work as Claude.

Provider spawns now strip foreign harness identity at the shared environment seam.

  • HARNESS_IDENTITY_ENV registers each provider's markers.
  • ProviderInstanceEnvironment drops what the spawning driver does not own.
  • T3CODE_*, own markers, and credentials survive.
  • tmux scrubbing unchanged.
patched codex child    0 CLAUDE* vars
unpatched installed    12 CLAUDE* vars

Seven tests: foreign-strip, own-kind, T3CODE_*, tmux.

Closes #98

🤖 claude/anthropic claude-opus-5 (high) · claude-code

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes
Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes
@donjor
donjor merged commit b7e34c5 into hyprws Aug 27, 2026
6 checks passed
@donjor
donjor deleted the t3code/fix-stale-harness-identity branch August 27, 2026 05:52
donjor added a commit that referenced this pull request Aug 27, 2026
A fork issue, comment, or pull-request body that writes a live upstream
reference makes GitHub post a backlink on that upstream thread, from the
fork's bot account. The fork does not file upstream, so the event is noise
on somebody else's issue.

`vp run fork:upstream-refs <file>` reads a body from a file or stdin, blanks
fenced blocks, indented code, code spans, and HTML comments at their original
offsets, and exits 1 with the line and column of anything left live. A bare
`pingdotgg#4379` counts: GitHub resolves a number this fork has never issued against
the repository it was forked from, so the plainest-looking citation is the
one that reaches upstream without naming it. Writing a fork reference as
`#108` clears the guard and still renders `#108`.
An upstream URL that names no item is not a finding.

Inline pairing splits on every block start that ends a paragraph, so a
backtick run cannot reach across a heading, a thematic break, a table cell,
an HTML block, or a deeper blockquote to mask a citation between them. Each
rule was checked in both directions against GitHub's own Markdown renderer.

The pre-publication run is the gate: GitHub posts the backlink when the item
is created, so nothing that reacts afterwards can withdraw it. Fork CI
re-runs the guard on every pull-request body as a backstop and says so.
`docs/internals/scripts.md` records what stays unguarded, including issue
bodies, comments, titles, and the parts of CommonMark the reader skips.

Fork-Domain: fork-meta
Fork-Tier: qol
donjor added a commit that referenced this pull request Aug 27, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 27, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 28, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Aug 28, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 28, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 29, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Aug 29, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 29, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 30, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Aug 30, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 30, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 30, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Aug 30, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 30, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 30, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Aug 30, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Aug 30, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Sep 2, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Sep 2, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Sep 2, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
* fix(server): provider spawns drop another harness's identity

A provider subprocess inherited the app launcher's harness markers, so a
Codex thread started from a Claude-launched T3 Code carried `CLAUDECODE`
and `CLAUDE_CODE_SESSION_ID`, and tooling inside the thread attributed
Codex work to Claude.

`mergeProviderInstanceEnvironment` now takes the target driver kind and
removes every other provider's identity variables, keeping credentials
and `T3CODE_*` session identity. The two seams that recompose the child
environment from `process.env` scrub the same way, so a complete driver
environment cannot be undone by the spawner.

Closes #98

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

* refactor(server): cursor probe reuses the cursor driver kind constant

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes

---------

Co-authored-by: donjor <donjordev@gmail.com>
donjor added a commit that referenced this pull request Sep 2, 2026
A fork issue or comment that wrote a live `pingdotgg/t3code#N` or a bare upstream URL made GitHub post a "mentioned this" event on the upstream thread, from our bot. The rule is now stated and enforced: wrap the citation in a code span, or paste the survey in a fence.

`vp run fork:upstream-refs` masks HTML comments, fenced blocks, and code spans at their original offsets, then refuses any live upstream issue, pull request, commit, or discussion reference left outside them, reporting line and column for each.

A bare `#N` is a finding too. GitHub resolves a number this fork has never issued against the repository it was forked from: `pingdotgg#5779` in a fork body links to `pingdotgg/issues/5779` and posts the backlink there. The guard has no network, so it cannot ask which numbers the fork holds and reports every bare number. Writing the fork item in full as `#108` clears it and still renders as `#108`.

```text
$ vp run fork:upstream-refs body.md
1:22 pingdotgg#4379 (cross-repo issue reference)
1:48 pingdotgg#4402 (upstream item URL)
3:11 #107 (bare item number, resolved upstream when this fork has no such item)
failed: 3 live upstream reference(s) in body.md; wrap each one in a code span or a fenced block so GitHub does not post a backlink on the pingdotgg/t3code thread, or write a bare number that names a fork item as RSI-Software/t3code-hyprws#N, which renders the same (docs/internals/fork-development.md)
```

Masking holds against the cases that make a naive scanner lie: indented and blockquoted fences, backtick runs that would otherwise pair across paragraphs, and emoji shifting every column after them. Item URLs no longer over-match `/issues/new` or `/discussions/categories/ideas`, which the fork's own `README.md` and `CONTRIBUTING.md` carry.

`AGENTS.md` and the fork guide carry the code-span form and the reason. Fork CI runs the guard on every pull-request body as a post-publication backstop, before the ledger step so a ledger failure cannot hide it.

A scan of the whole fork estate, 120 item bodies plus 95 comments plus 1 review, found zero live cross-repo, URL, commit, or discussion references. It is not a vacuous pass: the items that mention upstream carry their citations inside a fence or code span already.

The bare-number rule is preventive, and it is not free. The same scan reports 94 bare numbers across 47 surfaces. Every one of them names a number this fork holds today, so none has ever posted upstream; they are unqualified references that would resolve upstream the moment a fork body cited a number the fork does not own. Existing bodies are not being rewritten. New prose qualifies its references, and this pull request's own body does.

Refs #107

The refusal condition is not met by this PR. CI reads a body GitHub already published, and issue bodies and comments have no trigger at all, so the guard catches a live reference after the backlink exists. The pre-publication gate belongs in the `ghb` publish path, which runs the guard on the body file before posting; that is fork tooling a sibling change owns. The two stated-rule and clean-scan conditions are met here.

One residual, out of scope here: `docs/internals/t3-connect.md` carries `(pingdotgg#5051)` in prose inherited from upstream. It is a true positive that the guard never reads, because the guard scans GitHub bodies and not the tracked tree.

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
donjor added a commit that referenced this pull request Sep 2, 2026
Every rebase report now marks retire candidates per fork commit, and the fork ledger records each retire, keep, or partial decision by commit subject so the next tag does not re-ask.

before: retirement was a note in a rehearsal record; nothing in the stack or the report carried it forward.

now, `vp run fork:rebase-report --target upstream/main` (1.1 s):

```text
## Retire candidates

| Fork commit | Domain | Tier | Signals | Decision |
| --- | --- | --- | --- | --- |
| 792f80d refactor(web): add physical project sidebar scope | project-windows | core | `behaviour-overlap`: weak hunk overlap: apps/web/src/components/Sidebar.logic.ts@3~6 | candidate |
| b7e34c5 fix(server): provider spawns drop another harness identity (#108) | upstream-fixes | bugfix | `behaviour-overlap`: weak hunk overlap: apps/server/src/provider/Drivers/GrokDriver.ts@92~91, apps/server/src/provider/acp/Gro
```

`vp run fork:delta --check` on this head:

```text
ok: 68 fork commits tagged
```

**Mechanism**

- `scripts/lib/fork-rebase-feasibility.ts` and `scripts/fork-rebase-report.ts`: schema v3 adds `retireCandidates`, one entry per fork commit with read-only signals. `already-upstream` means the commit applies in reverse cleanly on the target; `behaviour-overlap` is `hard` on a same-hunk conflict and `weak` when a fork hunk sits within three lines of an upstream hunk on the same file. Same-file-only overlap is not a candidate.
- `scripts/lib/fork-retirement-ledger.ts`: parses the `Retired` and `Kept` tables in `docs/internals/fork-delta.md`; a subject in both is a partial decision.
- `scripts/fork-delta.ts`: listings omit retired subjects; `--check` exits 1 with `retired but present` while a retired subject is still in the stack.
- `docs/internals/fork-delta.md`: the two ledger tables, seeded empty, with the retirement outcomes paragraph. Upstream replacements are code-spanned, never live.

**Tests**

- finds conflict commit N, attributes files and counts conflict hunks and overlap
- renders a recorded keep as kept instead of a fresh candidate
- skips retired subjects from listings and makes --check fail while one is present
- keeps a partial subject active when its retired and kept portions are both recorded

Closes #101

Model: gpt-5.6-sol (worker), claude fable (host)
Harness: Pi peer-worker driven from Claude Code in T3 Code

Fork-Domain: fork-meta
Fork-Tier: qol
Co-authored-by: donjor <38745786+donjor@users.noreply.github.com>
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.

[📥] Provider threads inherit stale harness identity from the app launcher

1 participant