| name | platty-memory |
| description | Use when recording, updating, or removing human knowledge (why, corrections, constraints) anchored to Platty epics, documents, or document items. |
Platty Memory
Analytics Attribution
For direct invocation, set PLATTY_INVOCATION_SOURCE=platty-memory on every
Platty CLI process in this workflow. If an outer user-facing workflow routes
here, the outer workflow label wins and overrides this default. Preserve the
active label for retries, resumes, and every nextCommand or
nextAction.command execution.
PLATTY_INVOCATION_SOURCE=platty-memory platty memory list --project <project> --json
Use this skill when the user states domain knowledge that Platty cannot derive from code: a why, a policy background, a constraint, or a statement that generated content is wrong.
Memories are an overlay on the SOT, never part of it. They are returned by retrieval reads and injected into business-doc generation context, but they never edit document content.
When To Record
Record a memory when the user:
- explains why a rule, design, or data shape exists ("์ ์ฐ์ด D+2์ธ ์ด์ ๋ ์ฌ๋ฌดํ ์ ์ฑ
").
- corrects generated content ("์ด BR์ ํ๋ ธ์ด, ์ค์ ๋ก๋ ...").
- states a constraint or exception the code does not show.
- shares tacit knowledge about a table, field, API, screen, event, or schedule.
Also record when retrieval + code verification surfaces a fact the generated SOT
missed โ a generation gap confirmed by reading the source (e.g. an access-control
hole the docs only half-captured). Anchor it as a correction/constraint, cite the
source (file:line), and note it is as-of the current code. This is a bridge so
retrieval can surface the gap; when the miss is systemic, also fix generation so the
SOT captures it durably and the bridge memory can retire.
Do not record:
- facts the SOT already captures โ that is the SOT's job; regenerate or sync instead.
(A fact the SOT failed to capture is the gap case above, and is worth recording.)
- secrets, credentials, tokens, or PII. Memory content is sent to LLM workers (redaction exists, but do not rely on it) and survives deletion inside the revision history.
Abstraction-Level Routing
Anchor the memory at the abstraction level where the knowledge belongs:
๋๋ฉ์ธ ์ ๋ฐ์ ์ ์ฑ
/๋ฐฐ๊ฒฝ(why) โ EPIC anchor (--epic)
์ฉ์ด/๋ช
์นญ ๊ต์ โ glossary document (epic ๋ฒ์ ์ฉ์ด๋ epic glossary, ํ๋ก์ ํธ ๊ณตํต ์ฉ์ด๋ project glossary)
๋น์ฆ๋์ค ๊ท์น ๊ต์ /์์ธ โ br document
์ค๊ณ ๊ตฌ์กฐ/์ํคํ
์ฒ ๋ฐฐ๊ฒฝ โ design document
์ ์ค์ผ์ด์ค ๋ชฉ๋ก ๋จ์ ์ง์ โ ucl document item (--item-type/--item-key, key = UCL item stableKey)
ํน์ ์ ์ค์ผ์ด์ค ํ๋ฆ์ ์๋ฌต์ง/์์ธ โ ucs document
ํ
์ด๋ธ/ํ๋์ ์ค์ ์๋ฏธยท์ญ์ฌ โ data_dictionary document
API/ํ๋ฉด ๊ตฌํ ๋ํ
์ผยทํจ์ โ api_spec / screen_spec document
์ด๋ฒคํธ/์ค์ผ์ค ๋์์ ํจ์ โ event_spec / schedule_spec document
The stored level is derived from the anchor (epic for epic anchors, otherwise the document type), so anchoring at the right place is what makes the memory reach the right generation context later.
Anchor Discovery Flow
Find the anchor before adding:
Advanced memory retrieval commands:
platty epics list --project <project> --compact --json
platty epics show --project <project> --epic <epic-id> --include-docs --json
platty docs search --project <project> "<term>" --json
platty docs show --project <project> --document <doc-id> --json
For a document-item anchor (for example one UCL item), use advanced memory retrieval with docs show and copy the item's itemType and stableKey into --item-type/--item-key.
If memory list shows anchorStatus: "orphaned" (or "stale"), the anchor was deleted or regenerated by sync and the memory is stranded. Do not add+delete โ re-anchor it in place with memory reanchor so the memory and its history survive (see "Re-anchor Stranded Memory" below).
Add vs Update vs Delete
Before memory add, check what already exists on the anchor:
platty memory list --project <project> --document <doc-id> --json
platty memory list --project <project> --epic <epic-id> --json
(or use advanced memory retrieval and read the memories field already returned by docs show.)
- New knowledge on the anchor โ
memory add.
- Same topic as an existing memory โ
memory update --reason.
- Existing memory is wrong โ
memory delete --reason.
--reason is mandatory for update/delete and should quote what the user said โ it becomes the audit trail.
platty memory add --project <project> --epic <epic-id> --content "์ ์ฐ์ ์์
์ผ ๊ธฐ์ค D+2 (์ฌ๋ฌดํ ์ ์ฑ
)" --kind why --json
platty memory add --project <project> --document <doc-id> --content "<text>" --kind correction --json
platty memory add --project <project> --document <ucl-doc-id> --item-type <item-type> --item-key <stable-key> --content "<text>" --json
platty memory update --memory <memory-id> --content "<corrected text>" --reason "์ฌ์ฉ์ ๊ต์ : ..." --json
platty memory delete --memory <memory-id> --reason "์ฌ์ฉ์ ์์ฒญ: ๋ ์ด์ ์ ํจํ์ง ์์" --json
platty memory show --memory <memory-id> --json
--kind is why | correction | constraint | context (default context).
Alias memories for retrieval
Use context memories for user-confirmed domain aliases that help retrieval
normalize a raw question. Alias memories are search hints only; they are not
source-grounded business facts and must not be used as proof of behavior.
platty memory alias add --project <project> --epic <epic-id> --term "์์์น๊ตฌ" --canonical "์น๊ตฌ" --json
Prefer the narrowest confirmed anchor:
- If the alias belongs to one EPIC, anchor it to that EPIC.
- If the EPIC is not known, ask one clarifying question before recording it.
- Retrieval should use
sot glossary search --project <project> --query "<raw term>" --json;
alias memories are included in that CLI result and are not projected as glossary Markdown.
Re-anchor Stranded Memory
Sync regeneration drifts anchors: an epic is split/merged, a document is orphaned, or a use-case stableKey changes so the anchored item disappears. The memory row is never deleted โ it becomes stranded (needs_reanchor). A stranded memory is still real human knowledge; your job is to move its anchor onto the regenerated target, not to recreate or drop it.
Find stranded memories two ways:
platty memory needs-reanchor --project <project> --json
โฆor read memory/needs-reanchor.md in the SOT projection (the README flags it). Each entry gives the old-anchor clue: reason (document_orphaned | epic_deleted | anchor_null | item_missing), and the abandoned oldType/oldScope/oldScopeId.
Find the current target โ memory reanchor-candidates (don't hand-search the corpus)
Let the engine scope candidates for you. It returns the current (active) targets in the same
regeneration neighborhood โ same epic + documentType + scope for documents; same itemType in
the live parent for items; alive epics โ never a whole-corpus scan:
platty memory reanchor-candidates --project <project> --id <memory-id> --json
Each candidate carries kind (document | document_item | epic), its id (+ documentId/
itemType/stableKey for items), and a score (higher = closer match). Empty candidates means
no successor was found โ a hard-deleted anchor with no clue, or a genuinely removed target โ HOLD.
Decide: 1:1 re-anchor vs split vs merge/hold
- 1:1 (one clear current target) โ
memory reanchor. Keep the single memory; only its anchor moves. The old anchor is preserved as provenance in the revision history (a reanchor revision records prev/new anchor).
- Split (1 old โ N new targets) โ the knowledge must be divided. Create new memories on the children with
memory add, then mark the original superseded (memory delete --reason "split into <ids>"). Re-anchor is for 1:1 only.
- Merge / ambiguous / no clear target โ HOLD. Do not guess. Leave the memory stranded and tell the user which memory needs a human decision. A wrong re-anchor silently attaches a correction to the wrong rule โ worse than leaving it visibly stranded.
platty memory reanchor --project <project> --id <memory-id> --to-document <doc-id> --reason "<why this is the regenerated target>" --actor <agent-name> --json
platty memory reanchor --project <project> --id <memory-id> --to-item <doc-id> <item-type> <item-stable-key> --reason "..." --json
platty memory reanchor --project <project> --id <memory-id> --to-epic <epic-id> --reason "..." --json
After a reanchor, memory show lists the reanchor revision (prev/new anchor) and anchorStatus returns to active. Re-project the SOT (below) so memory/needs-reanchor.md clears.
Re-anchor Stop Conditions
STOP and HOLD (do not re-anchor) when any is true:
- Candidate scoping yields zero current targets โ the thing was genuinely deleted; park the memory and report it.
- Candidate scoping yields multiple plausible targets and you cannot prove which one from the old-anchor clue + content โ ambiguous; ask the user.
- The move would be a merge (several stranded memories onto one target with conflicting content) โ keep both/park and surface to the user.
- You are tempted to edit the memory content to make it fit a target โ re-anchor moves the anchor only; rewriting content to fit is fabrication.
Re-anchor Red Flags
| Red flag | Why it's wrong | Do instead |
|---|
memory delete + memory add to "move" an anchor | Drops the memory's identity and history; loses provenance | memory reanchor (1:1) keeps the row and records the move |
| Re-anchoring to the closest-looking doc without the old-anchor clue | Silently attaches knowledge to the wrong rule | Match on oldType/oldScopeId + content; HOLD if unsure |
| Re-anchoring on a guess to clear the warning | Optimizes the dashboard, corrupts the SOT overlay | A visibly stranded memory is safer than a wrongly anchored one |
| Treating a 1โN split as a single re-anchor | The original knowledge belongs to several targets | Split: add new memories, supersede the original |
Re-project The SOT After Writing (write-back loop)
The SOT Markdown folder (~/.platty/sot/<projectId>/) is a read-only projection.
A memory add/update/delete writes the DB but the projected memory.md files do
not change until a re-export. Until then any agent reading the Markdown (the
authoritative cross-session discovery surface) silently misses your write.
Close the loop every time you mutate memory:
platty memory add --project <project> --document <doc-id> --content "<text>" --kind correction --export-sot --json
platty sot export --project <project> --json
The memory add response's nextAction points at sot export whenever you did
not pass --export-sot โ follow it. Skipping the re-export is how a later session
answers around a constraint/correction you recorded.
Actor And Source Convention
Agents must always pass --source agent --actor <agent-name>:
platty memory add --project <project> --document <doc-id> --content "<text>" --source agent --actor <agent-name> --json
A plain memory add without these defaults to --source user --actor user and means a human typed it. Audit fields are self-reported โ acceptable for a local single-user tool, so do not misreport them.
Knowledge Questions (Elicitation Loop)
The code-derived SOT knows WHAT and HOW but not WHY/intent โ that layer only exists in
people's heads. The system surfaces the gaps as knowledge questions; your job is to ask
the human and fix each answer as a memory. A question is never a fact until answered.
platty memory questions absorb --project <project> --json
platty memory questions gap --project <project> --json
platty memory questions list --project <project> --scope doc --json
platty memory questions answer --project <project> --id <q> --content "<human's answer>" --kind why --json
platty memory questions dismiss --project <project> --id <q> --reason "<why not askable>" --json
The SOT projection also surfaces the backlog as a read file when backlog entries exist:
questions/open.md (priority-ordered, with a count + pointer in README.md) โ so an agent reading
the SOT sees "what to ask" without querying the DB. questions/coverage.md is a generated
coverage/quality surface for why/constraint/open-question coverage; use it for audit or memory
planning, not as first-pass retrieval evidence and not as a confirmed fact source.
Dialogue objective:
- Ask the human the open question, framed around the customer job it serves ("what is this
for / who relies on it / what breaks if it's wrong"), not as a code trivia quiz.
answer fixes the human's reply as a confirmed why/constraint memory on the question's
own anchor and links them โ this is the one path that turns a guess into confirmed knowledge.
- If the human doesn't know, or the question is irrelevant,
dismiss it with a reason. It is
preserved and can resurface later. Never invent an answer to clear the backlog.
- Do NOT answer on the human's behalf. If you have an inference, record it as a normal
memory add --source agent (which stays trust=proposed) โ do not launder it through
questions answer, which produces confirmed memory.
Boundary
- Memory never edits SOT. If a memory contradicts a fresh document, tell the user both exist and recommend business-docs sync or regeneration โ the memory feeds the next generation as a correction signal.
- Memories added after a generation run started appear from the next run for standard task types (context pages snapshot at run start). UCS task pages snapshot later, when their UCL is submitted, so a memory added mid-run may still reach that run's UCS tasks.
- Soft-deleted memories stay reconstructible in revision history (
memory show lists every revision with op, actor, reason, createdAt).