Promote an intake signal (or provisional proposal) into a curated memory entry — opens a PR and runs the admission gate.
Scanned 6/5/2026
Install via CLI
openskills install event4u-app/agent-config---
model_tier: medium
name: memory:promote
pack: meta
tier: 2
cluster: memory
sub: promote
description: Promote an intake signal (or provisional proposal) into a curated memory entry — opens a PR and runs the admission gate.
skills: [file-editor]
suggestion:
eligible: false
rationale: "Curation pipeline — overlaps /memory-add; keep explicit."
workspaces:
- agent-config-maintainer
packs:
- meta
---
# /memory promote
Moves an entry from the provisional layer (intake JSONL) into the
curated layer (`agents/memory/<type>.yml` or sharded). Promotion is
gated by
[`scripts/check_memory_proposal.py`](../../../scripts/check_memory_proposal.py),
which enforces the **pattern-vs-one-off** discipline: either ≥ 2
distinct paths share the root-cause signature, or the submitter
supplies ≥ 3 concrete future decisions that will be steered by the
entry.
## Prerequisites
- The signal already exists in `agents/memory/intake/signals-*.jsonl`
via [`/propose-memory`](propose-memory.md) or a producer
(`/bug-fix`, `/do-and-judge`, incident-role exit).
- The user can name the intake `id` (e.g., `sig-abc123`). If not,
route to the read side:
`./agent-config memory:lookup --types <type> --key <hint>` to
surface candidates.
## Steps
### 1. Confirm the signal id
```
> Which intake signal are we promoting?
>
> 1. Paste `sig-xxxxxx`
> 2. Search by path/body — I'll list candidates
```
### 2. Run the admission gate
```bash
./agent-config memory:check-proposal --intake-id <sig-id>
```
If the gate reports failures, show them to the user numbered and ask:
```
> 1. Strengthen evidence — run /propose-memory again to add sibling paths
> 2. Fill `future_decisions:` — I'll edit the intake entry's metadata
> 3. Abandon promotion — the finding stays as intake
```
**Do NOT bypass the gate.** If the user insists, stop and require
explicit confirmation with `--force` intent. Never silently edit the
gate script to lower the bar.
### 3. Draft the curated entry
Using the schema in
[`engineering-memory-data-format`](../../docs/guidelines/agent-infra/engineering-memory-data-format.md),
hydrate the full frontmatter:
- `id` — kebab-case slug (not the `sig-*` id — that is an intake marker).
- `status: active`, `confidence: medium` (unless the pattern is old
and well-validated — then `high`).
- `source:` — at minimum the intake jsonl file + line number.
- `owner:`, `last_validated: <today>`, `review_after_days:`.
- `priority:` — optional (`critical` | `normal` | `low`); defaults to
`normal` when omitted. Pass through from the intake signal if it
carries one. Mark `critical` only when the entry is meant to surface
on every `/memory:load` regardless of query — e.g. a tenant-isolation
invariant or a payment-flow rule. The validator warns when a type
accumulates more than 10 active critical entries; raise the bar
deliberately. See [`engineering-memory-data-format`](../../docs/guidelines/agent-infra/engineering-memory-data-format.md)
§ Priority semantics for the full contract.
- `ts_week:` — optional ISO-week stamp `YYYY-Www` (e.g. `2026-W17`).
**Convention, not enforced.** Stamp the curated entry with the week
it was promoted, never the day or hour. ISO-week granularity prevents
intra-week timing inference (e.g. "this rule was added Tuesday 3pm
→ that's when the incident hit") while keeping useful long-term
ordering. Write it via:
```bash
date -u +'%G-W%V' # POSIX ISO week-numbering year + ISO week
```
See [`engineering-memory-data-format`](../../docs/guidelines/agent-infra/engineering-memory-data-format.md)
§ Temporal jitter for rationale.
- Type-specific fields (`rule`, `symptom`, `path`, …).
If the intake signal carries `tags: [<one>, <two>]`, **resolve via tag
intersection** (do not pick by file extension):
| Tags on signal | Curated target |
|---|---|
| `[convention]` | `agents/memory/conventions.yml` |
| `[invariant]` | `agents/memory/domain-invariants.yml` |
| `[gotcha]` | `agents/memory/operational-gotchas.yml` |
| `[pattern]` | `agents/memory/recurring-patterns.yml` |
| `[gotcha, invariant]` | `domain-invariants` (invariant wins — structural beats operational) |
| `[pattern, gotcha]` | `recurring-patterns` (pattern wins — repetition beats one-off) |
| `[convention, invariant]` | `domain-invariants` (invariant wins) |
If the user disagrees with the tag-intersection result, ask which
schema to write to and record the override in the `source:` block.
Show the YAML draft and ask for confirmation before writing.
### 4. Write the curated entry (content-addressed)
Compute the content hash and write a **one-entry file** at
`agents/memory/<type>/<hash>.yml`:
```bash
HASH=$(./agent-config memory:hash --yaml /tmp/draft.yml)
mkdir -p agents/memory/<type>
mv /tmp/draft.yml agents/memory/<type>/${HASH}.yml
```
- **One entry per file** — the filename is the sha256(canonical-JSON
of the entry, first 12 hex chars). Two branches promoting the same
entry converge to the same filename and `git merge` sees an
unchanged file, not a conflict.
- **Never append** to `<type>.yml` single-file mode in content-
addressed layouts. If the consumer still uses single-file (legacy),
the command MUST detect that via `agents/memory/<type>.yml`
existence and refuse with a migration hint:
`⚠️ agents/memory/<type>.yml exists — migrate to content-
addressed first (`/memory-migrate <type>`)`.
- **Schema validation** — run `./agent-config memory:check
--path agents/memory/<type>/${HASH}.yml` before commit. On failure,
delete the file and stop.
### 5. Record the supersede link
Append a `type: supersede` line to the monthly intake JSONL:
```bash
echo '{"type":"supersede","supersedes":"<sig-id>","promoted_to":"<curated id>"}' \
>> agents/memory/intake/signals-$(date +%Y-%m).jsonl
```
This keeps the intake stream truthful — lookups will ignore the
superseded signal.
### 6. Open a promotion PR
```bash
git checkout -b memory/promote-<curated-id>
git add agents/memory/ && git commit -m "memory: promote <sig-id> → <curated-id>"
git push -u origin memory/promote-<curated-id>
# Then route to /create-pr with the memory-promote template hint.
```
### 7. Report (verbosity-gated)
Read `verbosity.post_action_reports` from `.agent-settings.yml` (default
`minimal`).
- `off` → emit nothing on success; surface errors only.
- `minimal` (default) → one line:
`→ Promoted <sig-id> → <curated-id> (PR: <url or branch>)`.
- `full` → multi-line block:
```
> ✅ Promotion drafted.
> - Signal: <sig-id>
> - Curated: <curated-id> in agents/memory/<type>.yml
> - PR: <url or branch name>
> - Next: review + merge
```
## Safety
- **Never** rewrite existing curated entries — conflicts go through
supersede-chains, not overwrites.
- **Never** promote without the gate passing — the discipline is the
value of the curated layer.
- **Never** batch-promote more than one signal per PR — each entry
deserves a focused review.
## See also
- [`/propose-memory`](propose-memory.md) — write-side entry point.
- [`/memory-add`](memory-add.md) — direct curated write (skips intake).
- [`engineering-memory-data-format`](../../docs/guidelines/agent-infra/engineering-memory-data-format.md)
No comments yet. Be the first to comment!