diff --git a/.opencode/commands/standup.md b/.opencode/commands/standup.md index f081372..6deab48 100644 --- a/.opencode/commands/standup.md +++ b/.opencode/commands/standup.md @@ -6,7 +6,30 @@ Generate a standup update using the latest workspace state. First, refresh Mattermost context before drafting: -!`if [ -n "$FIDELITY_MATTERMOST_SYNC_CMD" ]; then bash -lc "$FIDELITY_MATTERMOST_SYNC_CMD" >/dev/null 2>&1 || true; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh >/dev/null 2>&1 || true; fi` +!`python3 - <<'PY' +import os +import subprocess +from pathlib import Path + +cmd = os.environ.get("AIW_MATTERMOST_SYNC_CMD") or os.environ.get("FIDELITY_MATTERMOST_SYNC_CMD") +if cmd: + result = subprocess.run(["bash", "-lc", cmd], capture_output=True, text=True) +elif Path("scripts/mattermost/sync.sh").is_file(): + result = subprocess.run(["bash", "scripts/mattermost/sync.sh"], capture_output=True, text=True) +else: + print("No Mattermost sync command configured.") + raise SystemExit(0) + +if result.returncode != 0: + print("__MATTERMOST_SYNC_FAILED__") + if result.stdout: + print(result.stdout.strip()) + if result.stderr: + print(result.stderr.strip()) +else: + if result.stdout.strip(): + print(result.stdout.strip()) +PY` Read: @@ -35,7 +58,28 @@ Latest Mattermost context, preferring inbox and falling back to generated JSONL: Detailed active work item files, if available: -!`if [ -d project-knowledge/02-work-items ]; then for f in project-knowledge/02-work-items/*.md; do case "$f" in *README.md|*index.md) continue;; esac; echo "\n### $f"; cat "$f"; done; else echo "No work item files available."; fi` +!`python3 - <<'PY' +import re +from pathlib import Path + +summary = Path("project-knowledge/01-current/work-items.md") +if not summary.is_file(): + print("No work item files available.") + raise SystemExit(0) + +text = summary.read_text() +paths = re.findall(r"Detail: `(project-knowledge/02-work-items/[^`]+)`", text) +if not paths: + print("No work item files available.") + raise SystemExit(0) + +for rel in paths: + path = Path(rel) + if not path.is_file(): + continue + print(f"\n### {rel}") + print(path.read_text()) +PY` Before drafting: @@ -51,6 +95,8 @@ Before drafting: - use `project-knowledge/03-context/workstreams/flow-page-references.md` to preserve real flow/page identifiers when shorthand appears in logs or messages - for standups that will also be sent to Teams, prefer plain language over internal implementation jargon; avoid unexplained terms like `fallback` - if work is in release-process waiting state, show the parallel story work explicitly instead of implying idle waiting +- if Mattermost sync failed, acknowledge that internally and rely on the latest saved workspace context instead of inventing fresher communication +- prefer only the detailed work-item files referenced by `project-knowledge/01-current/work-items.md`; do not mine unrelated or completed ticket files unless they are explicitly active in current memory Return a standup that is: @@ -65,3 +111,6 @@ Return a standup that is: - uses bullet points for each item - groups multiple updates for the same Jira item as indented sub-bullets - uses `JIRA-ID - Title` or `JIRA-ID Title` formatting instead of comma-separated ID/title formatting +- preserves chronological order within each Jira item's sub-bullets +- omits future-sprint stories from `Today` unless they are real blockers +- is ready to copy/paste into Mattermost as Markdown diff --git a/agent-memory/behavior/agent-behavior.md b/agent-memory/behavior/agent-behavior.md index a551028..bfed79e 100644 --- a/agent-memory/behavior/agent-behavior.md +++ b/agent-memory/behavior/agent-behavior.md @@ -1,7 +1,7 @@ --- type: agent-behavior status: active -updated: 2026-04-17 +updated: 2026-04-21 tags: [process, memory, agent] --- @@ -29,6 +29,9 @@ This applies to: The agent should not wait for a separate promotion command when the right update is already clear. +- When editing `project-knowledge/`, write as a human engineer maintaining shared project documentation. +- Keep agent-operating logic out of `project-knowledge/`; store that logic in prompts, commands, skills, agents, or `agent-memory/`. + --- ## Learning Sessions diff --git a/agent-memory/memory/context-maintenance.md b/agent-memory/memory/context-maintenance.md index 00e6878..ee59e5f 100644 --- a/agent-memory/memory/context-maintenance.md +++ b/agent-memory/memory/context-maintenance.md @@ -1,7 +1,7 @@ --- type: agent-memory status: active -updated: 2026-04-17 +updated: 2026-04-21 tags: - process - memory @@ -18,6 +18,9 @@ Keep this workspace useful as living memory instead of a pile of disconnected no - Update canonical context when a durable fact changes. - Prefer correcting stale context over appending contradictory notes. +- Keep `project-knowledge/` human-facing and project-facing: write it as an engineer maintaining shared project notes, not as an AI maintaining its own operating instructions. +- Do not place agent-only logic, output contracts, prompting tactics, evaluation heuristics, or command-behavior rules in `project-knowledge/` unless a human engineer on the project would reasonably want that exact guidance there. +- Put agent behavior, prompt logic, formatting contracts, and slash-command rules in `agent-memory/`, `.opencode/commands/`, `prompts/`, `.opencode/agents/`, or `.opencode/skills/` instead of `project-knowledge/`. - If a canonical note appears in an Obsidian Base, update its frontmatter properties together with the prose content. - When changing frontmatter properties on existing canonical notes, prefer Obsidian CLI property operations through `scripts/obsidian/cli.sh` when available so YAML spacing and property formatting stay clean; fall back to direct Markdown edits only when the CLI is unavailable or the operation is unsupported. - Keep templates under `project-knowledge/09-templates/` out of real-note Bases by filtering the template folder. diff --git a/project-knowledge/03-context/process/communication-rules.md b/project-knowledge/03-context/process/communication-rules.md index 5011466..179c6ea 100644 --- a/project-knowledge/03-context/process/communication-rules.md +++ b/project-knowledge/03-context/process/communication-rules.md @@ -2,7 +2,7 @@ type: process project: fidelity status: active -updated: 2026-04-16 +updated: 2026-04-21 tags: [process, communication] --- @@ -30,8 +30,6 @@ These rules keep standups, Jira notes, and Mattermost messages aligned with the - Do not present a fix as ready if it introduces a new bug or unresolved regression - Administrative/project-tracking updates should be prompt when others are visibly waiting on them ---- - ## English Quality Rules - Write in natural, professional US English that sounds like a fluent engineer wrote it diff --git a/prompts/standup.md b/prompts/standup.md index b06ecfc..f60aa76 100644 --- a/prompts/standup.md +++ b/prompts/standup.md @@ -1,41 +1,67 @@ # Standup Prompt -Use `project-knowledge/01-current/current-work.md`, `project-knowledge/01-current/work-items.md`, the relevant files under `project-knowledge/02-work-items/`, `project-knowledge/03-context/project.md`, `project-knowledge/03-context/workstreams/index.md`, `project-knowledge/03-context/process/communication.md`, `project-knowledge/04-people/manager.md`, the previous workday Mattermost context, today's daily note if present, and the latest available Mattermost context. +Use `project-knowledge/01-current/current-work.md`, `project-knowledge/01-current/work-items.md`, the detailed files referenced from that active-work summary, `project-knowledge/03-context/project.md`, `project-knowledge/03-context/workstreams/index.md`, `project-knowledge/03-context/process/communication.md`, `project-knowledge/04-people/manager.md`, the previous workday Mattermost context, today's daily note if present, and the latest available Mattermost context. Generate a standup update for an iOS engineer working on Fidelity. -Requirements: +## Output contract + +- Return exactly three sections in this order: `Yesterday:`, `Today:`, `Blockers:` +- Return Markdown that is ready to copy/paste directly into Mattermost +- Use one top-level bullet per Jira item +- Use indented sub-bullets only when they improve clarity +- Prefer one concise sub-bullet when nearby events are part of the same continuous context +- Keep sub-bullets in chronological order within each Jira item +- Keep the whole standup concise and ready to send + +## Selection rules - Use the most recent context only -- Be specific about what was worked on during the previous workday, not necessarily the previous calendar day +- `Yesterday` must describe work that actually happened on the previous workday, not older status changes that still appear in current memory - On Mondays, use Friday's work context unless a later prior day has Mattermost activity - If the previous calendar day has no work activity or is OOO/weekend, use the latest prior day with Mattermost activity -- Mention debugging findings only if they materially changed understanding -- Clarify auth-dependent behavior when relevant +- Treat the previous workday communication context as the primary source for `Yesterday` +- Use current memory to disambiguate, not to backfill unrelated older events +- Prefer updates directly tied to active work items over side questions, context refreshes, or manager-only reminders +- Exclude items that are not directly tied to a story unless they are true blockers +- Do not mention stories assigned to a future sprint unless they are a real blocker for today's work +- Do not include `Today` items that are known not to be worked on today + +## Story handling rules + - Mention Jira IDs and approved titles when they are available and clearly tied to the reported work - Prefer including story titles whenever a reported update maps clearly to a Jira item - Prefer story-based reporting when the work maps clearly to a Jira item -- Prefer updates directly tied to active work items over side questions, context refreshes, or manager-only reminders -- If documentation or root cause updates directly support a story, group that work under the related story instead of reporting it as a separate unrelated item -- Avoid vague phrases and generic progress language -- Separate the main issue from unrelated follow-up work unless both are explicitly relevant today -- Omit standup items that are not directly related to a story unless they are a real blocker -- Prefer evidence-backed statements over assumptions +- If documentation, root-cause analysis, or implementation analysis directly supports a story, group that work under the related story instead of listing it separately +- When one Jira item has multiple concrete updates, keep them under one top-level `JIRA-ID - Title` bullet +- When pairing a Jira ID with a title, prefer `ID - Title` or `ID Title`; do not use commas between them + +## Writing rules + - Write in natural US English that can be forwarded externally without rewriting - Write the standup as David's external progress report -- For standups that will also be sent to Teams, prefer plain outcome language over internal implementation jargon; avoid terms like `fallback` unless they are explained well enough for a broader audience +- Be specific, concise, and evidence-backed +- Avoid vague phrases and generic progress language +- Mention debugging findings only if they materially changed understanding +- Clarify auth-dependent behavior when relevant +- Separate external issues from regressions when that distinction matters +- For standups that may also be sent to Teams, prefer plain outcome language over internal implementation jargon; avoid unexplained terms like `fallback` - If a release or propagation step is waiting on approvals or pipeline work, make the parallel work explicit instead of sounding like the day is blocked on waiting alone - Do not mention Jeff by name - Do not mention Mattermost because it is internal-only communication -- Use bullet points for each item -- When one Jira item has multiple concrete updates, use one top-level Jira bullet and indented markdown sub-bullets instead of repeating the same Jira ID/title multiple times -- When pairing a Jira ID with a title, prefer `ID - Title` or `ID Title`; do not use commas between them -- Keep the sub-bullets in chronological order within each Jira item -- Do not mention stories assigned to a future sprint unless they are a real blocker for today's work -- Do not include "today" items that are known not to be worked on today -- Return Markdown that is ready to copy/paste directly into Mattermost -- Prefer one concise sub-bullet when nearby events are part of the same continuous context; split into multiple sub-bullets only when separation improves clarity -- Keep it concise and ready to send + +## Compression rules + +- Combine closely related events into one sentence when they share the same context and timeline +- Split into multiple sub-bullets only when separation improves accuracy or readability +- Prefer direct chronological phrasing such as `Started by...`, `Then...`, `Later...` when that keeps one bullet accurate and concise + +## Anti-patterns to avoid + +- Do not report a story as worked yesterday just because it is now `Done` +- Do not pull old closure events from durable memory into a new standup unless they happened on the previous workday +- Do not mention next-sprint work in `Today` when today's plan is already known and different +- Do not turn context notes into fake progress lines Format: