docs(trekresearch): split the Independence crossing's two risks and name the right control for each
The Phase 4.5 amendment to the Independence hard rule crosses that rule
deliberately, and the crossing is defensible: bounded to Phase 4.5 and the
Phase 5 loop, the initial swarm stays blind, and it resolves a tension the
brief created itself by asking for exactly this mining of Phase-4 output.
The defect was the compensating-control claim. query-privacy-gate.mjs was
named as THE control for the crossing, but it inspects outbound query
CONTENT for paths, repo identifiers and secret-shaped strings. It cannot
prevent a local finding from steering an external agent's question. It
compensates the EGRESS risk; the BIAS risk was left with no control while
the text read as though it had one.
Both risks are now stated separately with the control that actually bears on
each:
Bias - structural, not a gate. The initial external swarm stays blind, so
an independent baseline exists BEFORE anything crosses; the
crossing only ADDS to that baseline; and at effort: high - the only
effort at which any of this runs - contrarian-researcher is forced
always-on, so the brief always carries an adversarial
counter-evidence pass over the result the crossed queries fed.
Egress - query-privacy-gate.mjs, unchanged, with its non-overridable
hard-block tier.
Fixed at both sites: the Hard rules entry and the Phase 4.5 paragraph that
repeated the same attribution.
A doc-consistency pin now fails if the amendment names the privacy gate as
the compensating control again, and requires it to name both
contrarian-researcher and the egress framing - so the two cannot quietly
re-merge.
Review finding 4888ae847240142933469d70bafb6a9c23b7b2eb (MINOR).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuGhWAbWyRFBFeemfhxoVv
This commit is contained in:
parent
7dc0add768
commit
5f88385d2f
2 changed files with 62 additions and 9 deletions
|
|
@ -449,8 +449,12 @@ agent surfaced that no interview dimension claims.
|
|||
|
||||
Every outbound query generated from a discovered dimension passes
|
||||
`query-privacy-gate.mjs` before it leaves the machine — see the per-turn
|
||||
protocol in Phase 5. That gate is the compensating control for the
|
||||
Independence crossing this phase makes (see Hard rules → Independence).
|
||||
protocol in Phase 5. That gate controls the **egress** risk this phase's
|
||||
Independence crossing creates: local paths and identifiers travelling inside a
|
||||
query. It does **not** control the **bias** risk — it inspects query content and
|
||||
cannot stop a local finding from steering an external agent's question. The bias
|
||||
controls are structural (blind initial swarm, append-only crossing, unconditional
|
||||
`contrarian-researcher` at `effort: high`); see Hard rules → Independence.
|
||||
|
||||
## Phase 5 — Targeted follow-ups
|
||||
|
||||
|
|
@ -895,13 +899,29 @@ Low effort: inline research only, no agent swarm (existing
|
|||
**Amended (v5.10) for Phase 4.5:** dimension discovery deliberately crosses this
|
||||
rule. Its candidate dimensions are mined from the Phase-4 result set, which
|
||||
contains output from the five local codebase agents, so a discovered dimension
|
||||
can carry local context into an external query. The crossing is bounded to
|
||||
Phase 4.5 and the Phase 5 loop it feeds, it never applies to the initial
|
||||
external swarm (which stays blind to local findings), and the compensating
|
||||
control is `query-privacy-gate.mjs`: every outbound query is inspected before
|
||||
it leaves the machine, with a hard-block tier for secret-shaped strings that no
|
||||
operator flag can override. Triangulation still happens AFTER independent
|
||||
research.
|
||||
can carry local context into an external query.
|
||||
|
||||
The crossing creates **two distinct risks**, and they do not share a control:
|
||||
|
||||
- **Bias** — a local finding shapes what an external agent is asked. Its
|
||||
controls are structural, not a gate: the initial external swarm stays blind
|
||||
to local findings, so an **independent baseline already exists** before
|
||||
anything crosses; the crossing is confined to Phase 4.5 and the Phase 5 loop
|
||||
it feeds, which only ADD to that baseline and never revise it; and at
|
||||
`effort: high` — the only effort at which any of this runs —
|
||||
`contrarian-researcher` is forced always-on, so the brief always carries an
|
||||
adversarial counter-evidence pass over the result the crossed queries fed.
|
||||
Triangulation still happens AFTER independent research.
|
||||
- **Egress** — local paths, repo identifiers or secret-shaped strings leave the
|
||||
machine inside a query. That is what `query-privacy-gate.mjs` controls: every
|
||||
outbound query is inspected before it leaves, with a hard-block tier for
|
||||
secret-shaped strings that no operator flag can override.
|
||||
|
||||
The privacy gate was previously named as the compensating control for the
|
||||
crossing as a whole. It is not: it inspects query CONTENT and cannot stop a
|
||||
local finding from steering an external agent's question. Attributing the bias
|
||||
risk to it left that risk with no control while the text read as though it had
|
||||
one.
|
||||
- **Graceful degradation:** If MCP tools are unavailable (Tavily, Gemini, MS Learn),
|
||||
proceed with available tools and note limitations in brief metadata.
|
||||
- **Cost:** Model resolution at Agent-spawn sites is a three-layer fallback:
|
||||
|
|
|
|||
|
|
@ -1194,6 +1194,39 @@ test('STORM: README research-dimension prose stays at the existing 3–8 ceiling
|
|||
);
|
||||
});
|
||||
|
||||
// The Phase 4.5 amendment to the Independence hard rule crosses that rule
|
||||
// deliberately: discovered dimensions are mined from Phase-4 output, which holds
|
||||
// local-agent findings, so a discovered dimension can steer an external query.
|
||||
// The crossing is defensible — bounded, disclosed, and resolving a tension the
|
||||
// brief created itself. What was not defensible was naming query-privacy-gate.mjs
|
||||
// as its compensating control: that gate inspects outbound query CONTENT for
|
||||
// paths, repo identifiers and secret-shaped strings. It compensates the EGRESS
|
||||
// risk the crossing creates. It cannot stop a local finding from shaping an
|
||||
// external agent's question, so the bias risk was left with no named control
|
||||
// while the text read as though it had one.
|
||||
test('STORM: the Independence amendment does not name the privacy gate as the BIAS control', () => {
|
||||
const t = read('commands/trekresearch.md');
|
||||
const amendment = t.slice(t.indexOf('**Independence:**'), t.indexOf('**Graceful degradation:**'));
|
||||
assert.ok(amendment.length > 100, 'the Independence hard rule and its amendment must still be present');
|
||||
assert.ok(
|
||||
!/compensating\s+control\s+is\s+`query-privacy-gate/.test(amendment),
|
||||
'query-privacy-gate.mjs compensates egress, not bias — naming it as THE compensating control for the ' +
|
||||
'Independence crossing claims a control the gate cannot provide',
|
||||
);
|
||||
// The bias risk must carry a control that actually bears on bias.
|
||||
assert.match(
|
||||
amendment,
|
||||
/contrarian-researcher/,
|
||||
'the amendment must name the control that does bear on bias — contrarian-researcher runs unconditionally ' +
|
||||
'at effort: high, the only effort at which the crossing happens',
|
||||
);
|
||||
assert.match(
|
||||
amendment,
|
||||
/egress/i,
|
||||
'the privacy gate should still be named, as the control for the egress risk the same crossing creates',
|
||||
);
|
||||
});
|
||||
|
||||
test('STORM: no banned Sonnet-swarm phrase introduced on any STORM surface', () => {
|
||||
const BANNED = [
|
||||
'Sonnet exploration',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue