Commit Graph

17 Commits

Author SHA1 Message Date
Ralph Chang 8da39c7a9d fix(memory): address quality cleanup audit findings 2026-04-28 14:29:28 +08:00
Ralph Chang 56d7ef9a68 test(memory): add real workspace quality cleanup regression fixture 2026-04-28 14:17:43 +08:00
Ralph Chang 7427221640 feat(memory): add local quality cleanup audit logs 2026-04-28 14:17:17 +08:00
Ralph Chang 9991c95ff6 fix(memory): make quality cleanup migration conservative 2026-04-28 14:15:34 +08:00
Ralph Chang 465edfabf1 fix: unify all memory quality rules in single module 2026-04-28 13:34:33 +08:00
Ralph Chang 6a80f4b047 fix: auto-supersede low-quality compaction memories 2026-04-28 13:29:28 +08:00
Ralph Chang 53aa6d3c31 feat: implement Plan 1 - Critical Stability fixes
Wave 1: Storage and Journal Safety
- Add frozen cache TTL (1h) and size bounds (50 sessions)
- Add pending journal source-aware retention (compaction-only TTL)
- Add inter-process file lock with stale recovery
- Move processLatestUserMessage to first transform (after isSubAgent guard)

Wave 2: Promotion Ownership and Bounded Rejection
- Add pendingOwnerSessionID/pendingMessageID metadata
- Add owner-aware pending journal clearing
- Add explicit/manual bounded retry (max 3 attempts)
- Fix session.deleted cleanup idempotency

Wave 3: Normalize, Security, and Cache Hardening
- Fix load-time write loop (only write on security/migration change)
- Add deterministic sort tie-breaker (createdAt -> id)
- Add Bearer token redaction
- Add processed message cache bounds
- Remove priorityWithFreshness dead code

Tests: 180 pass, 0 fail
2026-04-28 11:59:29 +08:00
Ralph Chang 77d60abf5f refactor: make memory dedupe repo-agnostic 2026-04-27 21:19:42 +08:00
Ralph Chang 11361abc91 test: cover security hardening edge cases 2026-04-27 20:22:09 +08:00
Steven Choo acaa829df4 feat: implement indirect prompt injection protection and expanded secret redaction 2026-04-27 12:42:20 +02:00
Ralph Chang 3cc6dff7ae feat: add consolidation accounting for workspace memory promotion
P0 implementation with four waves:

Wave 1: Dedup with accounting
- Add dedupeLongTermEntriesWithAccounting()
- Classify exact duplicate, identity duplicate, topic duplicate

Wave 2: Normalization with accounting
- Add normalizeWorkspaceMemoryWithAccounting()
- Chain redaction → migration → enforceLongTermLimitsWithAccounting

Wave 3: Promotion accounting integration
- Update accountPendingPromotions() to use new accounting API
- Add supersededKeys to classification
- Distinguish promoted / absorbed / superseded / rejected

Wave 4: Integration tests
- End-to-end tests covering full pipeline

Bug fixes:
- Fix active vs superseded boundary (superseded entries no longer block promotion)
- Remove unused rejected_duplicate_lower_quality type
- Defer pending journal safety cap (TODO added)

Tests: 135 passing (up from 115)
2026-04-27 16:45:55 +08:00
Ralph Chang f6f35e87c1 feat: release v1.2.2 with multilingual memory hardening 2026-04-27 00:21:18 +08:00
Ralph Chang 3d44269228 fix: resolve remaining architect issues - split feedback keys, remove generic config key, supersession mode
- Split feedbackTopicKey: server-error now separate from port-occupied-environment
- Remove generic plugin.*config entity key (too broad), fall back to canonical dedup
- Feedback topic conflicts now use supersession mode (newer beats longer)
- Add 3 regression tests: English port/split, unrelated configs, feedback supersession

70/70 tests pass.
2026-04-26 16:54:24 +08:00
Ralph Chang a154139b27 fix: P0c/P0d architect review corrections
P0c fixes:
- Chinese file count regex now accepts 個/个 between number and 文件
- Admin PIN short reference (<20 chars) passes via config value allowlist
- Phase snapshot uses semantic window (.{0,20}) instead of absolute position

P0d fixes:
- Feedback key split: 500 error and port issue remain separate entries
- extractEntityKey avoids over-merging unrelated plugin configs
- chooseBetterMemory supports supersession mode (newer beats longer)
- Sort comparator now includes source priority as secondary tie-breaker

New regression tests (11 total):
- Real Admin PIN short reference passes
- Real Chinese 37 個文件 snapshot rejected
- Real pathology Phase 1-4 snapshot rejected
- Feedback 500 vs port entries not collapsed
- Unrelated plugin configs not collapsed
- Supersession prefers newer shorter over older longer

67/67 tests pass.
2026-04-26 16:50:58 +08:00
Ralph Chang 7527765207 feat: storage-time dedupe, stale pruning, and supersession (P0d)
- Project/reference entries dedupe by entity key (bilingual aware)
- Decision entries supersede by topic key (parser formats, template, etc)
- Feedback entries supersede by topic key (same issue, newer fix wins)
- Stale compaction/manual entries pruned after staleAfterDays + 30
- Explicit and feedback entries never age-pruned
- Freshness used as tie-breaker in priority-based trimming
- Adds 10 new tests covering dedup, supersession, staleness, and freshness
2026-04-26 16:37:18 +08:00
Ralph Chang 721544e7a8 fix: use plain text labels instead of Markdown headers
- Changed '## Memory Candidates' to 'Memory candidates:' in compaction context
- Changed '## Pending Todos' to 'Pending todos:' in todo rendering
- Updated extractCandidateBlock() to parse plain text format (primary)
- Removed stripXmlTags() function (no longer needed)
- All 42 tests pass

Root cause: Markdown headings (##) render as purple in OpenCode UI,
same issue as XML tags and HTML comments. Plain text labels avoid
all special markup rendering.
2026-04-26 15:13:58 +08:00
Ralph Chang 1bba0511bb fix: PR-1 memory plugin quality fixes
## Task 1: Fix exitCode undefined false positive
- Add `typeof exitCode !== "number"` check in plugin.ts
- Only extract errors when exitCode is explicitly non-zero
- Prevent git-log/cat with "errors" text from creating false positives

## Task 2: Fix workspace memory XML truncation
- Budget-aware line-by-line rendering
- Always include closing </workspace_memory> tag
- Return empty string when budget too small
- Bonus: canonical exact deduplication with source priority

## Task 3: Remove "always" as trigger
- Replace "always" with "going forward" in patterns
- Add word boundary via `g` flag and matchAll loop
- "from now on" still works as expected

## Task 4: Verification
- 22 tests passing
- typecheck passing

Tests cover:
- git log/cat with loose "errors" ignored
- TS2345/TypeError strong signals captured
- undefined exitCode: no create, no clear
- exitCode 0: clears errors
- exitCode non-zero: creates error
- XML never truncated mid-tag
- "always" not a trigger
2026-04-26 12:52:21 +08:00