1e7a7600a2
Refresh all AGENTS.md files to reflect codebase state at5ffbe0e24(wascd31d2a1a, 197 commits behind). Key drift corrections across 45 modified + 1 new file: Root AGENTS.md: - TS file counts: 1967 -> 2034 in src/ (1337 source + 697 test) - LOC: 278k -> 292k - Barrel index.ts: 120 -> 122 - Hook tier composition: 52/59 -> 54/61 (base/with team-mode) - Tool Guard hooks: 14 -> 16 (add fsync-skip-warning, bash-file-read-guard) - Add boulder feature, agent-ordering schema, .agents/ directory, v4.1.1 release tag - Add generated/ directory entry src/AGENTS.md: - Subsystem inventory: agents 96->102, hooks 570->581, tools 306->314, features 389->400, shared 258->278, cli 150->158, plugin 55->56 - LOC totals refreshed for every subsystem - Schema files: 32 -> 30 src/hooks/AGENTS.md: - Tier 2 (Tool Guard): 14 -> 16 hooks, add fsyncSkipWarning row - Total: 52 base / 59 team-mode -> 54 base / 61 team-mode - zauc-mocks count: 7 -> 5 src/features/AGENTS.md: - background-agent: 47 -> 57 files, mention archive fallback - opencode-skill-loader: 33 -> 30 - tmux-subagent: 34 -> 32 src/plugin/AGENTS.md: - Tool Guard composer count: 14 -> 16 - Aggregator total: 43 -> 45 src/cli/AGENTS.md: - Add new boulder subcommand (BoulderState inspector) - Command count: 6 -> 7 NEW: src/features/boulder-state/AGENTS.md - Document the new Boulder work tracking feature - Schema v2 with BoulderState/BoulderWorkState/TaskSessionState - Lifecycle, storage, integration points with atlas/ralph-loop hooks All other AGENTS.md files: Generated date 2026-05-08 -> 2026-05-14.
3.9 KiB
3.9 KiB
src/tools/hashline-edit/ — Hash-Anchored File Edit Tool
Generated: 2026-05-14
OVERVIEW
24 files. Implements the hashline_edit tool — hash-anchored file editing where every line reference includes a content hash (LINE#ID). Validates hashes before applying edits, rejecting stale references.
THREE-OP MODEL
All edits use exactly 3 operations:
| Op | pos | end | lines | Effect |
|---|---|---|---|---|
replace |
required | optional | required | Replace single line or range pos..end |
append |
optional | optional | required | Insert after anchor (or EOF if no anchor) |
prepend |
optional | optional | required | Insert before anchor (or BOF if no anchor) |
lines: null or lines: [] with replace = delete. delete: true at tool level = delete file.
EXECUTION PIPELINE
hashline-edit-executor.ts
→ normalize-edits.ts # Parse RawHashlineEdit → HashlineEdit (validate op schema)
→ validation.ts # Validate LINE#ID references (hash match, line exists)
→ edit-ordering.ts # Sort bottom-up (by line number, descending)
→ edit-deduplication.ts # Remove duplicate ops
→ edit-operations.ts # Apply each op using edit-operation-primitives.ts
→ autocorrect-replacement-lines.ts # Auto-fix indentation/formatting
→ hashline-edit-diff.ts # Build diff output using diff-utils.ts
KEY FILES
| File | Purpose |
|---|---|
tools.ts |
createHashlineEditTool() factory — tool schema + entry point |
hashline-edit-executor.ts |
Main execution: normalize → validate → order → apply → diff |
normalize-edits.ts |
Parse RawHashlineEdit[] (allows string op variants) → typed HashlineEdit[] |
validation.ts |
Validate LINE#ID: parse hash, verify line content matches stored hash |
hash-computation.ts |
computeLineHash(line) → 2-char CID from set ZPMQVRWSNKTXJBYH |
edit-operations.ts |
Apply replace/append/prepend to file lines array |
edit-operation-primitives.ts |
Low-level line array mutation primitives |
edit-ordering.ts |
Sort edits bottom-up to preserve line numbers during multi-edit |
edit-deduplication.ts |
Deduplicate overlapping/identical operations |
edit-text-normalization.ts |
Normalize line content (CRLF, BOM, trailing whitespace) |
file-text-canonicalization.ts |
Canonicalize full file content before hashing |
autocorrect-replacement-lines.ts |
Auto-restore indentation from original lines |
hashline-edit-diff.ts |
Generate unified diff for error/success messages |
diff-utils.ts |
Thin wrapper around diff npm library |
hashline-chunk-formatter.ts |
Format line chunks with LINE#ID tags |
tool-description.ts |
HASHLINE_EDIT_DESCRIPTION constant |
types.ts |
HashlineEdit, ReplaceEdit, AppendEdit, PrependEdit |
constants.ts |
Hash alphabet, separator character (#), pipe separator (` |
LINE#ID FORMAT
{line_number}#{hash_id}
hash_id: two chars fromZPMQVRWSNKTXJBYH(CID letters)- Example:
42#VKmeans line 42 with hashVK - Validation: recompute hash of current line content → must match stored hash
- Content separator:
|(pipe) between hash tag and content in read output
AUTOCORRECT BEHAVIORS (built-in)
- Merged lines auto-expanded back to original count
- Indentation restored from original lines
- BOM and CRLF line endings preserved
>>>prefix and diff markers inlinestext auto-stripped
ERROR CASES
- Hash mismatch → edit rejected, diff shown with current state
- Overlapping ranges → detected and rejected
- Missing
posforreplace→ schema error lines: nullwithappend/prepend→ schema error
HOW LINE HASHES WORK
// Reading: every line gets tagged
"42#VK| function hello() {"
// Editing: reference by tag
{ op: "replace", pos: "42#VK", lines: "function hello(name: string) {" }
// If file changed since read: hash won't match → rejected before corruption