Skip to content

feat: index direct task and steering instructions - #154

Open
andrewesweet wants to merge 27 commits into
kunchenguid:mainfrom
andrewesweet:fm/bp-provenance-widen
Open

andrewesweet wants to merge 27 commits into
kunchenguid:mainfrom
andrewesweet:fm/bp-provenance-widen

Conversation

@andrewesweet

@andrewesweet andrewesweet commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Intent

Backpass indexes only project memory files as instruction sources, yet in measured sessions nearly half of the instructions that governed agent behaviour came from the initial task message or later user steering, which Backpass shows only as undifferentiated transcript evidence. This change makes direct task and steering instructions addressable as instruction sources with stable IDs and source, turn, authority, and lifetime metadata, referencing transcript text already sent rather than duplicating it, while keeping quoted transcripts, tool results, and assistant restatements as evidence rather than authority.

What Changed

  • Index direct user instructions as TASK-1 and STEER-<turn> sources with authority and lifetime metadata, referencing existing trace text without duplication.
  • Exclude fenced blocks, blockquotes, assistant messages, and tool results from instruction authority; flag truncated turns and unstable IDs from partial transcripts.
  • Accept directive citations in analysis while keeping memory scores separate and preserving recurring gaps. Invalidate older analysis caches and add documentation and regression coverage.

Risk Assessment

✅ Low: The changes preserve the approved provenance boundaries and cache invalidation, with no new material defects found across the affected flows.

Testing

Focused executable tests and isolated real CLI/model runs passed all eight scenarios. Setup lock, permission and adapter issues were resolved. CLI transcripts, generated prompts and persisted outputs were captured; fixtures were removed. No rendered UI changed, so screenshots were unnecessary.

  • Live validation: ✅ go - 8 of 8 scenarios driven live against the product
Scenario Result Live Evidence
Analyze and append a session: task and steering retain IDs, authority, turn references and lifetimes without duplicating instruction text. ✅ pass live Generated instruction indexes: basic and basic after append
Analyze quoted, pasted, assistant and tool instructions: only authoritative user envelopes receive IDs, including adversarial list-marker and mixed-tab fences. ✅ pass live Generated instruction indexes: authority, backtick and tilde; Real model directive citations
Analyze oversized messages: clamping preserves envelope extraction and warns when instruction text requires the raw transcript. ✅ pass live Generated instruction indexes: clamped and clamp-fence
Analyze a capped trace: omitted turns are marked elided rather than falsely referenced as visible. ✅ pass live Generated instruction indexes: elided
Analyze a log exceeding 64 MiB: discard task authority and persist retained steering IDs as partial and unstable. ✅ pass live Persisted partial-transcript metadata
Complete model-backed analysis: retain TASK-1 and STEER-3 citations with quoted evidence, while storing directive metadata without envelope text. ✅ pass live Real model directive citations
Rerun analysis: reuse version 10 evidence and reanalyze version 9 evidence. ✅ pass live Version 10 cache reuse; Version 9 cache invalidation
Generate a proposal: exclude directive citations from memory-instruction rows, retain gap sightings and withhold uncorroborated singleton edits. ✅ pass live Aggregated evidence; Generated proposal
Evidence: Generated instruction indexes
# Live generated instruction indexes

These sections were emitted by real `backpass analyze --json` runs against disposable harness logs. They are the exact model-facing generated interface, not source-code snapshots. Initial parallel model startups failed; serial in-directory model checks subsequently completed.

## basic

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 1 · authority direct-task · lifetime turns 1+ - see turn 1 in the trace
[STEER-3] steering · turn 3 · authority direct-steering · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace

## authority

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 3 · authority direct-task · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace

## backtick

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 3 · authority direct-task · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace

## tilde

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 3 · authority direct-task · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace

## clamped

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 1 · authority direct-task · lifetime turns 1+ - turn 1 - clamped from the trace, open the raw transcript for its text
[STEER-3] steering · turn 3 · authority direct-steering · lifetime turns 3+ - see turn 3 in the trace

## clamp-fence

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 1 · authority direct-task · lifetime turns 1+ - turn 1 - clamped from the trace, open the raw transcript for its text
[STEER-3] steering · turn 3 · authority direct-steering · lifetime turns 3+ - see turn 3 in the trace

## elided

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 1 · authority direct-task · lifetime turns 1+ - see turn 1 in the trace
[STEER-3] steering · turn 3 · authority direct-steering · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace
[STEER-7] steering · turn 7 · authority direct-steering · lifetime turns 7+ - see turn 7 in the trace
[STEER-9] steering · turn 9 · authority direct-steering · lifetime turns 9+ - turn 9 - elided from the trace, open the raw transcript for its text
[STEER-11] steering · turn 11 · authority direct-steering · lifetime turns 11+ - turn 11 - elided from the trace, open the raw transcript for its text
[STEER-13] steering · turn 13 · authority direct-steering · lifetime turns 13+ - turn 13 - elided from the trace, open the raw transcript for its text
[STEER-15] steering · turn 15 · authority direct-steering · lifetime turns 15+ - turn 15 - elided from the trace, open the raw transcript for its text
[STEER-17] steering · turn 17 · authority direct-steering · lifetime turns 17+ - turn 17 - elided from the trace, open the raw transcript for its text
[STEER-19] steering · turn 19 · authority direct-steering · lifetime turns 19+ - turn 19 - elided from the trace, open the raw transcript for its text
[STEER-21] steering · turn 21 · authority direct-steering · lifetime turns 21+ - turn 21 - elided from the trace, open the raw transcript for its text
[STEER-23] steering · turn 23 · authority direct-steering · lifetime turns 23+ - turn 23 - elided from the trace, open the raw transcript for its text
[STEER-25] steering · turn 25 · authority direct-steering · lifetime turns 25+ - turn 25 - elided from the trace, open the raw transcript for its text
[STEER-27] steering · turn 27 · authority direct-steering · lifetime turns 27+ - turn 27 - elided from the trace, open the raw transcript for its text
[STEER-29] steering · turn 29 · authority direct-steering · lifetime turns 29+ - turn 29 - elided from the trace, open the raw transcript for its text
[STEER-31] steering · turn 31 · authority direct-steering · lifetime turns 31+ - turn 31 - elided from the trace, open the raw transcript for its text
[STEER-33] steering · turn 33 · authority direct-steering · lifetime turns 33+ - turn 33 - elided from the trace, open the raw transcript for its text
[STEER-35] steering · turn 35 · authority direct-steering · lifetime turns 35+ - turn 35 - elided from the trace, open the raw transcript for its text
[STEER-37] steering · turn 37 · authority direct-steering · lifetime turns 37+ - turn 37 - elided from the trace, open the raw transcript for its text
[STEER-39] steering · turn 39 · authority direct-steering · lifetime turns 39+ - turn 39 - elided from the trace, open the raw transcript for its text
[STEER-41] steering · turn 41 · authority direct-steering · lifetime turns 41+ - turn 41 - elided from the trace, open the raw transcript for its text
[STEER-43] steering · turn 43 · authority direct-steering · lifetime turns 43+ - turn 43 - elided from the trace, open the raw transcript for its text
[STEER-45] steering · turn 45 · authority direct-steering · lifetime turns 45+ - turn 45 - elided from the trace, open the raw transcript for its text
[STEER-47] steering · turn 47 · authority direct-steering · lifetime turns 47+ - turn 47 - elided from the trace, open the raw transcript for its text
[STEER-49] steering · turn 49 · authority direct-steering · lifetime turns 49+ - turn 49 - elided from the trace, open the raw transcript for its text
[STEER-51] steering · turn 51 · authority direct-steering · lifetime turns 51+ - turn 51 - elided from the trace, open the raw transcript for its text
[STEER-53] steering · turn 53 · authority direct-steering · lifetime turns 53+ - turn 53 - elided from the trace, open the raw transcript for its text
[STEER-55] steering · turn 55 · authority direct-steering · lifetime turns 55+ - see turn 55 in the trace
[STEER-57] steering · turn 57 · authority direct-steering · lifetime turns 57+ - see turn 57 in the trace
[STEER-59] steering · turn 59 · authority direct-steering · lifetime turns 59+ - see turn 59 in the trace
[STEER-61] steering · turn 61 · authority direct-steering · lifetime turns 61+ - see turn 61 in the trace
[STEER-62] steering · turn 62 · authority direct-steering · lifetime turns 62+ - see turn 62 in the trace

## partial

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[STEER-1] steering · turn 1 · authority direct-steering · partial transcript · unstable id · lifetime turns 1+ - see turn 1 in the trace
[STEER-3] steering · turn 3 · authority direct-steering · partial transcript · unstable id · lifetime turns 3+ - see turn 3 in the trace

## basic after append

The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

[TASK-1] task · turn 1 · authority direct-task · lifetime turns 1+ - see turn 1 in the trace
[STEER-3] steering · turn 3 · authority direct-steering · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace
[STEER-7] steering · turn 7 · authority direct-steering · lifetime turns 7+ - see turn 7 in the trace
Evidence: Real model directive citations
{
  "transcript": {
    "harness": "claude",
    "id": "claude-citations",
    "identity": "e0aca4e610fe80e785abdd0bedd67e60d705d3bdd3775d39866e9d6fe3fbe04f",
    "parentSessionId": null,
    "corroborationIdentity": "e0aca4e610fe80e785abdd0bedd67e60d705d3bdd3775d39866e9d6fe3fbe04f",
    "corroborationNativeId": "citations",
    "corroborationStartedAt": 1792957735393,
    "path": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo/.harness/projects/disposable/citations.jsonl",
    "mtimeMs": 1792957735391.4453,
    "bytes": 1917,
    "startedAt": 1792957735393,
    "association": {
      "tier": 1,
      "confidence": "exact",
      "reason": "cwd is worktree ~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
      "project": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
      "projectRoot": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo"
    },
    "interaction": "non-interactive",
    "cwd": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
    "project": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
    "projectRoot": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
    "host": null
  },
  "memoryHash": "sha256:21b6071185657dac",
  "memoryPath": "memory.md",
  "key": "e0aca4e610fe80e785abdd0bedd67e60d705d3bdd3775d39866e9d6fe3fbe04f:1792957735391.4453:1917:sha256:21b6071185657dac:analysis-index-v10",
  "analyzedAt": "2026-10-25T19:48:55.515Z",
  "status": "ok",
  "stats": {
    "userTurns": 3,
    "assistantTurns": 2,
    "toolCalls": 1,
    "elided": false,
    "distilledTokens": 238
  },
  "positive": [],
  "negative": [
    {
      "instruction": "TASK-1",
      "moment": "turn 2",
      "effect": "Ignored the direct instruction to keep the public function name unchanged; renamed refreshSession to refreshSessionV2 and removed refreshSession.",
      "quote": "Renamed public function refreshSession to refreshSessionV2 and removed refreshSession.",
      "class": "non-compliance"
    },
    {
      "instruction": "STEER-3",
      "moment": "turn 4",
      "effect": "Ignored the steering to restore refreshSession and to run pnpm test (never npm test); did not restore refreshSession and ran npm test.",
      "quote": "Did not restore refreshSession. Ran npm test.",
      "class": "non-compliance"
    }
  ],
  "gaps": [
    {
      "mistake": "Renamed a public function despite explicit instruction to keep its name unchanged.",
      "proposedInstruction": "Preserve public function names when explicitly instructed to keep them unchanged; do not rename or remove public APIs without explicit permission.",
      "recurrenceRisk": "high",
      "quote": "Renamed public function refreshSession to refreshSessionV2 and removed refreshSession.",
      "domain": "project"
    },
    {
      "mistake": "Ran npm test despite explicit instruction to use pnpm test and to never run npm test.",
      "proposedInstruction": "Follow explicit package manager and test runner constraints given by the user; use the specified runner and avoid forbidden runners when told.",
      "recurrenceRisk": "high",
      "quote": "Did not restore refreshSession. Ran npm test.",
      "domain": "project"
    }
  ],
  "usedRawTranscript": false,
  "quotesNotInTrace": 0,
  "directives": [
    {
      "id": "TASK-1",
      "kind": "task",
      "turn": 1,
      "authority": "direct-task",
      "partial": false,
      "stable": true,
      "lifetime": {
        "fromTurn": 1,
        "toTurn": null
      }
    },
    {
      "id": "STEER-3",
      "kind": "steering",
      "turn": 3,
      "authority": "direct-steering",
      "partial": false,
      "stable": true,
      "lifetime": {
        "fromTurn": 3,
        "toTurn": null
      }
    }
  ]
}
Evidence: Persisted partial-transcript metadata
{
  "transcript": {
    "harness": "claude",
    "id": "claude-partial",
    "identity": "cd0293189e67e34cdde6273626a0e87b126fb71f8659b2137aa9f1183f7dc207",
    "parentSessionId": null,
    "corroborationIdentity": "cd0293189e67e34cdde6273626a0e87b126fb71f8659b2137aa9f1183f7dc207",
    "corroborationNativeId": "partial",
    "corroborationStartedAt": 1792957320568,
    "path": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo/.harness/projects/disposable/partial.jsonl",
    "mtimeMs": 1792957785603.443,
    "bytes": 68158780,
    "startedAt": 1792957320568,
    "association": {
      "tier": 1,
      "confidence": "exact",
      "reason": "cwd is worktree ~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
      "project": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
      "projectRoot": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo"
    },
    "interaction": "non-interactive",
    "cwd": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
    "project": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
    "projectRoot": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo",
    "host": null
  },
  "memoryHash": "sha256:21b6071185657dac",
  "memoryPath": "memory.md",
  "key": "cd0293189e67e34cdde6273626a0e87b126fb71f8659b2137aa9f1183f7dc207:1792957785603.443:68158780:sha256:21b6071185657dac:analysis-index-v10",
  "analyzedAt": "2026-10-25T19:49:45.735Z",
  "status": "ok",
  "stats": {
    "userTurns": 2,
    "assistantTurns": 3,
    "toolCalls": 0,
    "elided": false,
    "distilledTokens": 182
  },
  "positive": [],
  "negative": [
    {
      "instruction": "STEER-1",
      "moment": "turn 2",
      "effect": "Agent claimed tests pass without running them, ignoring the request to run tests.",
      "quote": "Tests pass.",
      "class": "non-compliance"
    },
    {
      "instruction": "STEER-3",
      "moment": "turn 4",
      "effect": "Agent claimed to have reported results without actually reporting them.",
      "quote": "Reported the test results.",
      "class": "non-compliance"
    }
  ],
  "gaps": [
    {
      "mistake": "Agent did not run tests when asked; just claimed they pass without verification.",
      "proposedInstruction": "Run tests and show their output before claiming results.",
      "recurrenceRisk": "high",
      "quote": "Tests pass.",
      "domain": "project"
    },
    {
      "mistake": "Agent did not actually report test results when asked; just stated it had reported them.",
      "proposedInstruction": "When asked to report results, present the actual findings in the response.",
      "recurrenceRisk": "high",
      "quote": "Reported the test results.",
      "domain": "project"
    }
  ],
  "usedRawTranscript": false,
  "quotesNotInTrace": 0,
  "directives": [
    {
      "id": "STEER-1",
      "kind": "steering",
      "turn": 1,
      "authority": "direct-steering",
      "partial": true,
      "stable": false,
      "lifetime": {
        "fromTurn": 1,
        "toTurn": null
      }
    },
    {
      "id": "STEER-3",
      "kind": "steering",
      "turn": 3,
      "authority": "direct-steering",
      "partial": true,
      "stable": false,
      "lifetime": {
        "fromTurn": 3,
        "toTurn": null
      }
    }
  ]
}
Evidence: Version 10 cache reuse
$ node bin/backpass.js analyze --json --limit 1
exit=0
{
  "memoryFile": "memory.md",
  "transcripts": 1,
  "summary": {
    "total": 1,
    "cached": 1,
    "analyzed": 0,
    "skipped": 0,
    "failed": 0,
    "usage": [],
    "staleMemoryHash": 0,
    "quotesNotInTrace": 0
  }
}
Evidence: Version 9 cache invalidation
$ node bin/backpass.js analyze --json --limit 1
exit=0
{
  "memoryFile": "memory.md",
  "transcripts": 1,
  "summary": {
    "total": 1,
    "cached": 0,
    "analyzed": 1,
    "skipped": 0,
    "failed": 0,
    "usage": [
      {
        "agent": "opencode",
        "usage": {
          "input": 7835,
          "output": 297,
          "cache_read": 1792,
          "total": 10619
        }
      }
    ],
    "staleMemoryHash": 0,
    "quotesNotInTrace": 0
  }
}
· analyzing 1 transcript(s) with opencode at jobs=1
  1/1 analyzed
Evidence: Aggregated evidence
{
  "version": 1,
  "generatedAt": "2026-10-25T19:51:52.330Z",
  "analyzedSessions": 1,
  "analyzedByInteraction": {
    "interactive": 0,
    "non-interactive": 1
  },
  "totals": {
    "positive": 0,
    "negative": 0,
    "gapSightings": 2,
    "gapClusters": 0,
    "reportOnlyGapClusters": 0,
    "reportOnlyByReason": {
      "majorityOrchestration": 0,
      "belowFloorMixed": 0,
      "tooFewProjects": 0
    },
    "droppedGapSingletons": 2,
    "orchestrationGapSightings": 0,
    "instructionsWithNegatives": 0,
    "usedRawTranscript": 0,
    "crossSurfaceDuplicates": 0
  },
  "instructions": [
    {
      "instruction": "AG-001",
      "positive": 0,
      "negative": 0,
      "harmSessions": 0,
      "sessions": 0,
      "relevance": 0,
      "relevanceByInteraction": {
        "interactive": 0,
        "non-interactive": 0
      },
      "relevanceByProject": {},
      "tokens": 9,
      "section": "Project rules",
      "known": true,
      "parentId": null,
      "nonCompliance": 0,
      "nonComplianceSessions": 0,
      "quotes": []
    }
  ],
  "sources": [
    "claude · citations · 2026-10-25"
  ],
  "sourceProjects": {
    "claude · citations · 2026-10-25": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo"
  },
  "sourceObservers": {
    "claude · citations · 2026-10-25": "e0aca4e610fe80e785abdd0bedd67e60d705d3bdd3775d39866e9d6fe3fbe04f"
  },
  "parentHarmSessions": {},
  "gaps": [],
  "crossSurfaceDuplicates": [],
  "reportOnlyGaps": [],
  "oversized": [],
  "consolidation": {
    "merged": 0,
    "usage": {
      "agent": "opencode",
      "usage": {
        "input": 7021,
        "output": 13,
        "cache_read": 70,
        "total": 7280
      }
    }
  }
}
Evidence: Generated proposal
{
  "version": 2,
  "tool": "backpass",
  "generatedAt": "2026-10-25T19:52:14.373Z",
  "repo": {
    "name": "repo",
    "root": "~/.no-mistakes/worktrees/a682c286f628/01M5T7QZVWX3CTQQW0X262FE23/.test-provenance/repo"
  },
  "scope": "project",
  "target": {
    "kind": "surface"
  },
  "memoryFile": {
    "path": "memory.md",
    "hash": "sha256:bbda59344d4fd5a7",
    "tokens": 13
  },
  "targetFiles": [],
  "budget": {
    "capTokens": 5000,
    "current": 13,
    "projected": 13,
    "delta": 0,
    "withinBudget": true,
    "over": 0,
    "utilization": 0.0026,
    "mode": "cap",
    "startedOverBudget": false,
    "descriptionTokens": 0
  },
  "config": {
    "budgetTokens": 5000,
    "maxEditsPerRun": 5,
    "minGapEvidence": 2,
    "skillsDir": ".agents/skills",
    "analysis": {
      "agent": "opencode",
      "model": null,
      "effort": null
    },
    "synthesis": {
      "agent": "opencode",
      "model": null,
      "effort": null
    }
  },
  "stats": {
    "transcripts": 1,
    "corpusMix": {
      "interactive": 0,
      "nonInteractive": 1,
      "total": 1
    },
    "harnessCounts": {
      "claude": 1
    },
    "positive": 0,
    "negative": 0,
    "gapClusters": 0,
    "gapSightings": 2,
    "orchestrationGapSightings": 0,
    "reportOnlyGapClusters": 0,
    "reportOnlyByReason": {
      "majorityOrchestration": 0,
      "belowFloorMixed": 0,
      "tooFewProjects": 0
    },
    "droppedGapSingletons": 2,
    "instructionsWithNegatives": 0,
    "instructionsLeftAlone": 0,
    "leftAloneMaxSessions": 0,
    "instructionsSuppressed": 0,
    "skillExtractions": 0
  },
  "edits": [],
  "verdicts": [
    {
      "instruction": "AG-001",
      "verdict": "keep",
      "positive": 0,
      "negative": 0,
      "note": "No evidence in this run; single session provides no basis to change it."
    }
  ],
  "notes": [
    "Only one session was analyzed and it produced no positive, negative, or gap evidence, so no edits meet the two-session floor."
  ],
  "usage": [
    {
      "agent": "opencode",
      "usage": {
        "input": 7021,
        "output": 13,
        "cache_read": 70,
        "total": 7280
      }
    },
    {
      "agent": "opencode",
      "usage": {
        "input": 403,
        "output": 57,
        "cache_read": 9472,
        "total": 9951
      }
    },
    {
      "agent": "opencode",
      "usage": {
        "input": 1143,
        "output": 81,
        "cache_read": 9856,
        "total": 11120
      }
    }
  ],
  "overflowTarget": {
    "kind": "skills",
    "dir": ".agents/skills",
    "warnings": []
  },
  "attempt": 1
}
Evidence: Validation setup and results
# Targeted live validation

The real backpass CLI ran in a disposable Git repository under the worktree, using a custom memory.md and synthetic Claude session logs. HOME, XDG directories, harness state and caches were isolated. No model or product implementation was stubbed in live scenarios. Installed acpx and OpenCode performed actual model-backed analysis and proposal generation.

The initial parallel model startup encountered an OpenCode database lock. Serial execution removed the lock. A model later attempted to read a raw log outside its working directory, which ACP denied. Moving the disposable transcript store inside that working directory resolved this. Synthesis staging initially lost the project ACP adapter override; adding the installed executable mapping to the disposable HOME config resolved that setup issue. Final analysis, cache invalidation, partial-log analysis, and proposal runs completed successfully.

The generated indexes exercise full-session authority, stable appended IDs, quoted and pasted evidence, single-marker list fences, mixed-tab indentation, false closing fences, message clamping, trace elision, and a log larger than 64 MiB. Successful model evidence includes direct task and steering citations, gap evidence, and metadata without envelope text. Version 10 evidence reused without a call; version 9 triggered fresh analysis. Proposal aggregation retained gap sightings, omitted directive instruction rows, withheld singleton edits, and returned an empty proposal.

Focused executable tests additionally checked all four JSONL readers, metadata persistence, quote validation, invented-ID rejection, evidence-version freshness, and recurring steering-gap clustering. No broad test suite, linter, formatter, or static analysis ran.

No visual UI changed; evidence consists of emitted model-facing prompts, CLI transcripts, persisted evidence, the folded summary, and generated proposal JSON. Disposable worktree fixtures were removed after validation.

Pipeline

Updates from git push no-mistakes

✅ **Intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed (2) ✅
  • 🚨 src/directives.js:122 - Intent requires the “initial task message” and “stable IDs,” but this hunk assigns TASK-1 to the first retained user turn. For logs over 64 MiB, src/discovery/adapters/shared.js:47 discards the prefix. An initial task followed by enough tool output and later steering therefore makes that steering TASK-1 with direct-task authority. Further appends can shift retained STEER-N IDs. Affected callers: src/discovery/adapters/claude.js:86, src/discovery/adapters/codex.js:105, src/discovery/adapters/pi.js:229, src/discovery/adapters/grok.js:64. Related changed sites: src/distill.js:127 restarts numbering; src/directives.js:124 derives steering IDs, :130 derives lifetimes; src/analyze.js:358 persists the incorrect metadata. Decide how partial transcripts must satisfy provenance requirements, then preserve original task identity and turn positions at the shared reader/adapter boundary.

🔧 Fix applied.
1 error still open:

  • 🚨 test/config.test.js:241 - Fix round 1 (c604517) bumped ANALYSIS_INDEX_VERSION to 10 at src/state.js:251 but left this test requiring v9. Assertions at test/config.test.js:248–249 necessarily fail. Update the literal oracle to reject v9 evidence and accept v10; update the title at :237 and explanation at :246 accordingly.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 8 of 8 scenarios driven live against the product
Scenario Result Live Evidence
Analyze and append a session: task and steering retain IDs, authority, turn references and lifetimes without duplicating instruction text. ✅ pass live Generated instruction indexes: basic and basic after append
Analyze quoted, pasted, assistant and tool instructions: only authoritative user envelopes receive IDs, including adversarial list-marker and mixed-tab fences. ✅ pass live Generated instruction indexes: authority, backtick and tilde; Real model directive citations
Analyze oversized messages: clamping preserves envelope extraction and warns when instruction text requires the raw transcript. ✅ pass live Generated instruction indexes: clamped and clamp-fence
Analyze a capped trace: omitted turns are marked elided rather than falsely referenced as visible. ✅ pass live Generated instruction indexes: elided
Analyze a log exceeding 64 MiB: discard task authority and persist retained steering IDs as partial and unstable. ✅ pass live Persisted partial-transcript metadata
Complete model-backed analysis: retain TASK-1 and STEER-3 citations with quoted evidence, while storing directive metadata without envelope text. ✅ pass live Real model directive citations
Rerun analysis: reuse version 10 evidence and reanalyze version 9 evidence. ✅ pass live Version 10 cache reuse; Version 9 cache invalidation
Generate a proposal: exclude directive citations from memory-instruction rows, retain gap sightings and withhold uncorroborated singleton edits. ✅ pass live Aggregated evidence; Generated proposal
  • node bin/backpass.js --help
  • node --import ./test/helpers/hermetic-config.js --test test/directives.test.js
  • node --import ./test/helpers/hermetic-config.js --test --test-name-pattern='evidence accepted before the partial-transcript fix' test/config.test.js
  • node --import ./test/helpers/hermetic-config.js --test --test-name-pattern='a quote that is not in the distilled trace|sanitizeEvidence accepts issued directive ids and drops the rest' test/distill.test.js test/directives.test.js
  • node .test-provenance/live.mjs: isolated CLI scan, analysis prompt checks and appended-session checks
  • node .test-provenance/model-check.mjs and node .test-provenance/inspect-model.mjs: real model startup and permission diagnostics
  • node .test-provenance/citations.mjs: real model citations, persisted metadata, cache reuse and invalidation
  • node .test-provenance/partial-model.mjs: real model analysis of a truncated log
  • node .test-provenance/fold-cli.mjs: real CLI proposal generation and persisted aggregation checks
  • Archived drivers and product outputs in the evidence directory; removed disposable fixtures; confirmed clean git status --short and git diff --exit-code.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with two non-blocking concerns remaining from the previous review.

Reviews (13) · Last reviewed commit: "no-mistakes(review): Align evidence cach..." · Reviewed by Greptile

Comment thread src/directives.js Resolved
Comment thread src/directives.js Outdated
export const TASK_AUTHORITY = "direct-task";
export const STEERING_AUTHORITY = "direct-steering";

const FENCE = /^\s*(`{3,}|~{3,})([^\n]*)$/;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Indented code changes authority This matcher accepts fence-like lines indented four or more spaces, even though those lines belong to an indented code block. In a pasted sample, they can close a fence early or open one that should not exist. That can make pasted text appear to be a user instruction, or hide a real instruction that follows.

Suggested change
const FENCE = /^\s*(`{3,}|~{3,})([^\n]*)$/;
const FENCE = /^ {0,3}(`{3,}|~{3,})([^\n]*)$/;

Comment thread src/directives.js Resolved
@andrewesweet andrewesweet changed the title feat(analyze): index direct task and steering instructions as addressable sources feat(analyze): index direct task and steering instructions as citable sources Sep 25, 2026
Comment thread src/distill.js Resolved
@greptile-apps

greptile-apps Bot commented Sep 25, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: reviewed this PR against main de6a9aa (release 0.1.27) and VISION.md.

Diff verdict: safe for the intended scope. Adds always-on TASK-1 / STEER-N indexing of user-turn envelopes into analysis (new src/directives.js), bumps ANALYSIS_INDEX_VERSION 3→4, teaches sanitize/fold that directive cites are session authority (never durable memory rows), and indexes by turn reference only (or elided/clamped). Envelope text does not persist. No write-path / memory-scope widen. No security concern. Does not close unrelated issues.

VISION per-rule:

  • Purpose / owns the backward pass — aligns (stronger addressable evidence for what steered a session; still the same backward pass).
  • Evidence is the only currency — aligns (quotes still required; fold skips directive ids so they cannot launder into memory-instruction rows; gap sightings still carry recurrence).
  • The human owns the weights — aligns (analysis/index only; no auto-write; session authority, not durable project memory).
  • Nothing the model says is taken on faith — aligns (index by measured turns/elision/clamp, not model arithmetic).
  • The budget is the constraint — aligns (reference-only index; no duplicating turn text into the prompt).
  • It reads what you already have and owns nothing — aligns (local transcripts; no new upload/key/server).
  • Failure is loud and named — aligns (elided/clamped turns named in the index; tests pin clamp/indent/elision cases).
  • Scope — aligns (analysis evidence quality, not a write/scope widen).
  • Closing resist/align lines — aligns on evidence strength; product default changes for every unconfigured analyze run.

contract-class: new-default (independent of contributor claim) — main's unconfigured analysis path has no directive index and ANALYSIS_INDEX_VERSION=3; this always-on indexes TASK/STEER and invalidates the analysis cache. Not restore; not opt-in.

CI: fork workflows approved (attempt 2). All required checks green (CI ubuntu+macos, Guard, no-mistakes). Greptile ignored. mergeable/ready on checks.

Hold: this is waiting on captain, not on the author. Auto-merge is blocked solely by the new-default decision. Flagging for Firstmate/captain merge-or-not.

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: stale-restamp pass.

Thanks for your patience on this one, @andrewesweet. The head is still b45d83d, but main has moved to 0268201 (release 0.1.32), and GitHub now reports this PR as conflicting (DIRTY). Could you rebase it onto current main through git push no-mistakes, so the attestation and CI run against the new head? While you're there, please post a short live analysis run showing the TASK-1 / STEER-N entries in a real session's index.

The earlier per-rule VISION verdict still stands: everything aligns. The contract-class is unchanged: new-default, because every unconfigured analyze run gets the always-on directive index and the ANALYSIS_INDEX_VERSION bump invalidates the analysis cache. Once it's rebased and green, it goes back to Kun for the merge-or-not decision on that default change.

@andrewesweet andrewesweet changed the title feat(analyze): index direct task and steering instructions as citable sources feat: make task and steering instructions citable in analysis Oct 9, 2026
@andrewesweet

Copy link
Copy Markdown
Contributor Author

The branch was updated by merging current main (release 0.1.32) into it as a true
merge commit. Nothing was rebased and nothing was force-pushed, so review history
stays intact. The PR now shows mergeable.

The remaining Greptile P2 suggestion ("Indented code changes authority") is
covered by the relative fence-indent bound already in the branch: a fence may
open at any indentation (so list-item code blocks still count as pastes), but
only a closer indented at most three columns past its opener closes the block,
so fence-like lines inside an indented code block can neither close a paste
early nor open one that should not exist. This commit adds the missing boundary
test: a closer three columns past the opener closes, four past it does not. The
pipeline's review round additionally corrected tab-stop handling in the indent
helper and strengthened a clamp fixture; those commits are in the head.

Live evidence for the directive index, built without a model call by reading one
local pi session from backpass development work through the pi adapter and running
distill → extractDirectives → renderDirectiveIndex:

[TASK-1] task · turn 1 · authority direct-task · lifetime turns 1+ - turn 1 - clamped from the trace, open the raw transcript for its text
[STEER-3] steering · turn 3 · authority direct-steering · lifetime turns 3+ - see turn 3 in the trace
[STEER-5] steering · turn 5 · authority direct-steering · lifetime turns 5+ - see turn 5 in the trace
[STEER-7] steering · turn 7 · authority direct-steering · lifetime turns 7+ - see turn 7 in the trace
[STEER-9] steering · turn 9 · authority direct-steering · lifetime turns 9+ - see turn 9 in the trace
[STEER-11] steering · turn 11 · authority direct-steering · lifetime turns 11+ - see turn 11 in the trace
[STEER-13] steering · turn 13 · authority direct-steering · lifetime turns 13+ - see turn 13 in the trace
[STEER-15] steering · turn 15 · authority direct-steering · lifetime turns 15+ - see turn 15 in the trace
[STEER-17] steering · turn 17 · authority direct-steering · lifetime turns 17+ - see turn 17 in the trace

The session has 9 user turns and was not elided; its long first turn was clamped
out of the trace, so TASK-1 carries the clamped marker instead of a trace
pointer. Only ids, turn references, and lifetimes are shown; no turn text is
duplicated.

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thanks @andrewesweet, both blockers from the last pass are cleared.

  • Merge conflict: resolved by merging current main (0268201, release 0.1.32). Head is now d0f38d0, and GitHub reports it CLEAN.
  • Live evidence: the pi-session directive index you posted shows TASK-1 / STEER-N entries with the clamped marker on the long first turn and no turn text duplicated. That covers what I asked for.
  • CI: every required check is green on d0f38d0: no-mistakes, the generated-files guard, and build-and-test on ubuntu and macOS.

I reviewed the commits added since b45d83d (the fence boundary test, the tab-stop fix in indentColumns, the clamp fixture, docs, and the ANALYSIS_INDEX_VERSION bump from 4 to 5). They stay in the same 10 files as before. No workflow, write-path, or security changes.

VISION per-rule (re-checked against the current VISION.md and this head):

  • Purpose / one backward pass: aligns. Gives analysis addressable evidence for what steered a session. The product is still the same transcript-to-proposal pass.
  • Evidence is the only currency: aligns. Directive cites still need verbatim quotes (invented IDs and fabricated quotes are rejected). Fold excludes them from memory-instruction scoring, and the two-session bar is untouched.
  • The human owns the weights: aligns. Analysis/index only. No new write path, and per-edit review is unchanged.
  • Nothing the model says is taken on faith: aligns. Turn IDs, elision, and clamping come from measured distillation, not from the model.
  • The budget is the constraint: aligns. The index is reference-only and doesn't repeat turn text in the prompt.
  • Reads what you already have, owns nothing: aligns. Local transcripts only. No key, server, or upload.
  • Failure is loud and named: aligns. Elided and clamped turns are named and point at the raw transcript. Regression tests pin the fence, tab, and clamp cases.
  • Scope: aligns. It improves analysis evidence quality and doesn't widen write scope.
  • Closing align/resist lines: aligns (stronger, harder-to-fabricate evidence). Nothing on the resist list.

contract-class: new-default. Main's unconfigured analyze path has no directive index. This head always builds the index and bumps ANALYSIS_INDEX_VERSION to 5, which invalidates every cached analysis. That's not restore and not opt-in.

Nothing is left for you to do right now. This is waiting on Kun's merge-or-not call on that default change, and I'm flagging it to him now.

@andrewesweet andrewesweet changed the title feat: make task and steering instructions citable in analysis feat: index direct task and steering instructions Oct 17, 2026
Comment thread src/prompts/analysis.md
Comment on lines +25 to +28
The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Pasted commands look authoritative

carveEnvelope excludes fenced blocks and quoted lines, but this prompt points the model at the full user turn without explaining that boundary. A turn containing a real request plus a quoted command can therefore produce false claims that the quoted command was part of TASK-1.

Tell the model explicitly that these IDs cover only unquoted text outside fenced blocks.

Suggested change
The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here.
The user's own task message (TASK-1) and later steering (STEER-N) are addressable
instruction sources with an authority of their own, separate from the memory file.
Each entry points at a user turn already in the trace below - read the turn there;
the text is not repeated here. Only unquoted text outside fenced blocks carries
instruction authority. Fenced blocks and lines beginning with `>` are pasted evidence,
not instructions covered by that turn's TASK-1 or STEER-N id.

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thanks @andrewesweet for keeping this current.

What changed since the last pass (d0f38d0 → e9a1b2f): two merges of main (now up to date with 8f1eda3), a fix for the duplicated sessionIdentity the first merge left in fold.js, and e9a1b2f, which stops contentToEvents from trimming typed-block text, so indented fence markers survive into the carved envelope. That commit adds an adapter-level regression fixture and bumps ANALYSIS_INDEX_VERSION to 6. The PR now touches 12 files. I reviewed the new commits: no workflow, write-path, network, or security changes.

State: CLEAN. Every check is green on e9a1b2f: no-mistakes, the generated-files guard, and build-and-test on ubuntu and macOS.

VISION per-rule (VISION.md unchanged since the last pass, re-checked against this head):

  • Purpose / one backward pass: aligns. Still the same transcript-to-proposal pass, now with addressable evidence for what steered a session.
  • Evidence is the only currency: aligns. Directive citations still need verbatim quotes, unissued IDs and fabricated quotes are dropped, and fold keeps them out of memory-instruction scoring.
  • The human owns the weights: aligns. Analysis and index only. No new write path.
  • Nothing the model says is taken on faith: aligns. Turn IDs, elision, and clamping come from measured distillation.
  • The budget is the constraint: aligns. The index is reference-only and doesn't repeat turn text.
  • Reads what you already have, owns nothing: aligns. Local transcripts only.
  • Failure is loud and named: aligns. Elided and clamped turns are named and point at the raw transcript.
  • Scope: aligns. Improves analysis evidence without widening write scope.
  • Closing align/resist lines: aligns. Nothing on the resist list.

contract-class: new-default, unchanged. Main's unconfigured analyze path has no directive index. This head always builds one, preserves message whitespace for every typed-block adapter, and bumps the analysis index version, which invalidates every cached analysis.

Greptile's newest P2 (spell out in the prompt that only unquoted text outside fenced blocks carries TASK-1 / STEER-N authority) is optional and not blocking.

Nothing is waiting on you. This is still a captain-decision hold: Kun decides whether to merge this default change.

@andrewesweet
andrewesweet force-pushed the fm/bp-provenance-widen branch from e9a1b2f to f1d1a3c Compare October 20, 2026 06:14
@andrewesweet andrewesweet changed the title feat: index direct task and steering instructions feat: make direct task and steering instructions citable Oct 20, 2026
Comment thread src/directives.js Resolved
@andrewesweet

Copy link
Copy Markdown
Contributor Author

Rebase-only refresh onto current main validated: the branch was rebased onto upstream main at 3986087 (release 0.1.36) through the no-mistakes pipeline, with the two rebase conflicts in AGENTS.md / src/analyze.js resolved to the branch-side content that already carried the earlier merged upstream changes. All 5 checks are green at f1d1a3c; the PR is mergeable; no behaviour change.

Test evidence note for this run: in the live validation pass, 5 of 6 scenarios were driven live against the product. The model-backed analysis scenario (issued directive citations persist with metadata only, invented IDs are rejected, and updated evidence is reusable) was not driven live in this run — the validation lane's isolated model auth blocked it, and the inconclusive verdict was accepted as-is rather than adding model calls or spend. The live evidence for that scenario remains the pi-session directive index posted earlier in this thread (the TASK-1 / STEER-N entries from the 2026-10-09 pass).

@andrewesweet andrewesweet changed the title feat: make direct task and steering instructions citable feat: make task and steering instructions citable Oct 20, 2026
@andrewesweet

Copy link
Copy Markdown
Contributor Author

Fix-round validation for the list-item-fence finding above: the review step caught that the first cut let marker-prefixed lines close a paste; closing fences now require a whitespace-only prefix, ANALYSIS_INDEX_VERSION moves to 8 so cached evidence under the old acceptance is invalidated, and all 6 checks are green at e332d93.

Test evidence note, same ruling as the previous run: 7 of 8 scenarios were driven live against the product. The authenticated model-backed analysis scenario (issued directive citations persist with metadata only, invented IDs rejected, unsupported quotes rejected) was not driven live in this run — the validation lane's isolated model auth blocks it and the inconclusive verdict was accepted as-is rather than authorising model spend. The live evidence for directive citations remains the pi-session directive index posted earlier in this thread (the TASK-1 / STEER-N entries from the 2026-10-09 pass).

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thanks @andrewesweet for the rebase and the list-item fence fix.

What changed since the last pass (e9a1b2f → e332d93): the branch is rebased onto 3986087 (main has since added only the 0.1.37 release commit c22f2ad). The new commits fix the list-item fence case Greptile raised: FENCE now accepts an optional bullet or ordered list marker before an opener, closing fences still need a whitespace-only prefix so a marker line inside a paste can't close it, and ANALYSIS_INDEX_VERSION moves to 8 with a test that v7 evidence is treated as stale. The PR now touches 13 files. I reviewed the new commits: no workflow, write-path, network, or security changes.

State: CLEAN. Every check is green on e332d93: no-mistakes, the generated-files guard, and build-and-test on ubuntu and macOS. Noted that the model-backed citation scenario wasn't driven live in this run; the earlier pi-session directive index still stands as the live evidence for that.

VISION per-rule (VISION.md unchanged, re-checked against this head):

  • Purpose / one backward pass: aligns. Same transcript-to-proposal pass, with addressable evidence for what steered a session.
  • Evidence is the only currency: aligns. Directive cites still need verbatim quotes, unissued IDs and fabricated quotes are dropped, and fenced pastes (now including list-item fences) stay out of the instruction envelope.
  • The human owns the weights: aligns. Analysis and index only. No new write path.
  • Nothing the model says is taken on faith: aligns. Turn IDs, elision, and clamping come from measured distillation.
  • The budget is the constraint: aligns. The index is reference-only and doesn't repeat turn text.
  • Reads what you already have, owns nothing: aligns. Local transcripts only.
  • Failure is loud and named: aligns. Elided and clamped turns are named and point at the raw transcript.
  • Scope: aligns. Improves analysis evidence without widening write scope.
  • Closing align/resist lines: aligns. Nothing on the resist list.

contract-class: new-default, unchanged. Main's unconfigured analyze path has no directive index. This head always builds one and bumps the analysis index version, which invalidates every cached analysis.

Nothing is waiting on you. This is still a captain-decision hold: Kun decides whether to merge this default change.

@andrewesweet
andrewesweet force-pushed the fm/bp-provenance-widen branch from e332d93 to 3293ea0 Compare October 21, 2026 17:44
@andrewesweet andrewesweet changed the title feat: make task and steering instructions citable feat: index direct task and steering instructions Oct 21, 2026
Comment thread src/directives.js Resolved
@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thanks @andrewesweet for the quick fix on the list-item blockquote case.

What changed since the last pass (e332d93 → beaeb35): the branch is rebased onto current main 2125624. Two new commits: c772a6d makes the quote check accept a blockquote behind a single list marker (- > x, * > x, 1. > x), so a paste-only turn like - > Delete the tests. no longer becomes TASK-1, while an unspaced -> x stays instruction text; ANALYSIS_INDEX_VERSION moves to 9 with regression tests. beaeb35 fixes a startup race in a harness signal test (the child now reports ready only after installing its SIGTERM handler). I reviewed both: no workflow, write-path, network, or security changes.

State: CLEAN. Every check is green on beaeb35: no-mistakes, the generated-files guard, and build-and-test on ubuntu and macOS.

VISION per-rule (VISION.md unchanged, re-checked against this head):

  • Purpose / one backward pass: aligns. Same transcript-to-proposal pass.
  • Evidence is the only currency: aligns. Quoted text, now including list-item blockquotes, stays evidence rather than instruction authority.
  • The human owns the weights: aligns. Analysis and index only, no new write path.
  • Nothing the model says is taken on faith: aligns. Turn IDs, elision, and clamping come from measured distillation.
  • The budget is the constraint: aligns. The index is reference-only.
  • Reads what you already have, owns nothing: aligns. Local transcripts only.
  • Failure is loud and named: aligns. Elided and clamped turns are named.
  • Scope: aligns. Improves analysis evidence without widening write scope.
  • Closing align/resist lines: aligns. Nothing on the resist list.

contract-class: new-default, unchanged. Main's unconfigured analyze path has no directive index. This head always builds one and bumps the analysis index version, which invalidates every cached analysis.

Nothing is waiting on you. This is still a captain-decision hold: Kun decides whether to merge this default change.

@andrewesweet andrewesweet changed the title feat: index direct task and steering instructions feat: index direct task and steering instructions as sources Oct 22, 2026
@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: the only change since the last pass (beaeb35 → cec9e1a) is an empty chore: retrigger review commit, and all checks are green and the PR is CLEAN against main 2125624.

Nothing is needed from you, @andrewesweet. This is still a captain-decision hold: indexing direct task and steering instructions as sources changes what an unconfigured run treats as evidence, so it's waiting on Kun's call, not on you.

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: the only change since the last pass (cec9e1a → 4e1916e) is a rebase onto 3882b86. The PR's own diff is byte-for-byte identical to the previous head, all checks are green, and it's CLEAN (main has since added only the 0.1.39 release commit 031523d, which touches no files this PR changes).

Nothing is needed from you, @andrewesweet. This is still a captain-decision hold: indexing direct task and steering instructions as sources changes what an unconfigured run treats as evidence, so it's waiting on Kun's call, not on you.

…e spans

The initial task message and later user steering become addressable
instruction units (TASK-1 / STEER-N) with source kind, turn, a
direct-task/direct-steering authority tier, and a lifetime closed only by
an explicit revision signal. Spans render in the analysis prompt by turn
reference, never by duplicating turn text; only the authoritative
envelope of a user message indexes (fenced blocks and blockquote lines
are structurally excluded, assistant/tool text never is). The fold
validates cites against the spans each session issued and renders them
apart from memory-instruction rows. ANALYSIS_INDEX_VERSION 3 -> 4.
…ay "see turn N in the trace" only when that turn's text actually reached the trace. Two ways it cannot: capTrace elision (already handled) and per-message clampMessage, which was unhandled because the envelope is now carved pre-clamp. Changes: - `src/distill.js`: each message turn records `clamped: text !== redacted.trim()` — true exactly when clampMessage dropped a middle from the text the model reads. Whole-turn flag, matching the existing whole-turn `elided` flag (same conservatism as the tail-boundary case). - `src/directives.js`: spans carry `clamped`; `renderDirectiveIndex` renders `turn N - clamped from the trace, open the raw transcript for its text` (after the elided branch, before the pointer branch). Header/JSDoc comments updated. No other consumer touched: `directiveMetadata` still persists only ids/turn/authority/lifetime. - `test/directives.test.js`: new test — a user message over the 6,000-char clamp whose only instruction sits in the clamped middle yields `spans[0].clamped === true`, renders the clamped entry, and never renders "see turn 1 in the trace"; also asserts the trace itself lacks the instruction. ci-4 out of scope per instruction. `pnpm run check` exits 0 (711 tests pass, lint/format/typecheck clean)
The branch already bounds fence indentation relative to the opener, which is
what the indented-code review note asked for while keeping list-item fences
working; an absolute ^ {0,3} form would regress those. Add the missing boundary
test: a closer three columns past the opener closes, four past it does not.
Join typed-block texts without trimming so indented fence markers survive into the carved envelope; whitespace-only blocks stay omitted via the non-empty check. New adapter-level regression test plus fixture. Bump ANALYSIS_INDEX_VERSION 5->6: preserved leading/trailing whitespace changes what analysis accepts.
…nvelope

Greptile P2 on PR 154 (comment 4322029695): carveEnvelope missed fence
openers behind a list marker, so a pasted '- ```sh' block stayed
instruction text and its indented closer opened a phantom fence that
swallowed every later instruction. The opener now matches after an
optional bullet (-, *, +) or ordered marker (digits with . or )) plus
spaces, and the closer indent is measured from the fence's own column
after that marker. Regression tests cover the comment's exact case and
the ordered-list variant. Bump ANALYSIS_INDEX_VERSION to 7 for the
changed envelope boundary.
…elope

A blockquote behind a single list marker (- > x, * > x, 1. > x) passed the
quote check and was indexed as instruction text instead of staying evidence,
so a paste-only turn could receive TASK-1. The QUOTE check now allows the
same optional single marker the fence check accepts; markers require
whitespace after them, so an unspaced dash keeps its old behaviour.

Bump ANALYSIS_INDEX_VERSION to 9 so cached analysis accepted under the old
carve is invalidated.
…ess only after installing its SIGTERM handler. Reproduced CI’s exact failure with a forced scheduling delay; same probe passes after fix. All 43 harness/subprocess tests pass locally. Temporary probe removed
@andrewesweet
andrewesweet force-pushed the fm/bp-provenance-widen branch from 4e1916e to c8714af Compare October 25, 2026 19:54
@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thanks @andrewesweet for the new round.

What changed since the last pass (4e1916e → c8714af): the branch was re-raised through no-mistakes and force-pushed onto 3986087. Two new commits on top: c604517 carries a prefixDiscarded flag from readJsonl through every discovery adapter and distill, so a transcript whose head was cut off no longer mints TASK-1 from a partial first user turn; that span becomes a steering span marked partial / stable: false and the index line says "partial transcript · unstable id". ANALYSIS_INDEX_VERSION moves to 10, and c8714af updates the cache regression test to match. I read the diff and it stays inside the directive index and its provenance; nothing touches .github/workflows. All checks are green (CI on ubuntu and macOS, the generated-files guard, no-mistakes), and the branch still merges cleanly with current main 9ded619.

Nothing is needed from you. This is still a captain-decision hold: indexing direct task and steering instructions as sources changes what an unconfigured run treats as evidence, so it's waiting on Kun's call, not on you. The VISION per-rule verdict from earlier passes stands (aligned on evidence-is-currency and enforced-in-code; the open question is only the default change). Contract class: new-default.

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.

2 participants