mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-24 20:28:16 +02:00
assistant notes below each note
This commit is contained in:
parent
6040c54807
commit
de7d6b7a10
2 changed files with 81 additions and 5 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")}`;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue