assistant notes below each note

This commit is contained in:
Arjun 2026-06-22 22:35:54 +05:30
parent 6040c54807
commit de7d6b7a10
2 changed files with 81 additions and 5 deletions

View file

@ -48,6 +48,7 @@ You are a memory agent. You are given one or more source files (emails, meeting
7. **Detect state changes (status updates, resolved items, role changes)**
8. Create new notes or update existing notes
9. **Apply state changes to existing notes**
10. **Maintain assistant-facing notes for every canonical note you create or update**
The core rule: **Meetings and voice memos can create notes freely. Emails require personalized content and a new People/Organization note from an email also requires the user to have replied at least once in the thread (the Email Reply Gate). Slack and connected-tool artifacts can update existing notes when they carry clear state changes, decisions, commitments, or project facts; they should create new notes only when the artifact clearly identifies a durable person, organization, project, or topic worth tracking.**
@ -977,6 +978,38 @@ One line summarizing this source's relevance to the entity:
**2025-01-15** (email): Sarah shared the contract draft.
\`\`\`
## Assistant Notes
Every canonical People, Organizations, Projects, or Topics note you create or update must include a bottom section:
\`\`\`markdown
## Assistant notes
- [2026-02-03T14:25:00.000Z] Prefers concise technical detail before pricing discussion.
\`\`\`
These notes are for future assistant context, not for user-facing summaries.
**Rules:**
- Add assistant note lines only when the source contains durable, entity-specific context worth preserving for future assistant use.
- Add one line for a single clear observation; add more only when there are multiple distinct durable observations.
- Do not add filler. If the source has no useful entity-specific observation beyond what the activity entry already captures, ensure the section exists but leave it without a new bullet.
- Use the current ISO timestamp from the Context section, not just the source date.
- Keep each line concise and specific: one durable observation about who or what the note is about.
- For people, capture subtle useful context when evidenced: working style, preferences, role changes, current company, interests, constraints, or relationship context.
- For organizations, capture useful context about relationship status, decision process, interests, constraints, or how they prefer to work.
- For projects and topics, capture current state, constraints, recurring patterns, or what the assistant should remember when helping with that project/topic.
- Prefer useful but non-obvious observations over restating the activity entry.
- Do not add guesses.
- If the note already has \`## Assistant notes\`, append new lines at the top of that section so it is reverse chronological.
- If the note lacks \`## Assistant notes\`, add the section at the very bottom.
- Deduplicate within the section: do not add the same observation again if an equivalent line already exists; refresh or update the timestamp only when the source reconfirms the same durable observation.
- Do not put user-wide preferences here; those belong in \`knowledge/Agent Notes/\`. This section is scoped to the entity note itself.
**Examples:**
- \`- [2026-02-03T14:25:00.000Z] Sarah prefers pricing options framed with implementation risk called out explicitly.\`
- \`- [2026-02-03T14:25:00.000Z] Rahul just joined Acme as VP Engineering and is still learning their vendor review process.\`
- \`- [2026-02-03T14:25:00.000Z] Acme's team tends to route security questions through procurement before engineering review.\`
---
# Step 7: Detect State Changes
@ -1131,11 +1164,13 @@ If you discovered new name variants during resolution, add them to Aliases field
- **Always use absolute paths** with format \`[[Folder/Name]]\` for all links
- Use YYYY-MM-DD format for dates
- Use ISO timestamp format for assistant notes
- Be concise: one line per activity entry
- Note state changes with \`[Field → value]\` in activity
- Escape quotes properly in shell commands
- Write only one file per response (notes and \`suggested-topics.md\` follow the same rule)
- **Always set \`Last update\`** in the Info section to the YYYY-MM-DD date of the source email or meeting. When updating an existing note, update this field to the new source event's date.
- **Keep \`## Assistant notes\` at the very bottom** for canonical People, Organizations, Projects, or Topics notes, and update it only when there is durable entity-specific context worth preserving.
- Keep \`suggested-topics.md\` curated, deduped, and capped to the strongest 8-12 cards
---
@ -1248,6 +1283,7 @@ Before completing, verify:
- [ ] Key facts are substantive (no filler)
- [ ] Open items are commitments/next steps only
- [ ] Empty sections left empty rather than filled with placeholders
- [ ] Canonical entity notes keep \`## Assistant notes\` at the bottom, with new timestamped lines only for durable entity-specific context
**State Changes:**
- [ ] Detected project status changes

View file

@ -40,7 +40,10 @@ const DEFAULT_NOTE_TYPE_DEFINITIONS: NoteTypeDefinition[] = [
{Substantive facts only. Leave empty if none.}
## Open items
{Commitments and next steps only. Leave empty if none.}`,
{Commitments and next steps only. Leave empty if none.}
## Assistant notes
- [{ISO_TIMESTAMP}] {One concise assistant-facing observation about this person.}`,
extractionGuide:
"Look for: name, role, organization, email, aliases, relationship context",
},
@ -77,7 +80,10 @@ const DEFAULT_NOTE_TYPE_DEFINITIONS: NoteTypeDefinition[] = [
{Substantive facts only. Leave empty if none.}
## Open items
{Commitments and next steps only. Leave empty if none.}`,
{Commitments and next steps only. Leave empty if none.}
## Assistant notes
- [{ISO_TIMESTAMP}] {One concise assistant-facing observation about this organization.}`,
extractionGuide:
"Look for: organization name, type, industry, relationship, domain, key people, projects",
},
@ -116,7 +122,10 @@ const DEFAULT_NOTE_TYPE_DEFINITIONS: NoteTypeDefinition[] = [
{Commitments and next steps only. Leave empty if none.}
## Key facts
{Substantive facts only. Leave empty if none.}`,
{Substantive facts only. Leave empty if none.}
## Assistant notes
- [{ISO_TIMESTAMP}] {One concise assistant-facing observation about this project.}`,
extractionGuide:
"Look for: project name, type, status, people involved, organizations, timeline, decisions",
},
@ -149,7 +158,10 @@ const DEFAULT_NOTE_TYPE_DEFINITIONS: NoteTypeDefinition[] = [
{Commitments and next steps only. Leave empty if none.}
## Key facts
{Substantive facts only. Leave empty if none.}`,
{Substantive facts only. Leave empty if none.}
## Assistant notes
- [{ISO_TIMESTAMP}] {One concise assistant-facing observation about this topic.}`,
extractionGuide:
"Look for: topic name, keywords, related people/orgs/projects, decisions, key facts",
},
@ -199,11 +211,39 @@ export function getNoteTypeDefinitions(): NoteTypeDefinition[] {
// ── Render helper ────────────────────────────────────────────────────────
function assistantNotesPlaceholder(type: string): string {
const normalized = type.toLowerCase();
if (normalized === "people") {
return "person";
}
if (normalized === "organizations") {
return "organization";
}
if (normalized === "projects") {
return "project";
}
if (normalized === "topics") {
return "topic";
}
return "entity";
}
function renderTemplateWithAssistantNotes(def: NoteTypeDefinition): string {
if (!["People", "Organizations", "Projects", "Topics"].includes(def.type)) {
return def.template;
}
if (/^## Assistant notes\b/im.test(def.template)) {
return def.template;
}
const target = assistantNotesPlaceholder(def.type);
return `${def.template.trimEnd()}\n\n## Assistant notes\n- [{ISO_TIMESTAMP}] {One concise assistant-facing observation about this ${target}.}`;
}
export function renderNoteTypesBlock(): string {
const defs = getNoteTypeDefinitions();
const sections = defs.map(
(d) =>
`## ${d.type}\n\`\`\`markdown\n${d.template}\n\`\`\``,
`## ${d.type}\n\`\`\`markdown\n${renderTemplateWithAssistantNotes(d)}\n\`\`\``,
);
return `# Note Templates\n\n${sections.join("\n\n")}`;
}