Files
solution-erp/.claude/agent-memory/investigator-codebase/MEMORY.md
2026-07-13 16:05:44 +07:00

21 KiB
Raw Blame History

Investigator-Codebase Agent — Persistent Memory

Persistent diary cross-session. Auto-injected first ~200 lines at spawn (L1 HOT). Update BEFORE every stop. Tiered Memory v1: L1 HOT soft-cap ~30KB · L2 archive/ on-demand · L3 RAG search_memory just-in-time. Keep entry ≤ 1.5K chars (gotcha #53). Full verbatim history pre-S40 → git d2f52ba + archive/2026-05-q1..q4.md + archive/2026-06.md. 🗺️ Lookup map: archive/_INDEX.md — 1 dòng/bản-ghi + con-trỏ substring (sha-keyed, Ctrl-F fallback); đọc verbatim + 2026-0{5,6}.gist.md theo nhu cầu. S80 curate: moved 15 recon entries S65→S76 + 2× 06-20 → archive. Renamed S39: investigator → investigator-codebase (internal half; external → investigator-api).


🎯 Role baseline

Read-only INTERNAL audit SOLUTION_ERP codebase. Tools: Read, Grep, Glob, Bash + 5 RAG MCP. Output: concise findings <500 words + file:line refs. Skills: contract-workflow + permission-matrix + ef-core-migration.

🚫 Split boundary (S39)

  • MINE: internal SQL/EF/grep/reference mirror, sqlcmd schema scan, controller audit, migration diff, count grounding
  • NOT: external docs/CVE/lib → investigator-api · write → implementer · test → test-specialist · architecture decision → em main

🆕 Recent invest (S112-S114 stubs — verbatim → git history + archive/2026-07.md)

  • S114 (07-12) PE multi-winner PER-HANG-MUC (fable-clone): Mig58/59 multi-winner = WHOLE-SUPPLIER (PurchaseEvaluationSupplier.IsWinner); Quote.IsSelected per hang-muc×NCC = latent-hook Mig12 nay LIVE (Mig65 backfill re-key winner-truth IsWinner→IsSelected = CARDINALITY-CHANGE #2). winnerQuoteTotal=SUM(Quote WHERE IsSelected) PeFeatures.cs:1188. #1 open: N-win 1 hang-muc split KHOI-LUONG hay full-price (schema thieu per-winner volume). Tag [s114, pe-multiwinner-per-hangmuc, quote-isselected-live].
  • S113 (07-12) Supplier import v2 (5-lane ensemble): selection consumers qua ListSuppliersQuery (PeDetailTabs:2222+ContractCreatePage:321+dashboard); chot IsPublic-bool + dedup-MST+Code + fail-closed default. Prod 37 NCC. 1 lane #53-garble→em-main recover. Tag [s113, supplier-import-v2, ma-ncc=code].
  • S112 (07-12) Supplier Excel-import + PE sign-off (fable-clone): Supplier 27/27 bijective (Mig62 SHIPPED prod); dedup Code CI-collation → normalize-case TRUOC store; PE bypass = go/gate ApplyDrafterBypassOnSubmitAsync; EDGE-5 drafter-forge-Reject REACHABLE. Tag [s112, supplier-mapping, pe-bypass-a1, edge5-reachable].

📋 Patterns proven (apply confidently)

Schema scan via sqlcmd

sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Dev -Q "..."     # runtime API (primary)
sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Design -Q "..."  # ef tooling
ssh vietreport-vps "sqlcmd -S .\SQLEXPRESS -d SolutionErp -U vrapp -P '...' -Q '...'"  # prod

Queries: sys.columns, sys.triggers, __EFMigrationsHistory, COUNT(*), sys.indexes. Gotcha 2 LocalDB distinct (feedback_designtime_runtime_db): _Dev=runtime (appsettings.Development), _Design=dotnet ef default. Prod password fallback C:\inetpub\solution-erp\api\appsettings.Production.json khi $env:PROD_DB_PASSWORD empty.

Controller / wire-claim audit

  • Grep \[Route\("api/[a-z]+"\)\] enumerate controllers · \[Authorize(Policy = "..." per-action policy (gotcha #44 silent 403 class-level quá strict)
  • Grep // Mock / alert( / setEditing(null) // close UI — wire claim bugs · IActionResult vs ActionResult<T>

Smoke verify catalog

Bearer từ POST api.solutions.com.vn/api/auth/login → status matrix expected vs actual + file:line evidence.

Memory cross-reference

30 user-memory tại C:\Users\pqhuy\.claude\projects\D--...\memory\MEMORY.md (index). Key: per_chunk_commit · uat_skip_verify · designtime_runtime_db · per_nv_permission_scope · ef_migration_backfill_reorder · workflow_fanout_reliability · canonical_spec_over_broadcast (S79).

External research → DEFER investigator-api (split S39)


⚠️ Anti-patterns

Skip MEMORY update · Vague "seems like/probably" · Missing file:line · >500 words · Scope drift to architecture recommendation (em main decides)


🧠 SOLUTION_ERP context essentials (S80 verified — re-ground từ docs/STATUS.md canonical)

  • DB: Dev SolutionErp_Dev · Design SolutionErp_Design (distinct) · Prod .\SQLEXPRESS/SolutionErp/vrapp via SSH vietreport-vps
  • Migration path: src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/*.cs (⚠️ NOT root /Migrations/). 57 mig, last AddPeSuggestedPriceNotes.
  • Counts S80 (canonical docs/STATUS.md): 57 mig · 88 SQL tables (count .ToTable() ModelSnapshot NOT DbSet) · ~253 endpoints · 68 FE pages · 54 menu keys (BE MenuKeys const) · 354 test (45 Domain + 309 Infra) · 71 gotchas (format ### N.) · 30 user-memory · 6 skills · 11 sub-agents (all-inherit H8)
  • Tech: .NET 10 Clean Arch (Api→Application←Domain + Infra) + CQRS MediatR + EF Core 10 + 2 React 19 Vite 8 TS 6 (fe-admin :8082 + fe-user :8080) + SQL Server + Gitea CI + IIS
  • Prod: api/admin/eoffice.solutions.com.vn · Gitea git.baocaogiaoduc.vn/vietreport-admin/solution-erp (Actions API /api/v1/repos/.../actions/tasks NOT /runs 404, cache stale ~2min gotcha #46 — cross-check VPS mtime). Bundle live admin CsJetgZH/user BVS0ApIm (Run #330).
  • Auth: admin@solutions.com.vn/Admin@123456 (full) / nv.test@solutions.com.vn/TestUser@123456 (Drafter). Response accessToken+refreshToken+user. Password ≥12 chars.

🔄 Active workflow schemas (V1 + V2 coexist post-S17)

  • V1 Mig 21 flatWorkflowDefinition pin PE/Contract cũ. Match Dept+PositionLevel.
  • V2 Mig 22-31ApprovalWorkflow pin PE/Contract mới, match ApproverUserId 1-1 OR-of-N cùng Cấp. Steps (Phòng) > Levels (Cấp). PE + Contract đã wire V2 (Mig 32+33 S29). Proposal V2 (Mig 38). WorkflowApps skeleton (Mig 39).
    • Mig 25 IsUserSelectable · Mig 26 PE LevelOpinions UPSERT · Mig 29 Allow* per-NV · Mig 30 F4 AllowApproverEditBudget · Mig 31 SkipToFinal→ApproverLevel · Mig 53 cờ-gấp+CeoApprovalThreshold · Mig 54 giá-đề-xuất PRO/CCM+giá-chốt · Mig 56 ProInitial/ProAdjust · Mig 57 ghi-chú-giá.
  • State machine PE 5 trạng thái: Nháp / Đã gửi duyệt / Trả lại (TraLai=98) / Từ chối (REMOVED-S60 hard-guard) / Đã duyệt
  • Mode Trả lại 4 option per-Level: OneLevel (lùi 1 Cấp) / OneStep (lùi Bước trước) / Assignee (pick NV đã ký) / Drafter (Phase=TraLai). 3 mode đầu giữ ChoDuyet lùi pointer. Admin bypass level.Allow*.

📅 Recent activity (compressed — full verbatim → archive/2026-06.md via archive/_INDEX.md)

  • 2026-07-13 PE quote-NEGATIVE feature LENS Budget-consumers (ensemble, RETURN-only): anh Kiệt: cho nhập SỐ ÂM ô form.thanhTien (báo giá/hạng mục) dialog "Thêm NCC"; RULE = âm=khoản-TRỪ NCC, ngân sách GIỮ NGUYÊN. CRITICAL confirm: quote KHÔNG mutate PeWorkItemBudgets — budget chỉ ghi bởi UpdatePeBudgetPro/CcmCommandHandler (role-gated PRO/CCM, PeWorkItemBudgetFeatures.cs:105-107/175-177) + Adjust/SetCcmBudget; quote write-site (PurchaseEvaluationDetailFeatures.cs:308-345) chỉ đụng quote-field + re-derive IsWinner, NEVER budget. 5 consumer đọc SUM(ThanhTien WHERE IsSelected): (1) winnerQuoteTotal DISPLAY PeFeatures.cs:1188-1191 no-clamp (2) CCM-threshold PeWorkflowService.cs:884-893 guard >=ceoThreshold reject HIGH ko-reject-âm→âm cho CCM-finalize dễ hơn (3) giaTri CreateContract PER-WINNER CreateContractFromEvaluation:88-90,100 → Contract.GiaTri CÓ THỂ ÂM, BYPASS CreateContractCommandValidator.GiaTri>=0 (ContractFeatures.cs:46, chỉ áp manual-create path) (4) "So-với-ngân-sách" block-B DISPLAY PeFeatures.cs:904-947 budget read AsNoTracking untouched, soft-warn only (5) submit-guard PeWorkflowService.cs:196-209 = GUARD DUY NHẤT REJECT: if Sum()<=0 → "chưa có giá chào thầu" — WHOLE-phiếu total, per-item âm OK miễn net>0. NO quote validator tồn tại (grep⌀ UpsertPurchaseEvaluationQuoteCommandValidator) → âm đã flow BE 0-block, chỉ FE chặn. Keep-≥0 fields có validator: BudgetPeriodAmount/ApprovedPriceAmount/ProInitial/InitialAmount. ĐÃ allow-âm sẵn (unrelated): ProAdjustment/Adjustment/ExpectedRemainingAmount (PeFeatures.cs:345-348 mirror-LeaveBalance). Tag [s115?, pe-negative-quote, budget-not-mutated, submit-guard-sum-le-0, giaTri-negative-bypass-validator, no-quote-validator].

  • [→ git 07-12 · superseded by S115 entry above] PE per-HANGMUC multi-winner LENS BE-consumer-audit: 3 cardinality axes — SelectedSupplierId single (legacy) · Mig58 IsWinner=WHOLE-SUPPLIER liên-danh · Quote.IsSelected per hangmuc×supplier (S114 made LIVE). 5 money consumers keyed off IsSelected now (winnerQuoteTotal/submit-guard/ccm-threshold/giaTri/budget-block-B). ~6 test files. Tag [pe-multiwinner, per-hangmuc, quote-isselected, cardinality].

  • [→ git 07-12] Supplier-import-v2 LENS-3 FE-dialog-UX: SupplierImportDialog+SuppliersPage SHA-identical 2-app; dialog 2-step preview→confirm round-trips preview.rows → per-row edit feasible; ExpectedHeaderTokens 30-token baked SupplierExcelImportService.cs:35-68 = template single-source; Mã NCC=Code; import authz-mismatch BE [Roles=Admin,CatalogManager] vs FE Suppliers/Create open. Tag [s112, supplier-import-v2, fe-lens3, import-authz-mismatch].

  • [→ git+session-log 07-07] S105 BVAAU cross-repo auth RCA: Q1 root-cause = FE Home MÙ session (bundle cũ relative /api trên site TĨNH web.config loại ^/api//api/auth/me 404 → anonymous); fix API_BASE-absolute 51c69fb LIVE. Q2 CRM1 hở 2 tầng (FE soft + API enforceCrmGate:false) → flip AUTH_ENFORCE_CRM_GATE=true. Q3 Zalo "User_ID" KHÔNG có UI. Class "hub+site-tĩnh relative-/api chết im prod"; #53-garble-7 → SendMessage-resume recover. (verbatim → archive/2026-07.md)

  • [→ 07-12 LENS-3 entry above + git 07-06] S104 Supplier 30-field 🅰️ schema-invest WF wf_5ac2cdb0: SUPERSEDED anchors giữ: ClosedXML 0.105.0 = Excel-standard (KHÔNG OpenXml-raw, csproj:8); reuse-existing-cols>parallel; UpdateSupplierCommand.cs:49-57 blind-set=latent#73; seed fill-nulls-if-exists (DbInitializer.cs:2781); SupplierDto hand-projected 2-site (GetSupplierQuery.cs:21+ListSuppliersQuery.cs:48-50); Dialog.tsx:48 max-h-70vh; extract ui/PathLink.tsx. Chốt Mig 62 +18 nullable. (verbatim → archive/2026-07.md)

  • [→ git+session-log 07-03 + adap-reports] S101 H19-adopt Lane-2: map reviewer=review-gate / investigator=ground-truth-lane; 12-pt tier-checklist ALL (11/11 inherit, C3 no-[1m]-in-frontmatter); toggle-marker MUST copy .gitignore:87 last-match placement; VACUOUS-MET all-inherit+Fable. (verbatim → archive/2026-07.md)

  • [→ git+session-log 07-02 + adap-reports] S100 H18-adopt WF1: ghost-wire-class config-key-defined-but-unread (budget.json:54-55 script re-hardcode same-value→no-flag; catch=grep-key-across-scripts); cron=ghost-wire (CronList=0); _ledger orphan-catch 0/15-lifetime. (verbatim → archive/2026-07.md)

  • [→ git 07-12 · Mig64 IsPublic shipped since] Supplier import-v2 LENS-4 public/visibility recon: 3 SELECTION consumers ALL hit GET /suppliers ListSuppliersQuery (SuppliersPage:83 · PeDetailTabs:2222 · ContractCreatePage:321); DISPLAY-of-existing joins by stored SupplierId MUST NOT filter (ContractFeatures/PeFeatures/Dashboard); write-guard backstops ContractFeatures.cs:64+PurchaseEvaluationSupplierFeatures.cs:49. Rec fail-closed default + stored IsPublic bit. Tag [s112b, supplier-visibility, fail-closed-default].

  • [all verbatim → archive/2026-07.md] S98 verify-lane (detector 28→25, 8 derived-stale=FP vs canonical 61/89/440/79; grep exact misses README variant) · S97 feedback-audit (#77/#78/#79 gotchas.md:1301/1317/1325; #53-garble×6=cicd MEMORY-self-target ~17.5KB; Mig60 wrong-table Approvals→Mig61 Changelogs) · 07-01 Supplier-predecessor SUPERSEDED by 07-06 · S93 MFE denom=marks/AS/guards dedup-AS-xref=29, coverage exact-id OR ≥2-content-word.

  • PE FROZEN-Mig59 patchwork + go-live recon cluster (S87→S89, 8 entries verbatim → archive/2026-06.md): key catches — AREA-4 LATENT #73-class BUG HoSoLink absolute-set PurchaseEvaluationFeatures.cs:280 but PeHeaderForm PUT OMITS→clears (2 PUT mutually destructive, no preserve-test) · AREA-3 AllowApproverFinalize AUTO(Mig58)+finalizeByCcmDelegation OPT-IN(Mig54) coexist AUTO-first, ApplyApprovedPrice allow-list {Ncc,ProMin,ProMax,Ccm} · AREA-2 budget-matrix band-aid PeSuggestedPriceFeatures.cs:153-199 PRO=drafter vs CCM=role authz-asymm · AREA-6 FE all 6-comp+3-pages SHA-mirror 2-app, #70 stale-echo · S89 AllowApproverFinalize-NOTE GAP BE-field-MỚI (flag only currentLevelOptions, DTO no-carry→expose EndsBeforeCeo) · 06-24 winner=SINGLE SelectedSupplierId derived-3-site, terminal=per-Level bool · 06-23 urgent authz asymmetric, PE-create dropdown PeWorkspaceCreateView.tsx:94.

  • 2026-06-20 governance recon (both → archive/_INDEX): (a) landing-map — harness-11-engine.md=CANONICAL engine (D5/6/7 safety-tier+D8 one-dir-lock+D9 single-writer+D10 Bash-residual+CAVEAT no-OS-hook); error-ledger.md=§L.a AS-1..13+§L.b 7-step; rules.md §6.6=objective-criteria; report-before-stamp ⊂ D7 (extend not duplicate→C3 vocab-fork). (b) Harness-14 = age/recency-decay KHÔNG căn-cứ cắt feature; memory-budget.json 0 decay keep_floor=5=newest-protect drains-OLDEST; detectors canonical-anchor-vs-STATUS+disk 0 age-window; EVAL golden-set-solution_erp.jsonl 14q recall@5≥0.7 weekly-manual; anti-downgrade=H8 all-inherit PARTIAL (no generic rule grep 0).

  • PE recon cluster (S69→S76, verbatim → _INDEX): "Giá chào thầu" mục-c=WinnerQuoteTotal=SUM(Quote.ThanhTien WHERE supplier==Selected) DERIVED 3-site; Budget gate=PURE ROLE no-phase (canEditPro/Ccm PurchaseEvaluationFeatures.cs:800-801); submission-count-lock NEXISTS (grep 0); Value-threshold HOOK B=ApproveV2Async :816-845; PRO/CCM/CEO=Procurement/CostControl/Director shorthand; V2 routing IGNORES roles (=ApproverUserId) 100% LINEAR.

  • Office/HRM recon cluster (S65→S69, verbatim → _INDEX): 21 Off_* keys, 10 office pages {fe-admin,fe-user}/src/pages/office/ SHA-mirror (exc MyAttendance+AttendanceReport admin-only); golive-flip=remove RevokeTemporarilyHiddenModulesAsync DbInitializer.cs:2040; Employee master-detail EXISTS, Dept FLAT pre-Mig51; NamGroup PURO=UI-skin hardcoded-navTree; gotcha #66 index.css h1-4{color} OUTSIDE @layer→TW-v4 unlayered wins→heading MUST text-white!.

  • Governance/Harness recon cluster (S71, → _INDEX): H8 all-inherit FULLY adopted both layers (12/12 frontmatter + hmw.js resolveModel); run-trace "TRACKED" = 2-level (git check-ignore eligible vs git ls-files committed — model works only post git add); G-015 containment shift (Harness-2 "mọi tracked=vi-phạm" → H10 "tracked NGOÀI run-folder+code-disjoint=vi-phạm"). path-trap: bare runs/ from repo-root = 0 → actual .claude/workflows/runs/ (22 tracked). detector refine(b) = .claude/hooks/.claude/scripts not-exist (now S75 has scripts/governance-detectors.ps1).

  • [→ git pre-S60] S60 recon#2 V2-engine-map (ApproveV2Async:446-634 guard+UPSERT+advance; skipToFinal F2:561-602 precedent) · S60 PE Section-3 submit-guard ROLE-only. Full text git.

  • [→ archive/2026-06.md + git] S52 P11-D/E/F 6-gap recon · S50 HrmConfigs add-kind 11-spot · S51 gotcha #57 EXT reachability (curated S59).

  • [→ archive/2026-05-q4.md + git d2f52ba] S29-S37: clean-room > NamGroup-port verified 4× · Pattern 12-bis cross-module mirror · FK+freetext dual-write.

  • 2026-07-13 PE negative-quote LENS edge/precedent/test (fable-clone, RETURN-only; complements Budget-consumers entry ↑): BE+DB đã cho âm; blocker = FE helper + submit-guard. (a) parseVnd PeDetailTabs.tsx:51 strip [^\d] → minus mất; formatVndInput:52 n>0?:'' → âm+0 đều blank (lẫn "chưa báo giá"); AddSupplier gate thanhTien>0 :2226 skip quote khi ≤0 (empty≡0 by-design); inline QuoteCellDialog :2870 always-POST (store 0 OK); fe-admin SHA-identical :51/:52/:2226. (b) precedent = OMIT validator: ExpectedRemainingAmount PurchaseEvaluationFeatures.cs:348 + LeaveBalance AdjustmentDays LeaveBalanceFeatures.cs:107; Quote UpsertPurchaseEvaluationQuoteCommand DetailFeatures.cs:272 = NO validator (grep⌀) → BE nhận âm sẵn. (c) 0 test assert ThanhTien≥0. (d) gotcha #81 orthogonal (IsWinner==Any(IsSelected) bool≠sign → no phantom). (e) NO DB CHECK (HasCheckConstraint grep⌀ whole Infra; col decimal(18,2) config:131). HARD-INTERACTION submit-guard Sum()<=0 PurchaseEvaluationWorkflowService.cs:206+FE:201 → net-≤0 BLOCKED "chưa có giá"; che CCM-threshold:891. NS-giữ-nguyên architectural (quote never write PeWorkItemBudgets; âm chỉ shift winnerQuoteTotal:1188). Tag [pe-neg-quote,parsevnd-strip-minus,sum<=0-guard,no-check-constraint,omit-validator,iswinner-orthogonal].

  • [→ git 07-10] S108 first-real-run H19 cite-audit: 103/111 exact; class = worker-draft cite lệch ±1-2 quanh code-fence (audit MỞ ĐÚNG DÒNG đừng tin range) + drift-note-stale + email-fact honesty-trap. 0 garble.

  • 2026-07-12 (S111 H22 WAL deep-pass) [engine: fable-real-single · Fable-S111]: H22 WAL adopt → READY_WITH_NUANCES + spec 3-mục (em-main gov/settings · w1 pause+tiep · w2 start/end delta · w3 hook+README). Chốt: (1) .claude/settings*.json KHÔNG tồn tại → hooks-entry CREATE mới; hook = STAGED-until-verified (S100 ghost-wire, chỉ claim khi thấy wal: commit phiên mới). (2) engine:402 no-OS-hook = MÔ-TẢ (CAVEAT) không phải luật cấm; :116 E.3 "hook fails-open ≠ gate" → persist-only TƯƠNG THÍCH, update :402; ACTIVE-MARKS 0 mark cấm-hook; H5 start:41 chỉ cấm hook-switch MODEL. (3) AS-6 KHÔNG tăng: 2 runtime .json gitignored (.gitignore:124-125), hook commit LOCAL — push-set ≡ hôm nay. (4) cmd-PATH Git Bash trước WSL, bash 5.2.26 OK. (5) .gitattributes exists broadcasts-scoped → append *.sh; repo 0 .sh = zero churn. (6) 16 command 0 trùng pause/tiep. (7) Stop-hook fire chỉ TURN-boundary → chết giữa workflow-turn = vật-liệu DISK uncommitted, /tiep đọc cả git status/disk. (8) run.md thiếu taskList snapshot. Learned: "luật cấm hook" phải phân MÔ-TẢ vs LUẬT trước khi đòi carve-out. L1@19.8KB → suggest em-main curate.

  • 2026-07-11 (S110 H21+MTv3 deep-pass) [engine: fable-real-single · Fable-S110]: Task ground-truth 2 broadcast (H21 spec-file+per-invocation · MTv3 owner-choice) + inventory TOKEN toàn repo + SPEC 3-mục. Verdict PASS: (1) 12 persona file SẠCH 0-hit fable/engine-token (grep 2 vòng cả engine-đắt|top-model|ensemble) — NGƯỢC hub vòng-1 bắt persona-phụ lỗi; (2) MTv3 self-check regex §5 chính-thức 0-hit nhưng extended "lead LUÔN top-model" bắt 5 ACTIVE (engine:332 K.D · runbook:140/:455 · fable-real.md:17 · mark ACTIVE-MARKS:19) = regex-heuristic-miss class — sister diễn-đạt khác cụm regex; (3) hmw.js:38 comment "tier:'fable' khi hệ-trọng" = xung-đột MTv3 §1.3/H21 §3 (đường nâng hạng-nhất DUY NHẤT = owner gõ; comment cho lead-discretion) — comment-only fix; (4) hmw-mode.on = HỆ KHÁC (consent fan-out T3 ultracode-hmw-mem-governance, content tự khai /ultra-on) — ngoài scope H21; (5) mega-line "VẪN ON" class = standing-imperative-trong-history-blurb (S109-header + HANDOFF NEXT-anh = ACTIVE cần sửa; blurb-body = snapshot giữ). Bẫy fidelity lớn nhất: MTv3 §1.2/1.3 "sub gán cứng hạng-hai" đọc như floor → tưởng phá H8 all-inherit; triage-reply S2 CÙNG NGÀY waive đích-danh ("không đổi gì với form all-inherit"). ⚠️ #53 garble lượt return đầu (trả status-line giữa-chừng thay verdict) → coordinator SendMessage re-emit trong-session = recover OK, diary ghi trước re-emit.


🔄 Curate trigger

  • ~30KB → archive recent → L2 archive/<period>.md (byte-exact append) + _INDEX.md substring pointer. Stale >3mo → remove.

  • Last curate: 2026-07-06 (em-main single-writer, hook-triggered @21.4KB) — 6 stale governance/superseded entries (S93/S97/S98/S100/S101 + 07-01 Supplier-predecessor) verbatim → archive/2026-07.md, replaced with pointer-stubs. L1 back under target.
  • Prev curate: 2026-06-18 S71 (29.8→23.2KB FIFO-trim 3 + gist gen:2). Prev S70 (47.0→24.1KB dark-matter recovery + built _INDEX/gist). Prev S40 (35.7→~20KB).