feat(core): make path-local instruction discovery durable

Replace synthetic-message instruction injection with a durable
discovery projection so discovered AGENTS.md files survive compaction,
forks, reverts, and restarts.

- Add the instruction_file table and the durable
  session.instructions.discovered event; projection stores each
  discovered path and content with its owning assistant-message
  boundary and durable discovery order.
- Fold discovered files into the core/instructions source through
  InstructionDiscovery, absorbing SessionInstructions. Completed
  compaction rebaselines restate discovered instructions instead of
  summarizing them away.
- Re-read discovered files live at each observation so mid-session
  edits reach the model; the frozen discovery content stands in only
  when a file becomes unreadable.
- Narrate instruction file changes as per-file deltas via diffByKey,
  restating the full set only for pure reorderings.
- Fork copies discoveries within the inherited transcript, committed
  revert removes discoveries past the revert boundary, and Session
  movement clears them so the destination initializes a complete
  baseline.
This commit is contained in:
Kit Langton 2026-07-06 14:22:53 -04:00
commit 0726f09b05
28 changed files with 1166 additions and 598 deletions

View file

@ -1,9 +1,9 @@
{
"version": "7",
"dialect": "sqlite",
"id": "992b24b9-f3e9-41f5-87a5-4917d1423169",
"id": "4689ab8e-76e3-429e-832c-403de6b7de57",
"prevIds": [
"96e9fe64-660f-4a73-9414-b38bb7eac290"
"992b24b9-f3e9-41f5-87a5-4917d1423169"
],
"ddl": [
{
@ -58,6 +58,10 @@
"name": "instruction_entry",
"entityType": "tables"
},
{
"name": "instruction_file",
"entityType": "tables"
},
{
"name": "message",
"entityType": "tables"
@ -876,6 +880,66 @@
"entityType": "columns",
"table": "instruction_entry"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "session_id",
"entityType": "columns",
"table": "instruction_file"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "path",
"entityType": "columns",
"table": "instruction_file"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "content",
"entityType": "columns",
"table": "instruction_file"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "message_seq",
"entityType": "columns",
"table": "instruction_file"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "discovered_seq",
"entityType": "columns",
"table": "instruction_file"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "position",
"entityType": "columns",
"table": "instruction_file"
},
{
"type": "text",
"notNull": false,
@ -1651,6 +1715,21 @@
"entityType": "fks",
"table": "instruction_entry"
},
{
"columns": [
"session_id"
],
"tableTo": "session",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_instruction_file_session_id_session_id_fk",
"entityType": "fks",
"table": "instruction_file"
},
{
"columns": [
"session_id"
@ -1786,6 +1865,16 @@
"entityType": "pks",
"table": "instruction_entry"
},
{
"columns": [
"session_id",
"path"
],
"nameExplicit": false,
"name": "instruction_file_pk",
"entityType": "pks",
"table": "instruction_file"
},
{
"columns": [
"session_id",
@ -2252,4 +2341,4 @@
}
],
"renames": []
}
}