micode 0.3.4 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -135,29 +135,55 @@ Each task gets its own implement→review loop:
135
135
 
136
136
  ### 4. Session Continuity
137
137
 
138
- Maintain context across long sessions and context clears with the ledger system:
138
+ Maintain context across long sessions and context clears with structured compaction:
139
139
 
140
140
  #### Ledger System
141
141
 
142
- The **continuity ledger** captures essential session state:
142
+ The **continuity ledger** serves as both session state and compaction summary. Based on [Factory.ai's structured compaction research](https://factory.ai/blog/context-compression), which found that structured summarization with deterministic file tracking retains more useful context.
143
143
 
144
144
  ```
145
145
  /ledger
146
146
  ```
147
147
 
148
148
  Creates/updates `thoughts/ledgers/CONTINUITY_{session-name}.md` with:
149
- - Goal and constraints
150
- - Key decisions with rationale
151
- - Current state (Done/Now/Next)
152
- - Working set (branch, key files)
153
149
 
154
- **Auto-injection:** When starting a session, the most recent ledger is automatically injected into the system prompt.
150
+ ```markdown
151
+ # Session: {name}
152
+ Updated: {timestamp}
153
+
154
+ ## Goal
155
+ ## Constraints
156
+ ## Progress
157
+ ### Done
158
+ - [x] {Completed items}
159
+ ### In Progress
160
+ - [ ] {Current work}
161
+ ### Blocked
162
+ - {Issues, if any}
163
+ ## Key Decisions
164
+ - **{Decision}**: {Rationale}
165
+ ## Next Steps
166
+ 1. {Ordered list}
167
+ ## File Operations
168
+ ### Read
169
+ - `{paths read since last compaction}`
170
+ ### Modified
171
+ - `{paths written/edited since last compaction}`
172
+ ## Critical Context
173
+ - {Data, examples, references needed to continue}
174
+ ```
175
+
176
+ **Key features:**
177
+
178
+ - **Iterative merging** - Updates preserve existing information, adding new progress rather than regenerating from scratch
179
+ - **Deterministic file tracking** - Read/write/edit operations tracked automatically via tool call interception, not LLM extraction
180
+ - **Auto-injection** - Most recent ledger injected into system prompt on session start
155
181
 
156
182
  **Auto-clear:** At 80% context usage, the system automatically:
157
- 1. Updates the ledger
158
- 2. Creates a handoff document
183
+ 1. Captures file operations tracked since last clear
184
+ 2. Updates ledger with current state (iterative merge with previous)
159
185
  3. Clears the session
160
- 4. Injects the ledger into the fresh context
186
+ 4. Injects the updated ledger into fresh context
161
187
 
162
188
  #### Artifact Search
163
189
 
@@ -170,26 +196,17 @@ Search past work to find relevant precedent:
170
196
 
171
197
  Searches across:
172
198
  - Ledgers (`thoughts/ledgers/`)
173
- - Handoffs (`thoughts/shared/handoffs/`)
174
199
  - Plans (`thoughts/shared/plans/`)
175
200
 
176
201
  **Auto-indexing:** Artifacts are automatically indexed when created.
177
202
 
178
- #### Handoff
179
-
180
- Save/resume session state for continuity:
181
-
182
- - `handoff-creator`: Save current session (reads ledger for context)
183
- - `handoff-resumer`: Resume from handoff
184
- - Output: `thoughts/shared/handoffs/`
185
-
186
203
  ## Commands
187
204
 
188
205
  | Command | Description |
189
206
  |---------|-------------|
190
207
  | `/init` | Initialize project with ARCHITECTURE.md and CODE_STYLE.md |
191
208
  | `/ledger` | Create or update continuity ledger for session state |
192
- | `/search` | Search past handoffs, plans, and ledgers |
209
+ | `/search` | Search past plans and ledgers |
193
210
 
194
211
  ## Agents
195
212
 
@@ -207,8 +224,6 @@ Save/resume session state for continuity:
207
224
  | reviewer | subagent | claude-opus-4-5 | Review correctness and style |
208
225
  | ledger-creator | subagent | claude-sonnet | Create/update continuity ledgers |
209
226
  | artifact-searcher | subagent | claude-sonnet | Search past work for precedent |
210
- | handoff-creator | subagent | claude-opus-4-5 | Save session state |
211
- | handoff-resumer | subagent | claude-opus-4-5 | Resume from handoff |
212
227
 
213
228
  ## Tools
214
229
 
@@ -217,7 +232,7 @@ Save/resume session state for continuity:
217
232
  | `ast_grep_search` | AST-aware code pattern search |
218
233
  | `ast_grep_replace` | AST-aware code pattern replacement |
219
234
  | `look_at` | Extract file structure for large files |
220
- | `artifact_search` | Search past handoffs, plans, and ledgers |
235
+ | `artifact_search` | Search past plans and ledgers |
221
236
  | `background_task` | Run long-running tasks in background |
222
237
  | `background_output` | Check background task status/output |
223
238
  | `background_cancel` | Cancel background tasks |
@@ -229,7 +244,8 @@ Save/resume session state for continuity:
229
244
  |------|-------------|
230
245
  | Think Mode | Keywords like "think hard" enable 32k token thinking budget |
231
246
  | Ledger Loader | Injects continuity ledger into system prompt |
232
- | Auto-Clear Ledger | At 80% context, saves ledger + handoff and clears session |
247
+ | Auto-Clear Ledger | At 80% context, saves ledger with file ops and clears session |
248
+ | File Ops Tracker | Tracks read/write/edit tool calls for deterministic file operation logging |
233
249
  | Artifact Auto-Index | Indexes artifacts when written to thoughts/ directories |
234
250
  | Auto-Compact | Summarizes session when hitting token limits |
235
251
  | Context Injector | Injects ARCHITECTURE.md, CODE_STYLE.md, .cursorrules |
@@ -276,8 +292,7 @@ micode/
276
292
  ├── ledgers/ # Continuity ledgers
277
293
  └── shared/
278
294
  ├── designs/ # Brainstorm outputs
279
- ├── plans/ # Implementation plans
280
- └── handoffs/ # Session handoffs
295
+ └── plans/ # Implementation plans
281
296
  ```
282
297
 
283
298
  ## Development
@@ -341,3 +356,4 @@ Built on techniques from:
341
356
 
342
357
  - **[oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode)** - OpenCode plugin architecture, agent orchestration patterns, and trusted publishing setup
343
358
  - **[HumanLayer ACE-FCA](https://github.com/humanlayer/12-factor-agents)** - Advanced Context Engineering for Coding Agents, structured workflows, and the research → plan → implement methodology
359
+ - **[Factory.ai Context Compression](https://factory.ai/blog/context-compression)** - Structured compaction research showing that anchored iterative summarization with deterministic file tracking outperforms generic compression
@@ -7,11 +7,9 @@ import { plannerAgent } from "./planner";
7
7
  import { implementerAgent } from "./implementer";
8
8
  import { reviewerAgent } from "./reviewer";
9
9
  import { executorAgent } from "./executor";
10
- import { handoffCreatorAgent } from "./handoff-creator";
11
- import { handoffResumerAgent } from "./handoff-resumer";
12
10
  import { primaryAgent, PRIMARY_AGENT_NAME } from "./commander";
13
11
  import { projectInitializerAgent } from "./project-initializer";
14
12
  import { ledgerCreatorAgent } from "./ledger-creator";
15
13
  import { artifactSearcherAgent } from "./artifact-searcher";
16
14
  export declare const agents: Record<string, AgentConfig>;
17
- export { primaryAgent, PRIMARY_AGENT_NAME, brainstormerAgent, codebaseLocatorAgent, codebaseAnalyzerAgent, patternFinderAgent, plannerAgent, implementerAgent, reviewerAgent, executorAgent, handoffCreatorAgent, handoffResumerAgent, projectInitializerAgent, ledgerCreatorAgent, artifactSearcherAgent, };
15
+ export { primaryAgent, PRIMARY_AGENT_NAME, brainstormerAgent, codebaseLocatorAgent, codebaseAnalyzerAgent, patternFinderAgent, plannerAgent, implementerAgent, reviewerAgent, executorAgent, projectInitializerAgent, ledgerCreatorAgent, artifactSearcherAgent, };
@@ -1,4 +1,14 @@
1
1
  import type { PluginInput } from "@opencode-ai/plugin";
2
+ export declare function parseLedger(content: string, filePath: string, sessionName: string): {
3
+ id: string;
4
+ sessionName: string;
5
+ filePath: string;
6
+ goal: string;
7
+ stateNow: string;
8
+ keyDecisions: string;
9
+ filesRead: string;
10
+ filesModified: string;
11
+ };
2
12
  export declare function createArtifactAutoIndexHook(_ctx: PluginInput): {
3
13
  "tool.execute.after": (input: {
4
14
  tool: string;
@@ -0,0 +1,26 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ interface FileOps {
3
+ read: Set<string>;
4
+ modified: Set<string>;
5
+ }
6
+ export declare function trackFileOp(sessionID: string, operation: "read" | "write" | "edit", filePath: string): void;
7
+ export declare function getFileOps(sessionID: string): FileOps;
8
+ export declare function clearFileOps(sessionID: string): void;
9
+ export declare function getAndClearFileOps(sessionID: string): FileOps;
10
+ export declare function formatFileOpsForPrompt(ops: FileOps): string;
11
+ export declare function createFileOpsTrackerHook(_ctx: PluginInput): {
12
+ "tool.execute.after": (input: {
13
+ tool: string;
14
+ sessionID: string;
15
+ args?: Record<string, unknown>;
16
+ }, _output: {
17
+ output?: string;
18
+ }) => Promise<void>;
19
+ event: ({ event }: {
20
+ event: {
21
+ type: string;
22
+ properties?: unknown;
23
+ };
24
+ }) => Promise<void>;
25
+ };
26
+ export {};
package/dist/index.js CHANGED
@@ -763,14 +763,22 @@ Batch 3 (parallel):
763
763
  Executes ONE task from the plan.
764
764
  Input: Single task with context (which files, what to do).
765
765
  Output: Changes made and verification results for that task.
766
+ Invoke with: Task tool, subagent_type="implementer"
766
767
  </subagent>
767
768
  <subagent name="reviewer" spawn="parallel-per-task">
768
769
  Reviews ONE task's implementation.
769
770
  Input: Single task's changes against its requirements.
770
771
  Output: APPROVED or CHANGES REQUESTED for that task.
772
+ Invoke with: Task tool, subagent_type="reviewer"
771
773
  </subagent>
772
774
  </available-subagents>
773
775
 
776
+ <critical-instruction>
777
+ You MUST use the Task tool to spawn implementer and reviewer subagents.
778
+ Example: Task(description="Implement task 1", prompt="...", subagent_type="implementer")
779
+ Do NOT try to implement or review yourself - delegate to subagents.
780
+ </critical-instruction>
781
+
774
782
  <per-task-cycle>
775
783
  For each task:
776
784
  1. Spawn implementer with task details
@@ -782,18 +790,17 @@ For each task:
782
790
  </per-task-cycle>
783
791
 
784
792
  <parallel-spawning>
785
- Within a batch, spawn ALL implementers in a SINGLE message:
786
-
787
- Example for batch with tasks 1, 2, 3:
788
- - In ONE message, spawn:
789
- - implementer: "Execute task 1: [details]"
790
- - implementer: "Execute task 2: [details]"
791
- - implementer: "Execute task 3: [details]"
792
-
793
- Then after all complete, in ONE message spawn:
794
- - reviewer: "Review task 1 implementation"
795
- - reviewer: "Review task 2 implementation"
796
- - reviewer: "Review task 3 implementation"
793
+ Within a batch, spawn ALL implementers in a SINGLE message using the Task tool:
794
+
795
+ Example for batch with tasks 1, 2, 3 - call Task tool 3 times in ONE message:
796
+ - Task(description="Task 1", prompt="Execute task 1: [details]", subagent_type="implementer")
797
+ - Task(description="Task 2", prompt="Execute task 2: [details]", subagent_type="implementer")
798
+ - Task(description="Task 3", prompt="Execute task 3: [details]", subagent_type="implementer")
799
+
800
+ Then after all complete, in ONE message call Task tool for reviewers:
801
+ - Task(description="Review 1", prompt="Review task 1 implementation", subagent_type="reviewer")
802
+ - Task(description="Review 2", prompt="Review task 2 implementation", subagent_type="reviewer")
803
+ - Task(description="Review 3", prompt="Review task 3 implementation", subagent_type="reviewer")
797
804
  </parallel-spawning>
798
805
 
799
806
  <rules>
@@ -848,159 +855,6 @@ Then after all complete, in ONE message spawn:
848
855
  </never-do>`
849
856
  };
850
857
 
851
- // src/agents/handoff-creator.ts
852
- var handoffCreatorAgent = {
853
- description: "Creates handoff documents for session continuity",
854
- mode: "subagent",
855
- model: "anthropic/claude-opus-4-5",
856
- temperature: 0.2,
857
- tools: {
858
- edit: false,
859
- task: false
860
- },
861
- prompt: `<purpose>
862
- Create handoff document to transfer context to future session.
863
- </purpose>
864
-
865
- <when-to-use>
866
- <trigger>Hitting context limits</trigger>
867
- <trigger>Ending work session</trigger>
868
- <trigger>Switching to different task</trigger>
869
- </when-to-use>
870
-
871
- <rules>
872
- <rule>FIRST check for existing ledger at thoughts/ledgers/CONTINUITY_*.md</rule>
873
- <rule>If ledger exists, use its session name for handoff directory</rule>
874
- <rule>Capture ALL in-progress work</rule>
875
- <rule>Include exact file:line references for changes</rule>
876
- <rule>Document learnings and gotchas</rule>
877
- <rule>Prioritize next steps clearly</rule>
878
- <rule>Include git state (branch, commit)</rule>
879
- <rule>Reference all artifacts created</rule>
880
- </rules>
881
-
882
- <process>
883
- <step>Check for ledger at thoughts/ledgers/CONTINUITY_*.md</step>
884
- <step>If ledger exists, extract session name and state</step>
885
- <step>Review what was worked on</step>
886
- <step>Check git status for uncommitted changes</step>
887
- <step>Gather learnings and decisions made</step>
888
- <step>Identify next steps in priority order</step>
889
- <step>Write handoff document</step>
890
- <step>Commit handoff document</step>
891
- </process>
892
-
893
- <output-path>
894
- If ledger exists: thoughts/shared/handoffs/{session-name}/YYYY-MM-DD_HH-MM-SS.md
895
- Otherwise: thoughts/shared/handoffs/YYYY-MM-DD_HH-MM-SS_description.md
896
- </output-path>
897
-
898
- <document-format>
899
- <frontmatter>
900
- date: [ISO datetime]
901
- branch: [branch name]
902
- commit: [hash]
903
- session: [session name from ledger, if available]
904
- </frontmatter>
905
- <sections>
906
- <section name="Tasks">Table with Task | Status (completed/in-progress/blocked)</section>
907
- <section name="Current State">Working on, Blocked by, Plan location</section>
908
- <section name="Changes Made">file:line - what changed</section>
909
- <section name="Learnings">Discoveries, gotchas, decisions made and why</section>
910
- <section name="Next Steps">Prioritized list 1-3</section>
911
- <section name="Notes">Anything else for next session</section>
912
- </sections>
913
- </document-format>
914
-
915
- <output-summary>
916
- <template>
917
- Handoff: [path]
918
- Tasks: [X done, Y in-progress]
919
- Next: [top priority]
920
- </template>
921
- </output-summary>`
922
- };
923
-
924
- // src/agents/handoff-resumer.ts
925
- var handoffResumerAgent = {
926
- description: "Resumes work from a handoff document",
927
- mode: "subagent",
928
- model: "anthropic/claude-opus-4-5",
929
- temperature: 0.2,
930
- tools: {
931
- write: false,
932
- edit: false,
933
- task: false
934
- },
935
- prompt: `<purpose>
936
- Resume work from a handoff document. Verify state before proceeding.
937
- </purpose>
938
-
939
- <rules>
940
- <rule>Read handoff document COMPLETELY</rule>
941
- <rule>Load ALL referenced artifacts</rule>
942
- <rule>Verify git state matches</rule>
943
- <rule>Check for changes since handoff</rule>
944
- <rule>Report discrepancies before proceeding</rule>
945
- <rule>Don't assume - verify</rule>
946
- </rules>
947
-
948
- <process>
949
- <step>Find handoff (use provided path or list available)</step>
950
- <step>Read handoff completely</step>
951
- <step>Load referenced plans, research, files</step>
952
- <step>Verify current state matches</step>
953
- <step>Report analysis</step>
954
- <step>Wait for confirmation</step>
955
- </process>
956
-
957
- <state-verification>
958
- <check>Current branch</check>
959
- <check>Commit history (ahead/behind)</check>
960
- <check>Files mentioned still exist</check>
961
- <check>Changes mentioned are present</check>
962
- <check>No conflicting changes made</check>
963
- </state-verification>
964
-
965
- <output-format>
966
- <template>
967
- ## Resuming: [handoff path]
968
-
969
- **Created**: [date]
970
- **Branch**: [expected] \u2192 [actual]
971
- **Commit**: [expected] \u2192 [actual]
972
-
973
- ### State
974
- - Branch: [matches/differs]
975
- - Commit: [matches/X ahead/X behind]
976
- - Files: [verified/issues]
977
-
978
- ### Tasks
979
- | Task | Status | Verified |
980
- |------|--------|----------|
981
- | [Task] | [status] | [yes/no] |
982
-
983
- ### Learnings
984
- - [From handoff]
985
-
986
- ### Next Action
987
- [Top priority from handoff]
988
-
989
- ### Loaded
990
- - [x] [artifact]
991
- - [x] [artifact]
992
- </template>
993
- </output-format>
994
-
995
- <on-mismatch>
996
- <action>Report discrepancy and wait for guidance</action>
997
- <discrepancy>Branch different</discrepancy>
998
- <discrepancy>Unexpected commits</discrepancy>
999
- <discrepancy>Files changed/missing</discrepancy>
1000
- <discrepancy>Conflicting work detected</discrepancy>
1001
- </on-mismatch>`
1002
- };
1003
-
1004
858
  // src/agents/commander.ts
1005
859
  var PROMPT = `<identity>
1006
860
  You are Commander - pragmatic software engineer and orchestrator.
@@ -1078,9 +932,9 @@ Just do it - including obvious follow-up actions.
1078
932
  <rule>Reference plan file in commit body</rule>
1079
933
  </phase>
1080
934
 
1081
- <phase name="handoff">
1082
- <agent name="handoff-creator">Save session state</agent>
1083
- <agent name="handoff-resumer">Resume from handoff</agent>
935
+ <phase name="ledger" trigger="context getting full or session ending">
936
+ <action>System auto-updates ledger at 80% context usage</action>
937
+ <output>thoughts/ledgers/CONTINUITY_{session-name}.md</output>
1084
938
  </phase>
1085
939
  </workflow>
1086
940
 
@@ -1091,8 +945,7 @@ Just do it - including obvious follow-up actions.
1091
945
  <agent name="pattern-finder" mode="subagent" purpose="Find existing patterns"/>
1092
946
  <agent name="planner" mode="subagent" purpose="Create detailed implementation plans"/>
1093
947
  <agent name="executor" mode="subagent" purpose="Execute plan (runs implementer then reviewer automatically)"/>
1094
- <agent name="handoff-creator" mode="subagent" purpose="Create handoff docs"/>
1095
- <agent name="handoff-resumer" mode="subagent" purpose="Resume from handoffs"/>
948
+ <agent name="ledger-creator" mode="subagent" purpose="Create/update continuity ledgers"/>
1096
949
  <parallelization>
1097
950
  <safe>locator, analyzer, pattern-finder</safe>
1098
951
  <sequential>planner then executor</sequential>
@@ -1186,17 +1039,25 @@ var PROMPT2 = `
1186
1039
  <subagent name="codebase-locator" spawn="multiple">
1187
1040
  Fast file/pattern finder. Spawn multiple with different queries.
1188
1041
  Examples: "Find all entry points", "Find all config files", "Find test directories"
1042
+ Invoke with: Task tool, subagent_type="codebase-locator"
1189
1043
  </subagent>
1190
1044
  <subagent name="codebase-analyzer" spawn="multiple">
1191
1045
  Deep module analyzer. Spawn multiple for different areas.
1192
1046
  Examples: "Analyze src/core", "Analyze api layer", "Analyze database module"
1047
+ Invoke with: Task tool, subagent_type="codebase-analyzer"
1193
1048
  </subagent>
1194
1049
  <subagent name="pattern-finder" spawn="multiple">
1195
1050
  Pattern extractor. Spawn for different pattern types.
1196
1051
  Examples: "Find naming patterns", "Find error handling patterns", "Find async patterns"
1052
+ Invoke with: Task tool, subagent_type="pattern-finder"
1197
1053
  </subagent>
1198
1054
  </available-subagents>
1199
1055
 
1056
+ <critical-instruction>
1057
+ You MUST use the Task tool to spawn subagents. Call multiple Task tools in a SINGLE message for parallelism.
1058
+ Example: Task(description="Find entry points", prompt="Find all entry points and main files", subagent_type="codebase-locator")
1059
+ </critical-instruction>
1060
+
1200
1061
  <language-detection>
1201
1062
  <rule>Identify language(s) by examining file extensions and config files</rule>
1202
1063
  <markers>
@@ -1290,22 +1151,19 @@ var PROMPT2 = `
1290
1151
 
1291
1152
  <execution-example>
1292
1153
  <step description="Start with maximum parallelism">
1293
- In a SINGLE message, spawn:
1294
- - codebase-locator: "Find all entry points and main files"
1295
- - codebase-locator: "Find all config files (linters, formatters, build)"
1296
- - codebase-locator: "Find test directories and test files"
1297
- - codebase-analyzer: "Analyze the directory structure and organization"
1298
- - pattern-finder: "Find naming conventions used across the codebase"
1299
-
1300
- AND run tools:
1154
+ In a SINGLE message, call Task tool multiple times AND run other tools:
1155
+ - Task(description="Find entry points", prompt="Find all entry points and main files", subagent_type="codebase-locator")
1156
+ - Task(description="Find configs", prompt="Find all config files (linters, formatters, build)", subagent_type="codebase-locator")
1157
+ - Task(description="Find tests", prompt="Find test directories and test files", subagent_type="codebase-locator")
1158
+ - Task(description="Analyze structure", prompt="Analyze the directory structure and organization", subagent_type="codebase-analyzer")
1159
+ - Task(description="Find patterns", prompt="Find naming conventions used across the codebase", subagent_type="pattern-finder")
1301
1160
  - Glob: package.json, pyproject.toml, go.mod, Cargo.toml, etc.
1302
1161
  - Glob: README*, ARCHITECTURE*, docs/*
1303
- - Bash: ls -la (root directory)
1304
1162
  </step>
1305
1163
 
1306
1164
  <step description="Parallel deep analysis">
1307
- Based on discovery, in a SINGLE message spawn:
1308
- - codebase-analyzer for each major module found
1165
+ Based on discovery, in a SINGLE message:
1166
+ - Task for each major module: subagent_type="codebase-analyzer"
1309
1167
  - Read multiple source files simultaneously
1310
1168
  - Read multiple test files simultaneously
1311
1169
  </step>
@@ -1339,19 +1197,50 @@ Create or update a continuity ledger to preserve session state across context cl
1339
1197
  The ledger captures the essential context needed to resume work seamlessly.
1340
1198
  </purpose>
1341
1199
 
1200
+ <modes>
1201
+ <mode name="initial">Create new ledger when none exists</mode>
1202
+ <mode name="iterative">Update existing ledger with new information</mode>
1203
+ </modes>
1204
+
1342
1205
  <rules>
1343
1206
  <rule>Keep the ledger CONCISE - only essential information</rule>
1344
1207
  <rule>Focus on WHAT and WHY, not HOW</rule>
1345
- <rule>State should have exactly ONE item in "Now"</rule>
1346
1208
  <rule>Mark uncertain information as UNCONFIRMED</rule>
1347
1209
  <rule>Include git branch and key file paths</rule>
1348
1210
  </rules>
1349
1211
 
1212
+ <iterative-update-rules>
1213
+ <rule>PRESERVE all existing information from previous ledger</rule>
1214
+ <rule>ADD new progress, decisions, context from new messages</rule>
1215
+ <rule>UPDATE Progress: move In Progress items to Done when completed</rule>
1216
+ <rule>UPDATE Next Steps based on current state</rule>
1217
+ <rule>MERGE file operations: combine previous + new (passed deterministically)</rule>
1218
+ <rule>Never lose information - only add or update</rule>
1219
+ </iterative-update-rules>
1220
+
1221
+ <input-format-for-update>
1222
+ When updating an existing ledger, you will receive:
1223
+
1224
+ <previous-ledger>
1225
+ {content of existing ledger}
1226
+ </previous-ledger>
1227
+
1228
+ <file-operations>
1229
+ Read: path1, path2, path3
1230
+ Modified: path4, path5
1231
+ </file-operations>
1232
+
1233
+ <instruction>
1234
+ Update the ledger with the current session state. Merge the file operations above with any existing ones in the previous ledger.
1235
+ </instruction>
1236
+ </input-format-for-update>
1237
+
1350
1238
  <process>
1351
- <step>Check for existing ledger at thoughts/ledgers/CONTINUITY_*.md</step>
1352
- <step>If exists, read and update it</step>
1353
- <step>If not, create new ledger with session name from current task</step>
1239
+ <step>Check if previous-ledger is provided in input</step>
1240
+ <step>If provided: parse existing content and merge with new state</step>
1241
+ <step>If not: create new ledger with session name from current task</step>
1354
1242
  <step>Gather current state: goal, decisions, progress, blockers</step>
1243
+ <step>Merge file operations (previous + new from input)</step>
1355
1244
  <step>Write ledger in the exact format below</step>
1356
1245
  </process>
1357
1246
 
@@ -1362,21 +1251,37 @@ The ledger captures the essential context needed to resume work seamlessly.
1362
1251
  Updated: {ISO timestamp}
1363
1252
 
1364
1253
  ## Goal
1365
- {One sentence describing success criteria}
1254
+ {What we're trying to accomplish - one sentence describing success criteria}
1366
1255
 
1367
1256
  ## Constraints
1368
1257
  {Technical requirements, patterns to follow, things to avoid}
1369
1258
 
1259
+ ## Progress
1260
+ ### Done
1261
+ - [x] {Completed items}
1262
+
1263
+ ### In Progress
1264
+ - [ ] {Current work - what's actively being worked on}
1265
+
1266
+ ### Blocked
1267
+ - {Issues preventing progress, if any}
1268
+
1370
1269
  ## Key Decisions
1371
- - {Decision}: {Rationale}
1270
+ - **{Decision}**: {Rationale}
1271
+
1272
+ ## Next Steps
1273
+ 1. {Ordered list of what to do next}
1372
1274
 
1373
- ## State
1374
- - Done: {Completed items as comma-separated list}
1375
- - Now: {Current focus - exactly ONE thing}
1376
- - Next: {Queued items in priority order}
1275
+ ## File Operations
1276
+ ### Read
1277
+ - \`{paths that were read}\`
1377
1278
 
1378
- ## Open Questions
1379
- - UNCONFIRMED: {Things needing verification}
1279
+ ### Modified
1280
+ - \`{paths that were written or edited}\`
1281
+
1282
+ ## Critical Context
1283
+ - {Data, examples, references needed to continue work}
1284
+ - {Important findings or discoveries}
1380
1285
 
1381
1286
  ## Working Set
1382
1287
  - Branch: \`{branch-name}\`
@@ -1385,7 +1290,7 @@ Updated: {ISO timestamp}
1385
1290
 
1386
1291
  <output-summary>
1387
1292
  Ledger updated: thoughts/ledgers/CONTINUITY_{session-name}.md
1388
- State: {Now item}
1293
+ State: {Current In Progress item}
1389
1294
  </output-summary>`
1390
1295
  };
1391
1296
 
@@ -1445,8 +1350,6 @@ var agents = {
1445
1350
  implementer: implementerAgent,
1446
1351
  reviewer: reviewerAgent,
1447
1352
  executor: executorAgent,
1448
- "handoff-creator": handoffCreatorAgent,
1449
- "handoff-resumer": handoffResumerAgent,
1450
1353
  "project-initializer": projectInitializerAgent,
1451
1354
  "ledger-creator": ledgerCreatorAgent,
1452
1355
  "artifact-searcher": artifactSearcherAgent
@@ -14144,18 +14047,6 @@ class ArtifactIndex {
14144
14047
  }
14145
14048
  getInlineSchema() {
14146
14049
  return `
14147
- CREATE TABLE IF NOT EXISTS handoffs (
14148
- id TEXT PRIMARY KEY,
14149
- session_name TEXT,
14150
- file_path TEXT UNIQUE NOT NULL,
14151
- task_summary TEXT,
14152
- what_worked TEXT,
14153
- what_failed TEXT,
14154
- learnings TEXT,
14155
- outcome TEXT,
14156
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
14157
- indexed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
14158
- );
14159
14050
  CREATE TABLE IF NOT EXISTS plans (
14160
14051
  id TEXT PRIMARY KEY,
14161
14052
  title TEXT,
@@ -14172,55 +14063,15 @@ class ArtifactIndex {
14172
14063
  goal TEXT,
14173
14064
  state_now TEXT,
14174
14065
  key_decisions TEXT,
14066
+ files_read TEXT,
14067
+ files_modified TEXT,
14175
14068
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
14176
14069
  indexed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
14177
14070
  );
14178
- CREATE VIRTUAL TABLE IF NOT EXISTS handoffs_fts USING fts5(id, session_name, task_summary, what_worked, what_failed, learnings);
14179
14071
  CREATE VIRTUAL TABLE IF NOT EXISTS plans_fts USING fts5(id, title, overview, approach);
14180
14072
  CREATE VIRTUAL TABLE IF NOT EXISTS ledgers_fts USING fts5(id, session_name, goal, state_now, key_decisions);
14181
14073
  `;
14182
14074
  }
14183
- async indexHandoff(record2) {
14184
- if (!this.db)
14185
- throw new Error("Database not initialized");
14186
- const existing = this.db.query(`SELECT id FROM handoffs WHERE file_path = ?`).get(record2.filePath);
14187
- if (existing) {
14188
- this.db.run(`DELETE FROM handoffs_fts WHERE id = ?`, [existing.id]);
14189
- }
14190
- this.db.run(`
14191
- INSERT INTO handoffs (id, session_name, file_path, task_summary, what_worked, what_failed, learnings, outcome, indexed_at)
14192
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
14193
- ON CONFLICT(file_path) DO UPDATE SET
14194
- id = excluded.id,
14195
- session_name = excluded.session_name,
14196
- task_summary = excluded.task_summary,
14197
- what_worked = excluded.what_worked,
14198
- what_failed = excluded.what_failed,
14199
- learnings = excluded.learnings,
14200
- outcome = excluded.outcome,
14201
- indexed_at = CURRENT_TIMESTAMP
14202
- `, [
14203
- record2.id,
14204
- record2.sessionName ?? null,
14205
- record2.filePath,
14206
- record2.taskSummary ?? null,
14207
- record2.whatWorked ?? null,
14208
- record2.whatFailed ?? null,
14209
- record2.learnings ?? null,
14210
- record2.outcome ?? null
14211
- ]);
14212
- this.db.run(`
14213
- INSERT INTO handoffs_fts (id, session_name, task_summary, what_worked, what_failed, learnings)
14214
- VALUES (?, ?, ?, ?, ?, ?)
14215
- `, [
14216
- record2.id,
14217
- record2.sessionName ?? null,
14218
- record2.taskSummary ?? null,
14219
- record2.whatWorked ?? null,
14220
- record2.whatFailed ?? null,
14221
- record2.learnings ?? null
14222
- ]);
14223
- }
14224
14075
  async indexPlan(record2) {
14225
14076
  if (!this.db)
14226
14077
  throw new Error("Database not initialized");
@@ -14251,14 +14102,16 @@ class ArtifactIndex {
14251
14102
  this.db.run(`DELETE FROM ledgers_fts WHERE id = ?`, [existing.id]);
14252
14103
  }
14253
14104
  this.db.run(`
14254
- INSERT INTO ledgers (id, session_name, file_path, goal, state_now, key_decisions, indexed_at)
14255
- VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
14105
+ INSERT INTO ledgers (id, session_name, file_path, goal, state_now, key_decisions, files_read, files_modified, indexed_at)
14106
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
14256
14107
  ON CONFLICT(file_path) DO UPDATE SET
14257
14108
  id = excluded.id,
14258
14109
  session_name = excluded.session_name,
14259
14110
  goal = excluded.goal,
14260
14111
  state_now = excluded.state_now,
14261
14112
  key_decisions = excluded.key_decisions,
14113
+ files_read = excluded.files_read,
14114
+ files_modified = excluded.files_modified,
14262
14115
  indexed_at = CURRENT_TIMESTAMP
14263
14116
  `, [
14264
14117
  record2.id,
@@ -14266,7 +14119,9 @@ class ArtifactIndex {
14266
14119
  record2.filePath,
14267
14120
  record2.goal ?? null,
14268
14121
  record2.stateNow ?? null,
14269
- record2.keyDecisions ?? null
14122
+ record2.keyDecisions ?? null,
14123
+ record2.filesRead ?? null,
14124
+ record2.filesModified ?? null
14270
14125
  ]);
14271
14126
  this.db.run(`
14272
14127
  INSERT INTO ledgers_fts (id, session_name, goal, state_now, key_decisions)
@@ -14284,23 +14139,6 @@ class ArtifactIndex {
14284
14139
  throw new Error("Database not initialized");
14285
14140
  const results = [];
14286
14141
  const escapedQuery = this.escapeFtsQuery(query);
14287
- const handoffs = this.db.query(`
14288
- SELECT h.id, h.file_path, h.task_summary, rank
14289
- FROM handoffs_fts
14290
- JOIN handoffs h ON handoffs_fts.id = h.id
14291
- WHERE handoffs_fts MATCH ?
14292
- ORDER BY rank
14293
- LIMIT ?
14294
- `).all(escapedQuery, limit);
14295
- for (const row of handoffs) {
14296
- results.push({
14297
- type: "handoff",
14298
- id: row.id,
14299
- filePath: row.file_path,
14300
- summary: row.task_summary,
14301
- score: -row.rank
14302
- });
14303
- }
14304
14142
  const plans = this.db.query(`
14305
14143
  SELECT p.id, p.file_path, p.title, rank
14306
14144
  FROM plans_fts
@@ -14360,7 +14198,7 @@ async function getArtifactIndex() {
14360
14198
 
14361
14199
  // src/tools/artifact-search.ts
14362
14200
  var artifact_search = tool({
14363
- description: `Search past handoffs, plans, and ledgers for relevant precedent.
14201
+ description: `Search past plans and ledgers for relevant precedent.
14364
14202
  Use this to find:
14365
14203
  - Similar problems you've solved before
14366
14204
  - Patterns and approaches that worked
@@ -14369,7 +14207,7 @@ Returns ranked results with file paths for further reading.`,
14369
14207
  args: {
14370
14208
  query: tool.schema.string().describe("Search query - describe what you're looking for"),
14371
14209
  limit: tool.schema.number().optional().describe("Max results to return (default: 10)"),
14372
- type: tool.schema.enum(["all", "handoff", "plan", "ledger"]).optional().describe("Filter by artifact type (default: all)")
14210
+ type: tool.schema.enum(["all", "plan", "ledger"]).optional().describe("Filter by artifact type (default: all)")
14373
14211
  },
14374
14212
  execute: async (args) => {
14375
14213
  try {
@@ -15261,6 +15099,69 @@ ${output.system}`;
15261
15099
  };
15262
15100
  }
15263
15101
 
15102
+ // src/hooks/file-ops-tracker.ts
15103
+ var sessionFileOps = new Map;
15104
+ function getOrCreateOps(sessionID) {
15105
+ let ops = sessionFileOps.get(sessionID);
15106
+ if (!ops) {
15107
+ ops = { read: new Set, modified: new Set };
15108
+ sessionFileOps.set(sessionID, ops);
15109
+ }
15110
+ return ops;
15111
+ }
15112
+ function trackFileOp(sessionID, operation, filePath) {
15113
+ const ops = getOrCreateOps(sessionID);
15114
+ if (operation === "read") {
15115
+ ops.read.add(filePath);
15116
+ } else {
15117
+ ops.modified.add(filePath);
15118
+ }
15119
+ }
15120
+ function getFileOps(sessionID) {
15121
+ const ops = sessionFileOps.get(sessionID);
15122
+ if (!ops) {
15123
+ return { read: new Set, modified: new Set };
15124
+ }
15125
+ return ops;
15126
+ }
15127
+ function clearFileOps(sessionID) {
15128
+ sessionFileOps.delete(sessionID);
15129
+ }
15130
+ function formatFileOpsForPrompt(ops) {
15131
+ const readPaths = Array.from(ops.read).sort();
15132
+ const modifiedPaths = Array.from(ops.modified).sort();
15133
+ let result = `<file-operations>
15134
+ `;
15135
+ result += `Read: ${readPaths.length > 0 ? readPaths.join(", ") : "(none)"}
15136
+ `;
15137
+ result += `Modified: ${modifiedPaths.length > 0 ? modifiedPaths.join(", ") : "(none)"}
15138
+ `;
15139
+ result += "</file-operations>";
15140
+ return result;
15141
+ }
15142
+ function createFileOpsTrackerHook(_ctx) {
15143
+ return {
15144
+ "tool.execute.after": async (input, _output) => {
15145
+ const toolName = input.tool.toLowerCase();
15146
+ if (!["read", "write", "edit"].includes(toolName)) {
15147
+ return;
15148
+ }
15149
+ const filePath = input.args?.filePath;
15150
+ if (!filePath)
15151
+ return;
15152
+ trackFileOp(input.sessionID, toolName, filePath);
15153
+ },
15154
+ event: async ({ event }) => {
15155
+ if (event.type === "session.deleted") {
15156
+ const props = event.properties;
15157
+ if (props?.info?.id) {
15158
+ clearFileOps(props.info.id);
15159
+ }
15160
+ }
15161
+ }
15162
+ };
15163
+ }
15164
+
15264
15165
  // src/hooks/auto-clear-ledger.ts
15265
15166
  var MODEL_CONTEXT_LIMITS2 = {
15266
15167
  "claude-opus": 200000,
@@ -15337,23 +15238,40 @@ function createAutoClearLedgerHook(ctx) {
15337
15238
  duration: 3000
15338
15239
  }
15339
15240
  }).catch(() => {});
15241
+ const fileOps = getFileOps(sessionID);
15242
+ const existingLedger = await findCurrentLedger(ctx.directory);
15340
15243
  const ledgerSessionResp = await ctx.client.session.create({
15341
15244
  body: {},
15342
15245
  query: { directory: ctx.directory }
15343
15246
  });
15344
15247
  const ledgerSessionID = ledgerSessionResp.data?.id;
15345
15248
  if (ledgerSessionID) {
15249
+ let promptText = "";
15250
+ if (existingLedger) {
15251
+ promptText += `<previous-ledger>
15252
+ ${existingLedger.content}
15253
+ </previous-ledger>
15254
+
15255
+ `;
15256
+ }
15257
+ promptText += formatFileOpsForPrompt(fileOps);
15258
+ promptText += `
15259
+
15260
+ <instruction>
15261
+ `;
15262
+ promptText += existingLedger ? "Update the ledger with the current session state. Merge the file operations above with any existing ones in the previous ledger." : "Create a new continuity ledger for this session.";
15263
+ promptText += `
15264
+ </instruction>`;
15346
15265
  await ctx.client.session.prompt({
15347
15266
  path: { id: ledgerSessionID },
15348
15267
  body: {
15349
- parts: [
15350
- { type: "text", text: "Update the continuity ledger with current session state before context clear." }
15351
- ],
15268
+ parts: [{ type: "text", text: promptText }],
15352
15269
  agent: "ledger-creator"
15353
15270
  },
15354
15271
  query: { directory: ctx.directory }
15355
15272
  });
15356
15273
  let attempts = 0;
15274
+ let ledgerCompleted = false;
15357
15275
  while (attempts < 30) {
15358
15276
  await new Promise((resolve2) => setTimeout(resolve2, 2000));
15359
15277
  const statusResp = await ctx.client.session.get({
@@ -15361,41 +15279,13 @@ function createAutoClearLedgerHook(ctx) {
15361
15279
  query: { directory: ctx.directory }
15362
15280
  });
15363
15281
  if (statusResp.data?.status === "idle") {
15282
+ ledgerCompleted = true;
15364
15283
  break;
15365
15284
  }
15366
15285
  attempts++;
15367
15286
  }
15368
- }
15369
- const handoffSessionResp = await ctx.client.session.create({
15370
- body: {},
15371
- query: { directory: ctx.directory }
15372
- });
15373
- const handoffSessionID = handoffSessionResp.data?.id;
15374
- if (handoffSessionID) {
15375
- await ctx.client.session.prompt({
15376
- path: { id: handoffSessionID },
15377
- body: {
15378
- parts: [
15379
- {
15380
- type: "text",
15381
- text: "Create a handoff document. Read the current ledger at thoughts/ledgers/ for context."
15382
- }
15383
- ],
15384
- agent: "handoff-creator"
15385
- },
15386
- query: { directory: ctx.directory }
15387
- });
15388
- let attempts = 0;
15389
- while (attempts < 30) {
15390
- await new Promise((resolve2) => setTimeout(resolve2, 2000));
15391
- const statusResp = await ctx.client.session.get({
15392
- path: { id: handoffSessionID },
15393
- query: { directory: ctx.directory }
15394
- });
15395
- if (statusResp.data?.status === "idle") {
15396
- break;
15397
- }
15398
- attempts++;
15287
+ if (ledgerCompleted) {
15288
+ clearFileOps(sessionID);
15399
15289
  }
15400
15290
  }
15401
15291
  const firstMessage = messages[0];
@@ -15423,7 +15313,7 @@ function createAutoClearLedgerHook(ctx) {
15423
15313
  await ctx.client.tui.showToast({
15424
15314
  body: {
15425
15315
  title: "Context Cleared",
15426
- message: "Ledger + handoff saved. Session ready to continue.",
15316
+ message: "Ledger saved. Session ready to continue.",
15427
15317
  variant: "success",
15428
15318
  duration: 5000
15429
15319
  }
@@ -15475,41 +15365,35 @@ function createAutoClearLedgerHook(ctx) {
15475
15365
  // src/hooks/artifact-auto-index.ts
15476
15366
  import { readFileSync as readFileSync3 } from "fs";
15477
15367
  var LEDGER_PATH_PATTERN = /thoughts\/ledgers\/CONTINUITY_(.+)\.md$/;
15478
- var HANDOFF_PATH_PATTERN = /thoughts\/shared\/handoffs\/(.+)\.md$/;
15479
15368
  var PLAN_PATH_PATTERN = /thoughts\/shared\/plans\/(.+)\.md$/;
15480
15369
  function parseLedger(content, filePath, sessionName) {
15481
15370
  const goalMatch = content.match(/## Goal\n([^\n]+)/);
15482
- const stateMatch = content.match(/- Now: ([^\n]+)/);
15371
+ const stateMatch = content.match(/### In Progress\n- \[ \] ([^\n]+)/);
15483
15372
  const decisionsMatch = content.match(/## Key Decisions\n([\s\S]*?)(?=\n## |$)/);
15373
+ const fileOpsSection = content.match(/## File Operations\n([\s\S]*?)(?=\n## |$)/);
15374
+ let filesRead = "";
15375
+ let filesModified = "";
15376
+ if (fileOpsSection) {
15377
+ const readMatch = fileOpsSection[1].match(/### Read\n([\s\S]*?)(?=\n### |$)/);
15378
+ const modifiedMatch = fileOpsSection[1].match(/### Modified\n([\s\S]*?)(?=\n### |$)/);
15379
+ if (readMatch) {
15380
+ const paths = readMatch[1].match(/`([^`]+)`/g);
15381
+ filesRead = paths ? paths.map((p) => p.replace(/`/g, "")).join(",") : "";
15382
+ }
15383
+ if (modifiedMatch) {
15384
+ const paths = modifiedMatch[1].match(/`([^`]+)`/g);
15385
+ filesModified = paths ? paths.map((p) => p.replace(/`/g, "")).join(",") : "";
15386
+ }
15387
+ }
15484
15388
  return {
15485
15389
  id: `ledger-${sessionName}`,
15486
15390
  sessionName,
15487
15391
  filePath,
15488
15392
  goal: goalMatch?.[1] || "",
15489
15393
  stateNow: stateMatch?.[1] || "",
15490
- keyDecisions: decisionsMatch?.[1]?.trim() || ""
15491
- };
15492
- }
15493
- function parseHandoff(content, filePath, fileName) {
15494
- const sessionMatch = content.match(/^session:\s*(.+)$/m);
15495
- const sessionName = sessionMatch?.[1] || fileName;
15496
- const taskMatch = content.match(/\*\*Working on:\*\*\s*([^\n]+)/);
15497
- const taskSummary = taskMatch?.[1] || "";
15498
- const learningsMatch = content.match(/## Learnings\n\n([\s\S]*?)(?=\n## |$)/);
15499
- const learnings = learningsMatch?.[1]?.trim() || "";
15500
- const workedMatch = content.match(/## What Worked\n\n([\s\S]*?)(?=\n## |$)/);
15501
- const whatWorked = workedMatch?.[1]?.trim() || learnings;
15502
- const failedMatch = content.match(/## What Failed\n\n([\s\S]*?)(?=\n## |$)/);
15503
- const whatFailed = failedMatch?.[1]?.trim() || "";
15504
- return {
15505
- id: `handoff-${fileName}`,
15506
- sessionName,
15507
- filePath,
15508
- taskSummary,
15509
- whatWorked,
15510
- whatFailed,
15511
- learnings,
15512
- outcome: "UNKNOWN"
15394
+ keyDecisions: decisionsMatch?.[1]?.trim() || "",
15395
+ filesRead,
15396
+ filesModified
15513
15397
  };
15514
15398
  }
15515
15399
  function parsePlan(content, filePath, fileName) {
@@ -15545,15 +15429,6 @@ function createArtifactAutoIndexHook(_ctx) {
15545
15429
  console.log(`[artifact-auto-index] Indexed ledger: ${filePath}`);
15546
15430
  return;
15547
15431
  }
15548
- const handoffMatch = filePath.match(HANDOFF_PATH_PATTERN);
15549
- if (handoffMatch) {
15550
- const content = readFileSync3(filePath, "utf-8");
15551
- const index = await getArtifactIndex();
15552
- const record2 = parseHandoff(content, filePath, handoffMatch[1]);
15553
- await index.indexHandoff(record2);
15554
- console.log(`[artifact-auto-index] Indexed handoff: ${filePath}`);
15555
- return;
15556
- }
15557
15432
  const planMatch = filePath.match(PLAN_PATH_PATTERN);
15558
15433
  if (planMatch) {
15559
15434
  const content = readFileSync3(filePath, "utf-8");
@@ -16062,6 +15937,7 @@ var OpenCodeConfigPlugin = async (ctx) => {
16062
15937
  const contextWindowMonitorHook = createContextWindowMonitorHook(ctx);
16063
15938
  const commentCheckerHook = createCommentCheckerHook(ctx);
16064
15939
  const artifactAutoIndexHook = createArtifactAutoIndexHook(ctx);
15940
+ const fileOpsTrackerHook = createFileOpsTrackerHook(ctx);
16065
15941
  const backgroundTaskManager = new BackgroundTaskManager(ctx);
16066
15942
  const backgroundTaskTools = createBackgroundTaskTools(backgroundTaskManager);
16067
15943
  return {
@@ -16083,11 +15959,13 @@ var OpenCodeConfigPlugin = async (ctx) => {
16083
15959
  };
16084
15960
  const mergedAgents = mergeAgentConfigs(agents, userConfig);
16085
15961
  config2.agent = {
16086
- [PRIMARY_AGENT_NAME]: mergedAgents[PRIMARY_AGENT_NAME],
16087
- ...Object.fromEntries(Object.entries(mergedAgents).filter(([k]) => k !== PRIMARY_AGENT_NAME)),
16088
15962
  ...config2.agent,
16089
15963
  build: { ...config2.agent?.build, mode: "subagent" },
16090
- plan: { ...config2.agent?.plan, mode: "subagent" }
15964
+ plan: { ...config2.agent?.plan, mode: "subagent" },
15965
+ triage: { ...config2.agent?.triage, mode: "subagent" },
15966
+ docs: { ...config2.agent?.docs, mode: "subagent" },
15967
+ ...Object.fromEntries(Object.entries(mergedAgents).filter(([k]) => k !== PRIMARY_AGENT_NAME)),
15968
+ [PRIMARY_AGENT_NAME]: mergedAgents[PRIMARY_AGENT_NAME]
16091
15969
  };
16092
15970
  config2.mcp = {
16093
15971
  ...config2.mcp,
@@ -16135,6 +16013,7 @@ var OpenCodeConfigPlugin = async (ctx) => {
16135
16013
  await commentCheckerHook["tool.execute.after"]({ tool: input.tool, args: input.args }, output);
16136
16014
  await contextInjectorHook["tool.execute.after"]({ tool: input.tool, args: input.args }, output);
16137
16015
  await artifactAutoIndexHook["tool.execute.after"]({ tool: input.tool, args: input.args }, output);
16016
+ await fileOpsTrackerHook["tool.execute.after"]({ tool: input.tool, sessionID: input.sessionID, args: input.args }, output);
16138
16017
  },
16139
16018
  event: async ({ event }) => {
16140
16019
  if (event.type === "session.deleted") {
@@ -16149,6 +16028,7 @@ var OpenCodeConfigPlugin = async (ctx) => {
16149
16028
  await tokenAwareTruncationHook.event({ event });
16150
16029
  await contextWindowMonitorHook.event({ event });
16151
16030
  backgroundTaskManager.handleEvent(event);
16031
+ await fileOpsTrackerHook.event({ event });
16152
16032
  }
16153
16033
  };
16154
16034
  };
@@ -1,13 +1,3 @@
1
- export interface HandoffRecord {
2
- id: string;
3
- sessionName?: string;
4
- filePath: string;
5
- taskSummary?: string;
6
- whatWorked?: string;
7
- whatFailed?: string;
8
- learnings?: string;
9
- outcome?: "SUCCEEDED" | "PARTIAL_PLUS" | "PARTIAL_MINUS" | "FAILED" | "UNKNOWN";
10
- }
11
1
  export interface PlanRecord {
12
2
  id: string;
13
3
  title?: string;
@@ -22,9 +12,11 @@ export interface LedgerRecord {
22
12
  goal?: string;
23
13
  stateNow?: string;
24
14
  keyDecisions?: string;
15
+ filesRead?: string;
16
+ filesModified?: string;
25
17
  }
26
18
  export interface SearchResult {
27
- type: "handoff" | "plan" | "ledger";
19
+ type: "plan" | "ledger";
28
20
  id: string;
29
21
  filePath: string;
30
22
  title?: string;
@@ -37,7 +29,6 @@ export declare class ArtifactIndex {
37
29
  constructor(dbDir?: string);
38
30
  initialize(): Promise<void>;
39
31
  private getInlineSchema;
40
- indexHandoff(record: HandoffRecord): Promise<void>;
41
32
  indexPlan(record: PlanRecord): Promise<void>;
42
33
  indexLedger(record: LedgerRecord): Promise<void>;
43
34
  search(query: string, limit?: number): Promise<SearchResult[]>;
@@ -5,7 +5,6 @@ export declare const artifact_search: {
5
5
  limit: import("zod").ZodOptional<import("zod").ZodNumber>;
6
6
  type: import("zod").ZodOptional<import("zod").ZodEnum<{
7
7
  all: "all";
8
- handoff: "handoff";
9
8
  plan: "plan";
10
9
  ledger: "ledger";
11
10
  }>>;
@@ -13,6 +12,6 @@ export declare const artifact_search: {
13
12
  execute(args: {
14
13
  query: string;
15
14
  limit?: number | undefined;
16
- type?: "all" | "handoff" | "plan" | "ledger" | undefined;
15
+ type?: "all" | "plan" | "ledger" | undefined;
17
16
  }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
18
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micode",
3
- "version": "0.3.4",
3
+ "version": "0.4.1",
4
4
  "description": "OpenCode plugin with Brainstorm-Research-Plan-Implement workflow",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -44,7 +44,7 @@
44
44
  "url": "https://github.com/vtemian/micode/issues"
45
45
  },
46
46
  "dependencies": {
47
- "@opencode-ai/plugin": "1.0.207"
47
+ "@opencode-ai/plugin": "^1.0.219"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@biomejs/biome": "^2.3.10",
@@ -1,2 +0,0 @@
1
- import type { AgentConfig } from "@opencode-ai/sdk";
2
- export declare const handoffCreatorAgent: AgentConfig;
@@ -1,2 +0,0 @@
1
- import type { AgentConfig } from "@opencode-ai/sdk";
2
- export declare const handoffResumerAgent: AgentConfig;