Compare commits
51 Commits
e4b39c4a9e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0980e6695a | |||
| abab9bb9b6 | |||
| 60868b9c96 | |||
| 7594e8ebc9 | |||
| d01ee1ac1a | |||
| cc716f8f7e | |||
| e03518e507 | |||
| ad230e1abe | |||
| 1ad707373a | |||
| 7cbb49134a | |||
| f0d3cd4ce9 | |||
| fb8a6ba2d9 | |||
| e0069fd8c6 | |||
| fc2abda588 | |||
| 7da22da168 | |||
| b7ce929c50 | |||
| 4000747641 | |||
| ab36e4b465 | |||
| 8c58210c0c | |||
| b21889c4ab | |||
| cfd61bdee3 | |||
| d3e909d39e | |||
| 9f8d3b975f | |||
| 1121433db8 | |||
| eb11bb9442 | |||
| fdbf52f811 | |||
| ee35f70c3e | |||
| 3d4da1919a | |||
| e081360a84 | |||
| d318701899 | |||
| 3816487bec | |||
| b886c61afd | |||
| 9dd731f758 | |||
| 73166b585f | |||
| f726814811 | |||
| 8950cfcdf0 | |||
| 456a4c3381 | |||
| 7fc4320f46 | |||
| 5949820347 | |||
| 286adf2d6c | |||
| bc467c8a8c | |||
| 12f3e74d39 | |||
| 767f97f3bb | |||
| b5c3ada57d | |||
| 97ef0be216 | |||
| e01b59c065 | |||
| 1c7e18d7c1 | |||
| 46c7ce2824 | |||
| 1382f1ac1a | |||
| 1c9b9fd51a | |||
| f72a828805 |
8
.agents/mcp_config.json
Normal file
8
.agents/mcp_config.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"aiw-context-mcp": {
|
||||
"url": "http://127.0.0.1:8765/mcp",
|
||||
"serverUrl": "http://127.0.0.1:8765/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,10 @@ Use this skill when the user wants a prompt for another AI assistant, GitHub Cop
|
||||
- test strategy
|
||||
- story/PR drafting
|
||||
2. Pull only the relevant context:
|
||||
- `project-knowledge/02-work-items/` for ticket-specific context
|
||||
- `project-knowledge/03-context/systems/` for component context
|
||||
- `project-knowledge/03-context/workstreams/` for recurring constraints
|
||||
- `project-knowledge/03-context/ios/` for Swift/iOS guidance
|
||||
- `workspaces/fidelity/project-knowledge/02-work-items/` for ticket-specific context
|
||||
- `workspaces/fidelity/project-knowledge/03-context/systems/` for component context
|
||||
- `workspaces/fidelity/project-knowledge/03-context/workstreams/` for recurring constraints
|
||||
- `workspaces/fidelity/project-knowledge/03-context/ios/` for Swift/iOS guidance
|
||||
3. Make the prompt self-contained.
|
||||
4. Tell the target AI what to inspect before acting.
|
||||
5. State constraints, non-goals, and validation expectations.
|
||||
|
||||
@@ -12,8 +12,8 @@ Use this skill for Swift, SwiftUI, iOS architecture, concurrency, testing, or de
|
||||
## Workflow
|
||||
|
||||
1. Identify whether the question is general Swift/iOS or Fidelity-specific.
|
||||
2. Read `project-knowledge/03-context/ios/current-practices.md` for currentness rules.
|
||||
3. Read `project-knowledge/03-context/ios/project-swift-guidance.md` when the answer may affect XFlow, Fid4, XFlowViewMaker, FTFrameworks, feature flags, or consumer validation.
|
||||
2. Read `workspaces/fidelity/project-knowledge/03-context/ios/current-practices.md` for currentness rules.
|
||||
3. Read `workspaces/fidelity/project-knowledge/03-context/ios/project-swift-guidance.md` when the answer may affect XFlow, Fid4, XFlowViewMaker, FTFrameworks, feature flags, or consumer validation.
|
||||
4. If the answer depends on current Apple APIs, Xcode versions, dependency tooling, package-manager behavior, testing frameworks, or migration guidance, verify with official/primary documentation before making strong claims.
|
||||
5. Separate:
|
||||
- current best practice
|
||||
|
||||
@@ -22,4 +22,5 @@ Use this skill for standups, daily scrum updates, end-of-day summaries, and shor
|
||||
- Use explicit work-item ID and title when available.
|
||||
- Keep the report concise and ready to send.
|
||||
- Do not mention internal evidence sources unless the user asks.
|
||||
- For Mattermost-ready standups, include a visible blank line before section headers such as `Today:` and `Blockers:`. Always verify there is an empty line immediately above `Today:` before returning the draft.
|
||||
- Use `Blockers: None` only when no blocker is visible in current memory.
|
||||
|
||||
@@ -27,4 +27,4 @@ Skills available through the shared `.agents/` surface for Antigravity-compatibl
|
||||
## Compatibility Notes
|
||||
|
||||
- `.agents/skills/` is the shared skill source intended for Antigravity-compatible and cross-tool discovery.
|
||||
- `.opencode/skills/` mirrors the installed skills for OpenCode runtime discovery.
|
||||
- OpenCode CLI also discovers `.agents/skills/`; do not mirror these skills into `.opencode/skills/`, because duplicate skill names create warnings and ambiguous discovery.
|
||||
|
||||
@@ -8,9 +8,9 @@ Read:
|
||||
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@agent-memory/workflows/ai-to-ai-prompting.md
|
||||
|
||||
Read active profile, if present:
|
||||
@@ -23,13 +23,13 @@ Relevant active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
|
||||
@@ -10,26 +10,25 @@ Inputs:
|
||||
|
||||
- `$ARGUMENTS` may contain an export path, channel names, or date filters
|
||||
- if no explicit path is given, use `AIW_SLACK_EXPORT_PATH` when available
|
||||
- Fidelity profile alias: `FIDELITY_SLACK_EXPORT_PATH`
|
||||
- otherwise, if `archives/slack/export/` exists, use it as the default import source
|
||||
- if no channels are specified, auto-detect channels using `AIW_CHANNEL_PREFIX`
|
||||
- Fidelity default prefix: `fidelity`
|
||||
|
||||
Run the importer:
|
||||
|
||||
!`prefix="${AIW_CHANNEL_PREFIX:-fidelity}"; if [ -n "$ARGUMENTS" ]; then python3 scripts/slack/import_slack_export.py $ARGUMENTS; elif [ -n "$AIW_SLACK_EXPORT_PATH" ]; then python3 scripts/slack/import_slack_export.py --export-path "$AIW_SLACK_EXPORT_PATH" --channel-prefix "$prefix"; elif [ -n "$FIDELITY_SLACK_EXPORT_PATH" ]; then python3 scripts/slack/import_slack_export.py --export-path "$FIDELITY_SLACK_EXPORT_PATH" --channel-prefix "$prefix"; elif [ -d archives/slack/export ]; then python3 scripts/slack/import_slack_export.py --export-path archives/slack/export --channel-prefix "$prefix"; else echo "Provide archive import arguments, set AIW_SLACK_EXPORT_PATH, set FIDELITY_SLACK_EXPORT_PATH, or place an extracted export in archives/slack/export."; fi`
|
||||
!`prefix="${AIW_CHANNEL_PREFIX:-fidelity}"; if [ -n "$ARGUMENTS" ]; then python3 scripts/slack/import_slack_export.py $ARGUMENTS; elif [ -n "$AIW_SLACK_EXPORT_PATH" ]; then python3 scripts/slack/import_slack_export.py --export-path "$AIW_SLACK_EXPORT_PATH" --channel-prefix "$prefix"; elif [ -d archives/slack/export ]; then python3 scripts/slack/import_slack_export.py --export-path archives/slack/export --channel-prefix "$prefix"; else echo "Provide archive import arguments, set AIW_SLACK_EXPORT_PATH, or place an extracted export in archives/slack/export."; fi`
|
||||
|
||||
Read:
|
||||
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@core/integrations/communication-model.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@agent-memory/memory/context-maintenance.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
|
||||
Imported summary, if present:
|
||||
|
||||
@@ -44,11 +43,11 @@ Instructions:
|
||||
- treat the archive as historical evidence
|
||||
- promote durable project-relevant context automatically when confidence is high
|
||||
- prefer durable role/person associations, recurring architecture patterns, repeated work-item references, approval/scope history, and process lessons
|
||||
- create or update `project-knowledge/04-people/*.md` when a human repeatedly affects project flow
|
||||
- create or update `workspaces/fidelity/project-knowledge/04-people/*.md` when a human repeatedly affects project flow
|
||||
- avoid promoting outdated daily status unless it changes current understanding
|
||||
- update existing memory when the archive clarifies or corrects it
|
||||
- keep ambiguous or likely outdated facts as archive-only context
|
||||
- write promoted memory to `project-knowledge/`
|
||||
- write promoted memory to `workspaces/fidelity/project-knowledge/`
|
||||
|
||||
Return:
|
||||
|
||||
|
||||
@@ -7,36 +7,36 @@ Use the configured live communication connector to fetch fresh evidence and main
|
||||
Preferred command sources:
|
||||
|
||||
- `AIW_MATTERMOST_SYNC_CMD`
|
||||
- Fidelity profile alias: `FIDELITY_MATTERMOST_SYNC_CMD`
|
||||
- workspace fallback: `bash scripts/mattermost/sync.sh`
|
||||
- Built-in wrapper: `bash scripts/mattermost/sync.sh`
|
||||
|
||||
Run the connector:
|
||||
|
||||
!`if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -n "$FIDELITY_MATTERMOST_SYNC_CMD" ]; then bash -lc "$FIDELITY_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No live communication sync command is configured."; fi`
|
||||
!`if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No live communication sync command is configured."; fi`
|
||||
|
||||
Read:
|
||||
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@core/integrations/communication-model.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@agent-memory/memory/context-maintenance.md
|
||||
|
||||
Fresh communication evidence:
|
||||
|
||||
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No communication evidence available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Instructions:
|
||||
|
||||
- if the sync command failed, stop and do not edit workspace memory
|
||||
- prefer local proxy mirror evidence when present; use the configured sync wrapper only when a fresh API pull is required
|
||||
- treat connector output as evidence, not automatically as project truth
|
||||
- promote only explicit, project-relevant, high-confidence facts
|
||||
- default destination is `project-knowledge/06-daily/$(date +%F).md`
|
||||
- update `project-knowledge/01-current/current-work.md` only for facts that materially change the active work window
|
||||
- update `project-knowledge/02-work-items/*.md` for explicit work-item IDs, approved titles, points, scope, and status notes
|
||||
- keep `project-knowledge/01-current/work-items.md` aligned as the compact summary of active work items
|
||||
- default destination is `workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md`
|
||||
- update `workspaces/fidelity/project-knowledge/01-current/current-work.md` only for facts that materially change the active work window
|
||||
- update `workspaces/fidelity/project-knowledge/02-work-items/*.md` for explicit work-item IDs, approved titles, points, scope, and status notes
|
||||
- keep `workspaces/fidelity/project-knowledge/01-current/work-items.md` aligned as the compact summary of active work items
|
||||
- do not write tooling noise, sync status, or generic chat chatter into project memory
|
||||
- if a fact is ambiguous, skip it rather than asking what to do
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ Read:
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@prompts/copilot-prompt.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@agent-memory/workflows/ai-to-ai-prompting.md
|
||||
@project-knowledge/03-context/ios/index.md
|
||||
@project-knowledge/03-context/ios/project-swift-guidance.md
|
||||
@project-knowledge/03-context/systems/index.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/project-swift-guidance.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/systems/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
|
||||
Active profile, if present:
|
||||
|
||||
@@ -28,13 +28,13 @@ Detailed active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
|
||||
@@ -11,14 +11,14 @@ Use these files as the baseline context:
|
||||
@agent-memory/behavior/learning-sessions.md
|
||||
@agent-memory/memory/promotion-rules.md
|
||||
@agent-memory/integrations/technical-verification.md
|
||||
@project-knowledge/00-start/start-here.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/process/communication.md
|
||||
@project-knowledge/03-context/ios/index.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/00-start/start-here.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/communication.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/index.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
|
||||
Today's date:
|
||||
|
||||
@@ -26,11 +26,11 @@ Today's date:
|
||||
|
||||
Today's canonical daily note, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Latest daily notes available:
|
||||
|
||||
!`if [ -d project-knowledge/06-daily ]; then ls -1 project-knowledge/06-daily 2>/dev/null | sort | tail -n 3; else echo "No daily notes directory available."; fi`
|
||||
!`if [ -d workspaces/fidelity/project-knowledge/06-daily ]; then ls -1 workspaces/fidelity/project-knowledge/06-daily 2>/dev/null | sort | tail -n 3; else echo "No daily notes directory available."; fi`
|
||||
|
||||
Detailed active work item files, if available:
|
||||
|
||||
@@ -38,13 +38,13 @@ Detailed active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
@@ -59,7 +59,7 @@ PY`
|
||||
|
||||
Latest Mattermost context, if available:
|
||||
|
||||
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No Mattermost context available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Respond with:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description: Force-sync Mattermost and answer from the latest matching message
|
||||
---
|
||||
|
||||
Force-refresh Mattermost first, then answer the user's question from the refreshed inbox.
|
||||
Refresh/read Mattermost first, then answer the user's question from the freshest evidence. Prefer the local proxy mirror when it is present; use the configured sync wrapper only when a fresh API pull is required.
|
||||
|
||||
Use this when the user asks for:
|
||||
|
||||
@@ -11,46 +11,13 @@ Use this when the user asks for:
|
||||
- the latest Mattermost update
|
||||
- the latest message in `fidelity-preguntas`
|
||||
|
||||
Run sync:
|
||||
Run sync/fallback refresh:
|
||||
|
||||
!`start=$(date +%s); if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -n "$FIDELITY_MATTERMOST_SYNC_CMD" ]; then bash -lc "$FIDELITY_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No Mattermost sync command is configured."; fi; status=$?; end=$(date +%s); echo "__MATTERMOST_SYNC_SECONDS__=$((end - start))"; exit "$status"`
|
||||
!`start=$(date +%s); if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No Mattermost sync command is configured."; fi; status=$?; end=$(date +%s); echo "__MATTERMOST_SYNC_SECONDS__=$((end - start))"; exit "$status"`
|
||||
|
||||
Read a focused slice of refreshed Mattermost context:
|
||||
Read a focused slice of refreshed Mattermost context, preferring the proxy mirror:
|
||||
|
||||
!`python3 - <<'PY'
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
paths = [
|
||||
Path("ai/inbox/mattermost-latest.md"),
|
||||
Path("scripts/mattermost/generated/mattermost_context.jsonl"),
|
||||
]
|
||||
|
||||
source = next((path for path in paths if path.is_file() and path.stat().st_size > 0), None)
|
||||
if not source:
|
||||
print("No Mattermost context available after sync.")
|
||||
raise SystemExit(0)
|
||||
|
||||
records = []
|
||||
for line in source.read_text().splitlines():
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
records.append(json.loads(line))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
manager_names = {"jeff", "jeff.dewitte"}
|
||||
manager_records = [
|
||||
record for record in records
|
||||
if str(record.get("username", "")).lower() in manager_names
|
||||
]
|
||||
|
||||
focused = manager_records[-10:] if manager_records else records[-15:]
|
||||
for record in focused:
|
||||
print(json.dumps(record, ensure_ascii=False))
|
||||
PY`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode focused`
|
||||
|
||||
User request:
|
||||
|
||||
|
||||
@@ -9,15 +9,15 @@ Read:
|
||||
@README.md
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
@agent-memory/memory/context-maintenance.md
|
||||
|
||||
Today's existing log, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Incorporate these new rough notes into today's log:
|
||||
|
||||
@@ -26,7 +26,7 @@ $ARGUMENTS
|
||||
Instructions:
|
||||
|
||||
- use `workspace-memory-curation` when available
|
||||
- Update or create `project-knowledge/06-daily/$(date +%F).md`
|
||||
- Update or create `workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md`
|
||||
- Maintain daily-note frontmatter for Obsidian Bases: `date`, `focus`, `work-items`, `blockers`, and `updated`
|
||||
- Preserve concrete technical meaning
|
||||
- Capture both technical findings and communication context when relevant
|
||||
|
||||
@@ -9,20 +9,20 @@ Use `professional-communication` when available.
|
||||
Read:
|
||||
|
||||
@prompts/manager-update.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/process/communication.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/communication.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
|
||||
Today's log, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Latest Mattermost context, if available:
|
||||
|
||||
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No Mattermost context available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Detailed active work item files, if available:
|
||||
|
||||
@@ -30,13 +30,13 @@ Detailed active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
|
||||
@@ -2,32 +2,36 @@
|
||||
description: Sync Mattermost context and automatically promote high-confidence project memory
|
||||
---
|
||||
// turbo-all
|
||||
Use the configured Mattermost sync command to fetch fresh communication context and maintain workspace memory automatically.
|
||||
Use the configured Mattermost sync command and/or local proxy mirror evidence to fetch fresh communication context and maintain workspace memory automatically.
|
||||
|
||||
Preferred command sources:
|
||||
|
||||
- `AIW_MATTERMOST_SYNC_CMD`
|
||||
- Fidelity profile alias: `FIDELITY_MATTERMOST_SYNC_CMD`
|
||||
- fallback: `bash scripts/mattermost/sync.sh`
|
||||
- Built-in wrapper: `bash scripts/mattermost/sync.sh`
|
||||
|
||||
Run the command and use its output as fresh communication context:
|
||||
|
||||
!`if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -n "$FIDELITY_MATTERMOST_SYNC_CMD" ]; then bash -lc "$FIDELITY_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No Mattermost sync command is configured."; fi`
|
||||
!`if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No Mattermost sync command is configured."; fi`
|
||||
|
||||
Fresh Mattermost evidence, preferring the proxy mirror:
|
||||
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Use this command implicitly when the user asks for the latest or last Mattermost message, especially messages from Jeff or the current manager.
|
||||
|
||||
Then:
|
||||
|
||||
- if the command fails, stop there and do not edit any workspace files
|
||||
- use `ai/inbox/mattermost-latest.md` if it exists and is non-empty
|
||||
- prefer the local proxy mirror via `scripts/mattermost-proxy/read-context.py --mode latest` when it has evidence
|
||||
- otherwise use `workspaces/fidelity/inbox/mattermost-latest.md` if it exists and is non-empty
|
||||
- otherwise use `scripts/mattermost/generated/mattermost_context.jsonl` if it exists and is non-empty
|
||||
- apply the memory promotion rules from `agent-memory/memory/promotion-rules.md`
|
||||
- treat Mattermost output as live communication evidence; the agent decides what becomes promoted memory
|
||||
- automatically promote explicit, project-relevant, high-confidence facts
|
||||
- default destination is `project-knowledge/06-daily/$(date +%F).md`
|
||||
- update `project-knowledge/01-current/current-work.md` only for facts that materially change the current work window
|
||||
- update `project-knowledge/02-work-items/*.md` for explicit Jira IDs, approved titles, points, scope, and status notes
|
||||
- keep `project-knowledge/01-current/work-items.md` aligned as the compact summary of active ticket files
|
||||
- default destination is `workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md`
|
||||
- update `workspaces/fidelity/project-knowledge/01-current/current-work.md` only for facts that materially change the current work window
|
||||
- update `workspaces/fidelity/project-knowledge/02-work-items/*.md` for explicit Jira IDs, approved titles, points, scope, and status notes
|
||||
- keep `workspaces/fidelity/project-knowledge/01-current/work-items.md` aligned as the compact summary of active ticket files
|
||||
- do not write tooling noise, sync status, or generic chat chatter into project memory
|
||||
- if a fact is ambiguous, skip it rather than asking the user what to do
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ Read:
|
||||
|
||||
@core/integrations/memory-vault-model.md
|
||||
@agent-memory/workflows/workspace-architecture.md
|
||||
@project-knowledge/09-templates/work-item.md
|
||||
@project-knowledge/09-templates/person.md
|
||||
@project-knowledge/09-templates/decision.md
|
||||
@project-knowledge/09-templates/system.md
|
||||
@project-knowledge/09-templates/workstream.md
|
||||
@workspaces/fidelity/project-knowledge/09-templates/work-item.md
|
||||
@workspaces/fidelity/project-knowledge/09-templates/person.md
|
||||
@workspaces/fidelity/project-knowledge/09-templates/decision.md
|
||||
@workspaces/fidelity/project-knowledge/09-templates/system.md
|
||||
@workspaces/fidelity/project-knowledge/09-templates/workstream.md
|
||||
|
||||
Instructions:
|
||||
|
||||
|
||||
@@ -8,25 +8,25 @@ Read:
|
||||
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/systems/index.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@project-knowledge/03-context/workstreams/flow-page-references.md
|
||||
@project-knowledge/03-context/process/index.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/systems/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/flow-page-references.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/index.md
|
||||
|
||||
Today's log, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Current Mattermost inbox, if present:
|
||||
|
||||
!`if [ -f ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; else echo "No Mattermost inbox file is available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Generated Mattermost context, if present:
|
||||
|
||||
!`if [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No generated Mattermost context is available."; fi`
|
||||
!`if [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No legacy generated Mattermost context is available."; fi`
|
||||
|
||||
User direction or facts to promote:
|
||||
|
||||
@@ -37,20 +37,20 @@ Instructions:
|
||||
- Promote only confirmed project-relevant facts
|
||||
- Ignore tooling noise and sync status
|
||||
- Update the smallest correct set of files among:
|
||||
- `project-knowledge/06-daily/$(date +%F).md`
|
||||
- `project-knowledge/01-current/current-work.md`
|
||||
- `project-knowledge/02-work-items/*.md`
|
||||
- `project-knowledge/01-current/work-items.md`
|
||||
- `project-knowledge/03-context/project.md`
|
||||
- `project-knowledge/03-context/systems/*.md`
|
||||
- `project-knowledge/03-context/workstreams/*.md`
|
||||
- `project-knowledge/03-context/process/*.md`
|
||||
- `project-knowledge/05-decisions/*.md`
|
||||
- `workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md`
|
||||
- `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
- `workspaces/fidelity/project-knowledge/02-work-items/*.md`
|
||||
- `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/systems/*.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/workstreams/*.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/process/*.md`
|
||||
- `workspaces/fidelity/project-knowledge/05-decisions/*.md`
|
||||
- `.opencode/commands/*.md` when command behavior needs to change
|
||||
- `prompts/*.md` when a reusable output template needs to change
|
||||
- `.opencode/agents/*.md` or `AGENTS.md` when default agent behavior needs to change
|
||||
- `.opencode/skills/*/SKILL.md` when a specialized workflow needs to change
|
||||
- `project-knowledge/00-start/*.md` when durable project onboarding guidance needs to change
|
||||
- `.agents/skills/*/SKILL.md` when a specialized workflow needs to change
|
||||
- `workspaces/fidelity/project-knowledge/00-start/*.md` when durable project onboarding guidance needs to change
|
||||
- `agent-memory/**/*.md` when agent learning, promotion, verification, or self-maintenance behavior needs to change
|
||||
- Prefer concrete project updates over broad summaries
|
||||
- If a fact is still ambiguous, do not promote it
|
||||
|
||||
@@ -10,7 +10,6 @@ Inputs:
|
||||
|
||||
- `$ARGUMENTS` may contain an export path, channel names, or date filters
|
||||
- if no explicit path is given in the arguments, use `AIW_SLACK_EXPORT_PATH` when available
|
||||
- Fidelity profile alias: `FIDELITY_SLACK_EXPORT_PATH`
|
||||
- otherwise, if `archives/slack/export/` exists, use it as the default import source
|
||||
- if no channels are specified, auto-detect channels using `AIW_CHANNEL_PREFIX`
|
||||
- Fidelity default prefix: `fidelity`
|
||||
@@ -20,21 +19,21 @@ Inputs:
|
||||
|
||||
First, run the importer:
|
||||
|
||||
!`prefix="${AIW_CHANNEL_PREFIX:-fidelity}"; if [ -n "$ARGUMENTS" ]; then python3 scripts/slack/import_slack_export.py $ARGUMENTS; elif [ -n "$AIW_SLACK_EXPORT_PATH" ]; then python3 scripts/slack/import_slack_export.py --export-path "$AIW_SLACK_EXPORT_PATH" --channel-prefix "$prefix"; elif [ -n "$FIDELITY_SLACK_EXPORT_PATH" ]; then python3 scripts/slack/import_slack_export.py --export-path "$FIDELITY_SLACK_EXPORT_PATH" --channel-prefix "$prefix"; elif [ -d archives/slack/export ]; then python3 scripts/slack/import_slack_export.py --export-path archives/slack/export --channel-prefix "$prefix"; else echo "Provide Slack import arguments, set AIW_SLACK_EXPORT_PATH, set FIDELITY_SLACK_EXPORT_PATH, or place an extracted export in archives/slack/export."; fi`
|
||||
!`prefix="${AIW_CHANNEL_PREFIX:-fidelity}"; if [ -n "$ARGUMENTS" ]; then python3 scripts/slack/import_slack_export.py $ARGUMENTS; elif [ -n "$AIW_SLACK_EXPORT_PATH" ]; then python3 scripts/slack/import_slack_export.py --export-path "$AIW_SLACK_EXPORT_PATH" --channel-prefix "$prefix"; elif [ -d archives/slack/export ]; then python3 scripts/slack/import_slack_export.py --export-path archives/slack/export --channel-prefix "$prefix"; else echo "Provide Slack import arguments, set AIW_SLACK_EXPORT_PATH, or place an extracted export in archives/slack/export."; fi`
|
||||
|
||||
Read:
|
||||
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@core/integrations/communication-model.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/systems/index.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@project-knowledge/03-context/process/index.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/systems/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/index.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
|
||||
Imported summary, if present:
|
||||
|
||||
@@ -55,7 +54,7 @@ Instructions:
|
||||
- durable role/person associations
|
||||
- recurring architecture or debugging patterns
|
||||
- past approvals or decisions that still matter
|
||||
- create or update `project-knowledge/04-people/*.md` when the archive shows a human repeatedly contributing across channels, years, or high-signal technical/process discussions
|
||||
- create or update `workspaces/fidelity/project-knowledge/04-people/*.md` when the archive shows a human repeatedly contributing across channels, years, or high-signal technical/process discussions
|
||||
- store people conservatively:
|
||||
- exact role only when explicitly supported by the archive
|
||||
- otherwise store collaboration pattern, communication style, and project relationship
|
||||
@@ -70,7 +69,7 @@ Instructions:
|
||||
- avoid promoting outdated daily status unless it changes current understanding
|
||||
- update existing memory when the archive clarifies or corrects it
|
||||
- if historical facts are ambiguous or likely outdated, summarize them as archived context instead of promoting them
|
||||
- write promoted memory to `project-knowledge/`
|
||||
- write promoted memory to `workspaces/fidelity/project-knowledge/`
|
||||
|
||||
Return:
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import subprocess
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
cmd = os.environ.get("AIW_MATTERMOST_SYNC_CMD") or os.environ.get("FIDELITY_MATTERMOST_SYNC_CMD")
|
||||
cmd = os.environ.get("AIW_MATTERMOST_SYNC_CMD")
|
||||
today = datetime.now().astimezone().date().isoformat()
|
||||
|
||||
commands = []
|
||||
@@ -66,20 +66,20 @@ PY`
|
||||
Read:
|
||||
|
||||
@prompts/standup.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/workstreams/flow-page-references.md
|
||||
@project-knowledge/03-context/process/communication.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/flow-page-references.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/communication.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
|
||||
Today's log, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Latest refreshed Mattermost context, if present:
|
||||
|
||||
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No refreshed Mattermost context available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode standup --today $(date +%F)`
|
||||
|
||||
Detailed active work item files, if available:
|
||||
|
||||
@@ -87,13 +87,13 @@ Detailed active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
@@ -118,11 +118,11 @@ Before drafting:
|
||||
- if documentation or root cause updates directly support a story, roll them into that story's update instead of listing them separately
|
||||
- exclude items that are not directly tied to a story unless they are true blockers
|
||||
- when one Jira item has multiple concrete updates, group them under one top-level `JIRA-ID - Title` bullet with indented markdown sub-bullets instead of repeating the same Jira line
|
||||
- use `project-knowledge/03-context/workstreams/flow-page-references.md` to preserve real flow/page identifiers when shorthand appears in logs or messages
|
||||
- use `workspaces/fidelity/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
|
||||
- prefer only the detailed work-item files referenced by `workspaces/fidelity/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:
|
||||
|
||||
@@ -140,4 +140,5 @@ Return a standup that is:
|
||||
- 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
|
||||
- includes a visible blank line before `Today:` and before `Blockers:` when present; before returning, verify there is an empty line immediately above each section header so Mattermost renders it correctly
|
||||
- is ready to copy/paste into Mattermost as Markdown
|
||||
|
||||
@@ -21,22 +21,22 @@ Read:
|
||||
@core/README.md
|
||||
@core/memory/operational-memory.md
|
||||
@prompts/story-draft.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@project-knowledge/03-context/process/communication.md
|
||||
@project-knowledge/03-context/process/jira-story-rules.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/communication.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/jira-story-rules.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
|
||||
Today's log, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Latest Mattermost context, if available:
|
||||
|
||||
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No Mattermost context available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Detailed active work item files, if available:
|
||||
|
||||
@@ -44,13 +44,13 @@ Detailed active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
|
||||
@@ -6,14 +6,14 @@ Answer the user's Swift/iOS programming question using current iOS practices and
|
||||
|
||||
Read:
|
||||
|
||||
@project-knowledge/03-context/ios/index.md
|
||||
@project-knowledge/03-context/ios/current-practices.md
|
||||
@project-knowledge/03-context/ios/project-swift-guidance.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/current-practices.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/project-swift-guidance.md
|
||||
@agent-memory/integrations/technical-verification.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/systems/index.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/systems/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
|
||||
User question:
|
||||
|
||||
|
||||
@@ -7,20 +7,20 @@ Use this command when new information should become part of the persistent works
|
||||
Read:
|
||||
|
||||
@README.md
|
||||
@project-knowledge/00-start/start-here.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/systems/index.md
|
||||
@project-knowledge/03-context/workstreams/index.md
|
||||
@project-knowledge/03-context/workstreams/flow-page-references.md
|
||||
@workspaces/fidelity/project-knowledge/00-start/start-here.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/systems/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/workstreams/flow-page-references.md
|
||||
@agent-memory/memory/context-maintenance.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
|
||||
Today's existing log, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
New information to incorporate:
|
||||
|
||||
@@ -31,21 +31,21 @@ Instructions:
|
||||
- use `workspace-memory-curation` when available
|
||||
- Treat direct user corrections and learning-session updates as memory sources.
|
||||
- For learning-session updates, prefer durable project understanding over transient ticket status.
|
||||
- Route durable learning to architecture/process/system/workstream notes; route only truly current operational state to `project-knowledge/01-current/` or `project-knowledge/06-daily/`.
|
||||
- Route durable learning to architecture/process/system/workstream notes; route only truly current operational state to `workspaces/fidelity/project-knowledge/01-current/` or `workspaces/fidelity/project-knowledge/06-daily/`.
|
||||
- If the new information corrects the agent's uncertainty handling or recurring behavior, update the command, prompt, agent, skill, or process rule that controls that behavior.
|
||||
- Decide whether the new information belongs in:
|
||||
- today's daily note: `project-knowledge/06-daily/$(date +%F).md`
|
||||
- current work: `project-knowledge/01-current/current-work.md`
|
||||
- work items: `project-knowledge/02-work-items/*.md`
|
||||
- active work summary: `project-knowledge/01-current/work-items.md`
|
||||
- project overview: `project-knowledge/03-context/project.md`
|
||||
- systems: `project-knowledge/03-context/systems/`
|
||||
- workstreams: `project-knowledge/03-context/workstreams/`
|
||||
- process: `project-knowledge/03-context/process/`
|
||||
- manager mapping: `project-knowledge/04-people/manager.md`
|
||||
- people roster: `project-knowledge/04-people/index.md`
|
||||
- people notes: `project-knowledge/04-people/*.md`
|
||||
- decisions: `project-knowledge/05-decisions/`
|
||||
- today's daily note: `workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md`
|
||||
- current work: `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
- work items: `workspaces/fidelity/project-knowledge/02-work-items/*.md`
|
||||
- active work summary: `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
- project overview: `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
- systems: `workspaces/fidelity/project-knowledge/03-context/systems/`
|
||||
- workstreams: `workspaces/fidelity/project-knowledge/03-context/workstreams/`
|
||||
- process: `workspaces/fidelity/project-knowledge/03-context/process/`
|
||||
- manager mapping: `workspaces/fidelity/project-knowledge/04-people/manager.md`
|
||||
- people roster: `workspaces/fidelity/project-knowledge/04-people/index.md`
|
||||
- people notes: `workspaces/fidelity/project-knowledge/04-people/*.md`
|
||||
- decisions: `workspaces/fidelity/project-knowledge/05-decisions/`
|
||||
- `.agents/workflows/*.md`
|
||||
- `.agents/rules/*.md`
|
||||
- `prompts/*.md`
|
||||
|
||||
@@ -16,14 +16,14 @@ $ARGUMENTS
|
||||
Read:
|
||||
|
||||
@prompts/mattermost-translation.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/process/communication.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/communication.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
|
||||
If relevant, use today's log for context:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Return:
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@ Read core:
|
||||
|
||||
Read active workspace memory:
|
||||
|
||||
@project-knowledge/00-start/start-here.md
|
||||
@project-knowledge/01-current/current-work.md
|
||||
@project-knowledge/01-current/work-items.md
|
||||
@project-knowledge/03-context/project.md
|
||||
@project-knowledge/03-context/process/communication.md
|
||||
@project-knowledge/03-context/ios/index.md
|
||||
@project-knowledge/04-people/manager.md
|
||||
@project-knowledge/04-people/index.md
|
||||
@workspaces/fidelity/project-knowledge/00-start/start-here.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/project.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/process/communication.md
|
||||
@workspaces/fidelity/project-knowledge/03-context/ios/index.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/manager.md
|
||||
@workspaces/fidelity/project-knowledge/04-people/index.md
|
||||
|
||||
Read active profile, preferring the configured profile and falling back to Fidelity:
|
||||
|
||||
@@ -33,11 +33,11 @@ Today's date:
|
||||
|
||||
Today's canonical daily note, if present:
|
||||
|
||||
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
!`if [ -f workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md ]; then cat workspaces/fidelity/project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
|
||||
|
||||
Latest daily notes available:
|
||||
|
||||
!`if [ -d project-knowledge/06-daily ]; then ls -1 project-knowledge/06-daily 2>/dev/null | sort | tail -n 3; else echo "No daily notes directory available."; fi`
|
||||
!`if [ -d workspaces/fidelity/project-knowledge/06-daily ]; then ls -1 workspaces/fidelity/project-knowledge/06-daily 2>/dev/null | sort | tail -n 3; else echo "No daily notes directory available."; fi`
|
||||
|
||||
Detailed active work item files, if available:
|
||||
|
||||
@@ -45,13 +45,13 @@ Detailed active work item files, if available:
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
summary = Path("project-knowledge/01-current/work-items.md")
|
||||
summary = Path("workspaces/fidelity/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)
|
||||
paths = re.findall(r"Detail: `(workspaces/fidelity/project-knowledge/02-work-items/[^`]+)`", text)
|
||||
if not paths:
|
||||
print("No work item files available.")
|
||||
raise SystemExit(0)
|
||||
@@ -66,7 +66,7 @@ PY`
|
||||
|
||||
Latest communication inbox, if available:
|
||||
|
||||
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No live communication context available."; fi`
|
||||
!`python3 scripts/mattermost-proxy/read-context.py --mode latest`
|
||||
|
||||
Respond with:
|
||||
|
||||
|
||||
38
.gitignore
vendored
38
.gitignore
vendored
@@ -8,24 +8,40 @@ __pycache__/
|
||||
.venv/
|
||||
|
||||
# Mattermost raw inbox artifacts
|
||||
ai/inbox/mattermost-latest.md
|
||||
ai/inbox/mattermost-*.md
|
||||
ai/inbox/mattermost-status.json
|
||||
workspaces/*/inbox/mattermost-latest.md
|
||||
workspaces/*/inbox/mattermost-*.md
|
||||
workspaces/*/inbox/mattermost-status.json
|
||||
workspaces/*/inbox/mattermost-mirror/*
|
||||
!workspaces/*/inbox/mattermost-mirror/.gitkeep
|
||||
workspaces/*/inbox/photos/*
|
||||
!workspaces/*/inbox/photos/.gitkeep
|
||||
|
||||
# Local build artifact for the iPhone photo inbox pasteboard helper
|
||||
scripts/iphone-photo-inbox/.env
|
||||
scripts/iphone-photo-inbox/copy_files_to_clipboard
|
||||
|
||||
# Workspace-local Mattermost runtime artifacts
|
||||
scripts/mattermost/.env
|
||||
scripts/mattermost/.venv/
|
||||
scripts/mattermost/generated/*
|
||||
!scripts/mattermost/generated/.gitkeep
|
||||
scripts/mattermost-proxy/.env
|
||||
|
||||
# Obsidian local runtime state
|
||||
/.obsidian/
|
||||
project-knowledge/.obsidian/workspace*.json
|
||||
project-knowledge/.obsidian/workspace-mobile*.json
|
||||
project-knowledge/.obsidian/graph.json
|
||||
project-knowledge/.obsidian/hotkeys.json
|
||||
project-knowledge/.obsidian/community-plugins.json
|
||||
project-knowledge/.obsidian/plugins/
|
||||
project-knowledge/.obsidian/snippets/
|
||||
project-knowledge/.obsidian/cache/
|
||||
workspaces/*/project-knowledge/.obsidian/workspace*.json
|
||||
workspaces/*/project-knowledge/.obsidian/workspace-mobile*.json
|
||||
workspaces/*/project-knowledge/.obsidian/graph.json
|
||||
workspaces/*/project-knowledge/.obsidian/hotkeys.json
|
||||
workspaces/*/project-knowledge/.obsidian/community-plugins.json
|
||||
workspaces/*/project-knowledge/.obsidian/plugins/
|
||||
workspaces/*/project-knowledge/.obsidian/snippets/
|
||||
workspaces/*/project-knowledge/.obsidian/cache/
|
||||
.trash/
|
||||
|
||||
# Antigravity CLI local workspace configuration
|
||||
.antigravitycli/
|
||||
|
||||
# AI Workspace local service runtime
|
||||
.aiw/runtime/
|
||||
.aiw/indexes/
|
||||
|
||||
@@ -12,20 +12,21 @@ Behavior rules:
|
||||
|
||||
- Treat `core/` as the reusable project-independent operating model.
|
||||
- Treat `profiles/fidelity/profile.md` as the active Fidelity project profile.
|
||||
- Treat `project-knowledge/` as the canonical clean project knowledge base for humans and AI.
|
||||
- Treat `workspaces/fidelity/project-knowledge/` as the canonical clean project knowledge base for humans and AI.
|
||||
- Treat `agent-memory/` as the operating memory for agent behavior, learning, promotion, verification, and self-maintenance rules.
|
||||
- Treat `scripts/memory/` as the project-agnostic access layer for note creation, project-knowledge search, Base queries, and health checks.
|
||||
- Treat `scripts/obsidian/` as the current Obsidian adapter. Do not couple durable memory rules to Obsidian-specific behavior.
|
||||
- Treat `ai/inbox/` and generated connector files as raw evidence only, not promoted memory.
|
||||
- Keep Obsidian Bases clean: do not let templates in `project-knowledge/09-templates/` appear as real daily notes, work items, people, decisions, systems, or workstreams.
|
||||
- Role mapping notes such as `project-knowledge/04-people/manager.md` are `type: role-map`; actual people profiles are `type: person`.
|
||||
- Treat `workspaces/fidelity/inbox/` and generated connector files as raw evidence only, not promoted memory.
|
||||
- For Mattermost context, prefer the local proxy mirror in `workspaces/fidelity/inbox/mattermost-mirror/` when present. Use `scripts/mattermost-proxy/read-context.py` or the mirror views (`latest.*`, `by-date/`, `channels/`, `threads/`) before falling back to legacy `workspaces/fidelity/inbox/mattermost-latest.md` or `scripts/mattermost/generated/` artifacts.
|
||||
- Keep Obsidian Bases clean: do not let templates in `workspaces/fidelity/project-knowledge/09-templates/` appear as real daily notes, work items, people, decisions, systems, or workstreams.
|
||||
- Role mapping notes such as `workspaces/fidelity/project-knowledge/04-people/manager.md` are `type: role-map`; actual people profiles are `type: person`.
|
||||
- When editing canonical project notes, update useful metadata at the same time: `updated`, `systems`, `workstreams`, `people`, `related`, `focus`, `work-items`, and `blockers` when applicable.
|
||||
- When creating a new typed note, prefer `bash scripts/memory/memory.sh create <type> <slug> [title]`, then inspect and refine the generated Markdown.
|
||||
- When checking project knowledge quality, use `bash scripts/memory/memory.sh health` and direct file inspection.
|
||||
- Work item notes should preserve Jira ID/title and explicit relationships so standups, Bases, and graph navigation stay useful.
|
||||
- Daily notes should include `focus`, `work-items`, and `blockers` when those values are clear.
|
||||
- Before answering a prompt that depends on current state, verify the latest relevant files instead of relying only on conversation history.
|
||||
- If the prompt asks for the latest Mattermost message, the last message from Jeff/current manager, or what someone just said, force a Mattermost refresh before answering and do not rely on stale inbox context.
|
||||
- If the prompt asks for the latest Mattermost message, the last message from Jeff/current manager, or what someone just said, refresh or read the freshest Mattermost evidence before answering; the proxy mirror is the primary source when it is present, and configured sync artifacts are secondary evidence.
|
||||
- Treat latest-message prompts as read-first: answer from refreshed evidence and report memory update candidates instead of editing canonical memory by default.
|
||||
- For learning-style questions, answer from known context and verified facts only; explicitly label unknowns, assumptions, and inferences.
|
||||
- For learning sessions, prioritize durable architecture, process, ownership, debugging strategy, release mechanics, domain concepts, and decision rules over transient ticket status.
|
||||
@@ -35,24 +36,24 @@ Behavior rules:
|
||||
- If the user corrects or teaches the agent during a learning session, update the smallest correct canonical file or behavior surface so future sessions benefit.
|
||||
- For any meaningful prompt, decide whether the interaction adds, corrects, or sharpens project memory.
|
||||
- When the user provides new durable information, update the right workspace files during the same turn when the destination is clear, but do not delay a straightforward answer just to create or reorganize memory.
|
||||
- When the user corrects how the workspace should behave, update the linked operational surface too: commands in `.opencode/commands/`, prompt templates in `prompts/`, agent rules in `AGENTS.md` or `.opencode/agents/`, skills in `.opencode/skills/`, and agent operating rules in `agent-memory/` when those files control the behavior.
|
||||
- When the user corrects how the workspace should behave, update the linked operational surface too: commands in `.opencode/commands/`, prompt templates in `prompts/`, agent rules in `AGENTS.md` or `.opencode/agents/`, skills in `.agents/skills/`, and agent operating rules in `agent-memory/` when those files control the behavior.
|
||||
- If existing context is stale, correct it directly instead of leaving conflicting versions.
|
||||
- Promote information carefully:
|
||||
- daily facts go to `project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
- current priorities go to `project-knowledge/01-current/current-work.md`
|
||||
- active Jira-linked work goes to `project-knowledge/02-work-items/*.md`
|
||||
- the active-work summary goes to `project-knowledge/01-current/work-items.md`
|
||||
- durable project knowledge overview goes to `project-knowledge/03-context/project.md`
|
||||
- system-specific durable knowledge goes to `project-knowledge/03-context/systems/`
|
||||
- workstream-specific durable knowledge goes to `project-knowledge/03-context/workstreams/`
|
||||
- project-facing process knowledge goes to `project-knowledge/03-context/process/`
|
||||
- confirmed team or manager communication preferences go to `project-knowledge/04-people/manager.md`
|
||||
- role-to-person mapping and recurring stakeholders go to `project-knowledge/04-people/`
|
||||
- confirmed decisions go to `project-knowledge/05-decisions/`
|
||||
- daily facts go to `workspaces/fidelity/project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
- current priorities go to `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
- active Jira-linked work goes to `workspaces/fidelity/project-knowledge/02-work-items/*.md`
|
||||
- the active-work summary goes to `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
- durable project knowledge overview goes to `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
- system-specific durable knowledge goes to `workspaces/fidelity/project-knowledge/03-context/systems/`
|
||||
- workstream-specific durable knowledge goes to `workspaces/fidelity/project-knowledge/03-context/workstreams/`
|
||||
- project-facing process knowledge goes to `workspaces/fidelity/project-knowledge/03-context/process/`
|
||||
- confirmed team or manager communication preferences go to `workspaces/fidelity/project-knowledge/04-people/manager.md`
|
||||
- role-to-person mapping and recurring stakeholders go to `workspaces/fidelity/project-knowledge/04-people/`
|
||||
- confirmed decisions go to `workspaces/fidelity/project-knowledge/05-decisions/`
|
||||
- behavioral rules for how this workspace should respond go to the exact command, prompt, agent, skill, or `agent-memory/` file that enforces that behavior
|
||||
- Use generic `AIW_*` integration variables for new tooling and keep `FIDELITY_*` only as Fidelity-profile aliases.
|
||||
- Use generic `AIW_*` integration variables for workspace tooling.
|
||||
- Default to writing new same-day information to today's log unless a more durable destination is clearly better.
|
||||
- Write canonical memory to `project-knowledge/`.
|
||||
- Write canonical memory to `workspaces/fidelity/project-knowledge/`.
|
||||
- Update preexisting memory when a new prompt clarifies or corrects something already stored.
|
||||
- Do not wait for a dedicated sync command if the correct memory update is already obvious.
|
||||
- For analysis, drafting, review, or translation prompts, answer first and persist second unless saving the fact is required to produce the answer safely.
|
||||
@@ -62,7 +63,7 @@ Behavior rules:
|
||||
- If the memory interface or Obsidian adapter fails, continue with direct Markdown operations when safe and do not promote the failure as project memory.
|
||||
- Do not over-promote uncertain information. Keep uncertain items in the daily log.
|
||||
- When drafting communication, preserve technical meaning and improve clarity in natural US English.
|
||||
- When answering Swift/iOS programming questions, use the project-local iOS skills and `project-knowledge/03-context/ios/`.
|
||||
- When answering Swift/iOS programming questions, use the project-local iOS skills and `workspaces/fidelity/project-knowledge/03-context/ios/`.
|
||||
- When answering programming, dependency-management, package-manager, CI/build, testing, or architecture-practice questions, verify with primary/current documentation when the topic may be outdated, disputed, version-sensitive, or project-critical.
|
||||
- For CocoaPods, podspecs, private spec repos, trunk/CDN behavior, SPM, Xcode, Swift, and Apple frameworks, do not rely only on model memory before giving strong advice.
|
||||
- When generating prompts for GitHub Copilot or another AI, use `agent-memory/workflows/ai-to-ai-prompting.md` and the `copilot-prompt-engineering` skill.
|
||||
|
||||
@@ -12,11 +12,12 @@ Behavior rules:
|
||||
|
||||
- Load `core/` first for project-independent operating rules.
|
||||
- Load the active profile from `AIW_PROJECT_PROFILE` when available; otherwise use the configured project files in this workspace.
|
||||
- Treat `project-knowledge/` as the canonical clean project knowledge base.
|
||||
- Treat `workspaces/fidelity/project-knowledge/` as the canonical clean project knowledge base.
|
||||
- Treat `agent-memory/` as the operating memory for agent behavior, learning, promotion, verification, and self-maintenance rules.
|
||||
- Treat `scripts/memory/` as the stable memory access layer.
|
||||
- Treat tool-specific integrations such as Obsidian as replaceable adapters.
|
||||
- Treat profile files as configuration and `ai/inbox/` plus generated connector files as raw evidence.
|
||||
- Treat profile files as configuration and `workspaces/fidelity/inbox/` plus generated connector files as raw evidence.
|
||||
- For live communication context, prefer project-local mirror evidence under `workspaces/fidelity/inbox/*-mirror/` through its reader script when available, then fall back to legacy inbox/generated connector artifacts.
|
||||
- Keep Obsidian Bases clean by excluding templates and typing role maps separately from people.
|
||||
- When updating canonical project notes, maintain relationship metadata and `updated` fields so project knowledge remains useful to both humans and agents.
|
||||
- Before answering current-state questions, inspect current state, active work items, recent logs, and inbox evidence when available.
|
||||
@@ -38,11 +39,11 @@ Behavior rules:
|
||||
|
||||
Memory destinations:
|
||||
|
||||
- daily facts -> `project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
- current priorities -> `project-knowledge/01-current/current-work.md`
|
||||
- active work items -> `project-knowledge/02-work-items/*.md`
|
||||
- active-work summary -> `project-knowledge/01-current/work-items.md`
|
||||
- durable project knowledge -> `project-knowledge/03-context/`
|
||||
- people and roles -> `project-knowledge/04-people/`
|
||||
- confirmed decisions -> `project-knowledge/05-decisions/`
|
||||
- reusable behavior -> `.opencode/commands/`, `prompts/`, `.opencode/agents/`, `.opencode/skills/`, `agent-memory/`, `core/`, or `scripts/`
|
||||
- daily facts -> `workspaces/fidelity/project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
- current priorities -> `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
- active work items -> `workspaces/fidelity/project-knowledge/02-work-items/*.md`
|
||||
- active-work summary -> `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
- durable project knowledge -> `workspaces/fidelity/project-knowledge/03-context/`
|
||||
- people and roles -> `workspaces/fidelity/project-knowledge/04-people/`
|
||||
- confirmed decisions -> `workspaces/fidelity/project-knowledge/05-decisions/`
|
||||
- reusable behavior -> `.opencode/commands/`, `prompts/`, `.opencode/agents/`, `.agents/skills/`, `agent-memory/`, `core/`, or `scripts/`
|
||||
|
||||
@@ -20,9 +20,7 @@ function envFlag(name, defaultValue = false) {
|
||||
}
|
||||
|
||||
async function resolveSyncCommand(directory) {
|
||||
const configured =
|
||||
process.env.AIW_MATTERMOST_SYNC_CMD?.trim() ||
|
||||
process.env.FIDELITY_MATTERMOST_SYNC_CMD?.trim()
|
||||
const configured = process.env.AIW_MATTERMOST_SYNC_CMD?.trim()
|
||||
if (configured) return configured
|
||||
|
||||
const fallbackScript = path.join(directory, "scripts/mattermost/sync.sh")
|
||||
@@ -43,6 +41,21 @@ async function resolveSyncContent(directory, stdoutText) {
|
||||
return (generated || "").trim()
|
||||
}
|
||||
|
||||
async function resolveProfileInbox(directory) {
|
||||
const profile = process.env.AIW_PROJECT_PROFILE?.trim() || "fidelity"
|
||||
const configured = process.env.AIW_PROJECT_INBOX_DIR?.trim()
|
||||
if (configured) return path.isAbsolute(configured) ? configured : path.join(directory, configured)
|
||||
|
||||
const workspaceConfigPath = path.join(directory, "profiles", profile, "workspace.json")
|
||||
try {
|
||||
const config = JSON.parse(await readFile(workspaceConfigPath, "utf8"))
|
||||
const inboxDir = config?.inbox_dir || `workspaces/${profile}/inbox`
|
||||
return path.isAbsolute(inboxDir) ? inboxDir : path.join(directory, inboxDir)
|
||||
} catch {
|
||||
return path.join(directory, "workspaces", profile, "inbox")
|
||||
}
|
||||
}
|
||||
|
||||
function extractPromptText(event) {
|
||||
const candidates = [
|
||||
event?.properties?.text,
|
||||
@@ -101,7 +114,6 @@ function requiresFreshMattermost(promptText) {
|
||||
process.env.AIW_COMMUNICATION_FRESH_TERMS,
|
||||
process.env.AIW_MANAGER_NAME,
|
||||
process.env.AIW_PRIMARY_STAKEHOLDER,
|
||||
process.env.FIDELITY_MANAGER_NAME,
|
||||
"jeff",
|
||||
"fidelity-preguntas",
|
||||
]
|
||||
@@ -133,7 +145,6 @@ export const MattermostInbox = async ({ $, directory, client }) => {
|
||||
|
||||
const intervalMinutes = Number.parseInt(
|
||||
process.env.AIW_MATTERMOST_SYNC_INTERVAL_MINUTES ||
|
||||
process.env.FIDELITY_MATTERMOST_SYNC_INTERVAL_MINUTES ||
|
||||
"15",
|
||||
10,
|
||||
)
|
||||
@@ -144,14 +155,12 @@ export const MattermostInbox = async ({ $, directory, client }) => {
|
||||
lastSyncAt = now
|
||||
const syncStartedAt = Date.now()
|
||||
|
||||
const inboxDir = path.join(directory, "ai/inbox")
|
||||
const inboxDir = await resolveProfileInbox(directory)
|
||||
const latestPath = path.join(inboxDir, "mattermost-latest.md")
|
||||
const statusPath = path.join(inboxDir, "mattermost-status.json")
|
||||
|
||||
const commandSource = process.env.AIW_MATTERMOST_SYNC_CMD?.trim()
|
||||
? "aiw-env"
|
||||
: process.env.FIDELITY_MATTERMOST_SYNC_CMD?.trim()
|
||||
? "fidelity-env"
|
||||
: "workspace-default"
|
||||
|
||||
try {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/ai-prompt-engineering.md
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/copilot-prompt-engineering.md
|
||||
@@ -1,31 +1,12 @@
|
||||
# OpenCode Skills Index
|
||||
# OpenCode Skills Compatibility
|
||||
|
||||
Skills available to the workspace agent.
|
||||
OpenCode CLI discovers the shared skills from `.agents/skills/`.
|
||||
|
||||
---
|
||||
Do not mirror skills into `.opencode/skills/`; duplicate skill names create warnings and ambiguous discovery.
|
||||
|
||||
## Generic Skills
|
||||
|
||||
- [Workspace Memory Curation](workspace-memory-curation/SKILL.md)
|
||||
- [Professional Communication](professional-communication/SKILL.md)
|
||||
- [Status Reporting](status-reporting/SKILL.md)
|
||||
- [AI Prompt Engineering](ai-prompt-engineering/SKILL.md)
|
||||
|
||||
---
|
||||
|
||||
## Fidelity / iOS Skills
|
||||
|
||||
- [Copilot Prompt Engineering](copilot-prompt-engineering/SKILL.md)
|
||||
- [iOS Swift Answering](ios-swift-answering/SKILL.md)
|
||||
- [iOS Testing Strategy](ios-testing-strategy/SKILL.md)
|
||||
- [SwiftUI Expert Skill](swiftui-expert-skill/SKILL.md)
|
||||
- [SwiftUI XFlow Review](swiftui-xflow-review/SKILL.md)
|
||||
- [Update SwiftUI APIs](update-swiftui-apis/SKILL.md)
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
Use:
|
||||
|
||||
- [Shared Skills Index](../../.agents/skills/index.md)
|
||||
- [Tooling Map](../../agent-memory/maps/tooling.md)
|
||||
- [Commands Index](../commands/index.md)
|
||||
- [Prompts Index](../../prompts/index.md)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/ios-swift-answering.md
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/ios-testing-strategy.md
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/professional-communication.md
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/status-reporting.md
|
||||
@@ -1 +0,0 @@
|
||||
../../.agents/skills/swiftui-expert-skill
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/swiftui-xflow-review.md
|
||||
@@ -1 +0,0 @@
|
||||
../../.agents/skills/update-swiftui-apis
|
||||
@@ -1 +0,0 @@
|
||||
../../../.agents/rules/workspace-memory-curation.md
|
||||
46
AGENTS.md
46
AGENTS.md
@@ -19,15 +19,15 @@ Keep the always-loaded context small. The hot set is:
|
||||
- `agent-memory/memory/promotion-rules.md`
|
||||
- `agent-memory/integrations/technical-verification.md`
|
||||
- `agent-memory/workflows/ai-to-ai-prompting.md`
|
||||
- `project-knowledge/00-start/start-here.md`
|
||||
- `project-knowledge/01-current/current-work.md`
|
||||
- `project-knowledge/01-current/work-items.md`
|
||||
- `project-knowledge/03-context/project.md`
|
||||
- `project-knowledge/03-context/process/communication.md`
|
||||
- `project-knowledge/03-context/ios/index.md`
|
||||
- `project-knowledge/03-context/ios/project-swift-guidance.md`
|
||||
- `project-knowledge/04-people/manager.md`
|
||||
- `project-knowledge/04-people/index.md`
|
||||
- `workspaces/fidelity/project-knowledge/00-start/start-here.md`
|
||||
- `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
- `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/process/communication.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/ios/index.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/ios/project-swift-guidance.md`
|
||||
- `workspaces/fidelity/project-knowledge/04-people/manager.md`
|
||||
- `workspaces/fidelity/project-knowledge/04-people/index.md`
|
||||
|
||||
Load everything else lazily when the task actually needs it.
|
||||
|
||||
@@ -36,16 +36,16 @@ Do not preemptively load broad context sets, all work-item files, or all process
|
||||
## Required Behavior
|
||||
|
||||
- Assume the workspace may contain stale context until checked.
|
||||
- Treat `project-knowledge/` as the canonical clean project memory for humans and AI. Treat `agent-memory/` as agent operating memory. Treat `ai/inbox/` as raw evidence only.
|
||||
- Treat `workspaces/fidelity/project-knowledge/` as the canonical clean project memory for humans and AI. Treat `agent-memory/` as agent operating memory. Treat `workspaces/fidelity/inbox/` as raw evidence only.
|
||||
- Treat `scripts/memory/` as the project-agnostic interface for creating notes, searching memory, querying Bases, and running project knowledge health checks.
|
||||
- Treat `scripts/obsidian/` as the current Obsidian adapter, not as the core memory abstraction.
|
||||
- Keep Obsidian Bases clean: templates in `project-knowledge/09-templates/` must not be treated as real notes, and role mapping files such as `project-knowledge/04-people/manager.md` must not be typed as people.
|
||||
- Keep Obsidian Bases clean: templates in `workspaces/fidelity/project-knowledge/09-templates/` must not be treated as real notes, and role mapping files such as `workspaces/fidelity/project-knowledge/04-people/manager.md` must not be typed as people.
|
||||
- Maintain useful project-note properties when editing canonical notes, especially work-item relationships (`systems`, `workstreams`, `people`, `related`) and daily note fields (`focus`, `work-items`, `blockers`).
|
||||
- Before answering questions that depend on current work state, inspect `project-knowledge/01-current/current-work.md` and the latest relevant daily note under `project-knowledge/06-daily/`.
|
||||
- Before answering questions that depend on current work state, inspect `workspaces/fidelity/project-knowledge/01-current/current-work.md` and the latest relevant daily note under `workspaces/fidelity/project-knowledge/06-daily/`.
|
||||
- Prefer lazy loading over eager loading. Pull in only the smallest relevant files for the active task.
|
||||
- If `ai/inbox/mattermost-latest.md` exists, inspect it for fresher communication context before answering standup, status, or manager-message prompts.
|
||||
- If the user asks for the latest/last/recent Mattermost message, the latest message from Jeff/current manager, or what someone just said, synchronize Mattermost first instead of relying on existing inbox context.
|
||||
- If automatic refresh is uncertain, use the explicit latest-message flow: run the Mattermost sync command, then answer from the refreshed inbox only.
|
||||
- For Mattermost evidence, prefer the local proxy mirror under `workspaces/fidelity/inbox/mattermost-mirror/` when present. Use `scripts/mattermost-proxy/read-context.py` or mirror views (`latest.*`, `by-date/`, `channels/`, `threads/`) before falling back to legacy `workspaces/fidelity/inbox/mattermost-latest.md` or `scripts/mattermost/generated/` artifacts.
|
||||
- If the user asks for the latest/last/recent Mattermost message, the latest message from Jeff/current manager, or what someone just said, use the explicit latest-message flow and answer from the freshest refreshed evidence; the proxy mirror is primary when available.
|
||||
- If automatic refresh is uncertain and the proxy mirror is not available, run the Mattermost sync command, then answer from the refreshed inbox only.
|
||||
- Treat latest-message flows as read-first. Report memory update candidates, but do not edit canonical memory from that command unless the user explicitly asks to promote the fact.
|
||||
- For learning-style questions, answer from known context and verified facts only; label unknowns, assumptions, and inferences instead of inventing missing details.
|
||||
- For learning sessions, prioritize durable architecture, process, ownership, debugging strategy, release mechanics, domain concepts, and decision rules over transient ticket status.
|
||||
@@ -60,12 +60,12 @@ Do not preemptively load broad context sets, all work-item files, or all process
|
||||
- Treat sync failures as operational errors, not project context.
|
||||
- If a patch or edit verification fails while making a non-essential memory update, stop retrying and return the user-facing answer with the failed target noted.
|
||||
- `mattermost-sync` should automatically promote high-confidence project facts without asking what to promote.
|
||||
- Prefer `project-knowledge/06-daily/` as the default destination for new Mattermost-derived facts.
|
||||
- Promote to `project-knowledge/01-current/current-work.md` only when the fact materially changes active work over the next few days.
|
||||
- Keep explicit Jira IDs and approved titles visible in `project-knowledge/02-work-items/` and summarize active items in `project-knowledge/01-current/work-items.md` when they are useful for future standups or manager updates.
|
||||
- Promote to `project-knowledge/03-context/project.md` only when the fact changes durable project understanding.
|
||||
- When a repeatedly mentioned person becomes relevant to project flow, create or update a file under `project-knowledge/04-people/`.
|
||||
- Keep role-to-person mapping explicit in `project-knowledge/04-people/manager.md` and the roster in `project-knowledge/04-people/index.md`.
|
||||
- Prefer `workspaces/fidelity/project-knowledge/06-daily/` as the default destination for new Mattermost-derived facts.
|
||||
- Promote to `workspaces/fidelity/project-knowledge/01-current/current-work.md` only when the fact materially changes active work over the next few days.
|
||||
- Keep explicit Jira IDs and approved titles visible in `workspaces/fidelity/project-knowledge/02-work-items/` and summarize active items in `workspaces/fidelity/project-knowledge/01-current/work-items.md` when they are useful for future standups or manager updates.
|
||||
- Promote to `workspaces/fidelity/project-knowledge/03-context/project.md` only when the fact changes durable project understanding.
|
||||
- When a repeatedly mentioned person becomes relevant to project flow, create or update a file under `workspaces/fidelity/project-knowledge/04-people/`.
|
||||
- Keep role-to-person mapping explicit in `workspaces/fidelity/project-knowledge/04-people/manager.md` and the roster in `workspaces/fidelity/project-knowledge/04-people/index.md`.
|
||||
- Never promote tooling chatter, sync status, or generic conversation noise.
|
||||
- Direct user prompts are also memory sources. Do not limit memory updates to explicit sync commands.
|
||||
- If a new prompt corrects prior understanding, update the canonical file directly instead of keeping both versions alive.
|
||||
@@ -77,8 +77,8 @@ Do not preemptively load broad context sets, all work-item files, or all process
|
||||
- If a previous context file is now stale or inaccurate, update that file directly.
|
||||
- Prefer correcting canonical context over appending contradictory notes.
|
||||
- Keep changes concise and auditable.
|
||||
- When the topic is architectural or historical, prefer updating the relevant file under `project-knowledge/03-context/systems/`, `project-knowledge/03-context/workstreams/`, or project-facing `project-knowledge/03-context/process/` instead of overloading `project-knowledge/03-context/project.md`.
|
||||
- When the user asks Swift, SwiftUI, iOS architecture, testing, or debugging questions, use `project-knowledge/03-context/ios/` and the local OpenCode iOS skills before answering.
|
||||
- When the topic is architectural or historical, prefer updating the relevant file under `workspaces/fidelity/project-knowledge/03-context/systems/`, `workspaces/fidelity/project-knowledge/03-context/workstreams/`, or project-facing `workspaces/fidelity/project-knowledge/03-context/process/` instead of overloading `workspaces/fidelity/project-knowledge/03-context/project.md`.
|
||||
- When the user asks Swift, SwiftUI, iOS architecture, testing, or debugging questions, use `workspaces/fidelity/project-knowledge/03-context/ios/` and the local OpenCode iOS skills before answering.
|
||||
- When the user asks about programming concepts, dependency tooling, package managers, CI/build tooling, testing frameworks, or practices that may be outdated or opinion-sensitive, verify against primary/current documentation before making strong claims.
|
||||
- For CocoaPods, podspecs, private specs repos, trunk/CDN behavior, Swift Package Manager, Xcode, Swift, Apple frameworks, and similar project-linked tooling, do not rely only on memory.
|
||||
- When the user asks for a prompt for another AI, GitHub Copilot, or the Fidelity development machine, use `agent-memory/workflows/ai-to-ai-prompting.md` and generate a self-contained prompt.
|
||||
|
||||
24
DECOMMISSIONED.md
Normal file
24
DECOMMISSIONED.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Decommissioned Workspace
|
||||
|
||||
This repository is no longer the active AIWorkspace runtime.
|
||||
|
||||
As of 2026-05-22, the active split is:
|
||||
|
||||
- reusable core: `/Users/david/Developer/ai-workspace`
|
||||
- Fidelity context pack: `/Users/david/Developer/fidelity-ai-context`
|
||||
- local project registry: `~/Library/Application Support/AIWorkspace/projects.json`
|
||||
- runtime state: `~/Library/Application Support/AIWorkspace/runtime/`
|
||||
- logs: `~/Library/Logs/AIWorkspace/`
|
||||
|
||||
Do not start services from this repository unless intentionally rolling back.
|
||||
|
||||
Use the new core instead:
|
||||
|
||||
```bash
|
||||
cd /Users/david/Developer/ai-workspace
|
||||
python3 scripts/aiw/services.py status --project fidelity
|
||||
python3 scripts/aiw/services.py doctor --project fidelity
|
||||
```
|
||||
|
||||
The old profile-based service manager may report services as `externally running`
|
||||
because the new core owns the same health ports.
|
||||
10
GEMINI.md
10
GEMINI.md
@@ -7,9 +7,9 @@ Shared rules and context already live in the normal workspace files. Do not dupl
|
||||
Read these first:
|
||||
|
||||
@./AGENTS.md
|
||||
@./project-knowledge/00-start/start-here.md
|
||||
@./project-knowledge/01-current/current-work.md
|
||||
@./project-knowledge/01-current/work-items.md
|
||||
@./workspaces/fidelity/project-knowledge/00-start/start-here.md
|
||||
@./workspaces/fidelity/project-knowledge/01-current/current-work.md
|
||||
@./workspaces/fidelity/project-knowledge/01-current/work-items.md
|
||||
|
||||
## Tool Surface
|
||||
|
||||
@@ -17,7 +17,7 @@ Read these first:
|
||||
- `.agents/` is the canonical shared cross-platform surface for workflows and reusable rule/skill content.
|
||||
- `.opencode/` is the OpenCode compatibility/runtime surface.
|
||||
- `.agent/` is an alias for tools that expect the singular directory naming.
|
||||
- `project-knowledge/` is canonical project memory.
|
||||
- `workspaces/fidelity/project-knowledge/` is canonical project memory.
|
||||
- `agent-memory/` is agent operating memory.
|
||||
|
||||
## Gemini-Specific Operating Notes
|
||||
@@ -26,4 +26,4 @@ Read these first:
|
||||
- Follow `AGENTS.md` as the shared source of truth for answer-first behavior, memory promotion, and lazy loading.
|
||||
- For analysis, review, translation, or drafting prompts, answer first and persist second unless saving the fact is clearly required to produce a safe answer.
|
||||
- Do not create new canonical notes in the critical path of a simple answer unless the user explicitly asked to save the information or the destination is obvious and non-blocking.
|
||||
- When memory should be updated, prefer the smallest correct change to `project-knowledge/` and avoid duplicating stale and corrected versions.
|
||||
- When memory should be updated, prefer the smallest correct change to `workspaces/fidelity/project-knowledge/` and avoid duplicating stale and corrected versions.
|
||||
|
||||
460
README.md
460
README.md
@@ -1,366 +1,216 @@
|
||||
# AI Workspace - Fidelity Profile
|
||||
# AI Workspace
|
||||
|
||||
Reusable AI-native companion workspace with Fidelity configured as the first real project profile.
|
||||
> **Decommissioned:** this repository is no longer the active AIWorkspace runtime.
|
||||
> Active services now run from `/Users/david/Developer/ai-workspace`, and Fidelity
|
||||
> context lives in `/Users/david/Developer/fidelity-ai-context`. See
|
||||
> [`DECOMMISSIONED.md`](DECOMMISSIONED.md) before using this repo.
|
||||
|
||||
This repository is not the product codebase. It is an operational context layer used to keep project state current, capture communication evidence, prepare standups, draft clear stakeholder updates, and generate self-contained prompts for another AI that has access to the implementation codebase.
|
||||
AI Workspace is a local, profile-based companion workspace for AI-assisted professional work. It keeps project memory, raw evidence, local services, and AI client integrations organized so agents can work from current, auditable context instead of chat history alone.
|
||||
|
||||
The reusable logic lives in `core/`. The clean project second brain lives in `project-knowledge/`. Agent operating memory lives in `agent-memory/`. Fidelity-specific setup lives in the active profile under `profiles/fidelity/`.
|
||||
The first real profile in this repository is `fidelity`, but the reusable model is intentionally project-independent.
|
||||
|
||||
Shared cross-platform workflow/rule content lives in `.agents/`. OpenCode reads that content through `.opencode/` compatibility paths, and Gemini-compatible entry context starts at `GEMINI.md`.
|
||||
## What This Repo Is
|
||||
|
||||
---
|
||||
Use this repository beside your real implementation work to:
|
||||
|
||||
## Purpose
|
||||
- maintain human-readable project memory;
|
||||
- capture communication or screenshot evidence before curation;
|
||||
- generate standups, stakeholder updates, and AI-to-AI prompts;
|
||||
- expose bounded local context to AI clients through MCP;
|
||||
- manage local services such as capture tools, context servers, and inbox helpers;
|
||||
- support long-running AI workflows with durable state artifacts.
|
||||
|
||||
- Provide a reusable file-based AI workspace pattern
|
||||
- Keep Fidelity context current outside the main development machine
|
||||
- Turn fragmented daily work into reusable AI-ready context
|
||||
- Support standups, manager updates, Jira notes, and debugging summaries
|
||||
- Generate high-quality prompts for GitHub Copilot or another AI on the Fidelity development machine
|
||||
- Improve communication quality without losing technical accuracy
|
||||
This repository is not the product codebase. It is a context and workflow layer.
|
||||
|
||||
---
|
||||
## Architecture At A Glance
|
||||
|
||||
## Operating Model
|
||||
|
||||
You work on Fidelity from a different machine.
|
||||
|
||||
This workspace is used to:
|
||||
|
||||
- record what happened during implementation and debugging
|
||||
- sync relevant communication from Mattermost
|
||||
- preserve current project context between sessions
|
||||
- draft messages for the current manager or stakeholder with the right tone and scope
|
||||
- translate rough notes into concise native-sounding English
|
||||
- generate self-contained prompts for another AI that does have access to the product codebase
|
||||
```text
|
||||
Communication / photos / archives / manual notes
|
||||
↓
|
||||
Raw profile inbox evidence
|
||||
↓
|
||||
Human or agent curation
|
||||
↓
|
||||
Canonical Markdown project knowledge
|
||||
↓
|
||||
Derived local index
|
||||
↓
|
||||
Read-only MCP context server
|
||||
↓
|
||||
OpenCode / Claude Code / Copilot / Antigravity / other AI clients
|
||||
```
|
||||
|
||||
Core principle:
|
||||
|
||||
Context must be updated before asking AI to write.
|
||||
```text
|
||||
Markdown project knowledge is canonical. Inboxes, indexes, chat memory, and cloud memory are supporting layers.
|
||||
```
|
||||
|
||||
Reusable principle:
|
||||
## Main Folders
|
||||
|
||||
Integrations extract evidence. The agent promotes memory.
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `docs/` | Simple project-independent documentation for developers adopting the workspace |
|
||||
| `core/` | Reusable operating model and architecture notes |
|
||||
| `profiles/` | Project-specific configuration and assumptions |
|
||||
| `workspaces/<profile>/project-knowledge/` | Profile-owned canonical Markdown vault |
|
||||
| `agent-memory/` | Agent behavior, promotion, verification, and workflow memory |
|
||||
| `workspaces/<profile>/inbox/` | Profile-owned raw evidence before promotion into canonical memory |
|
||||
| `scripts/aiw/` | Service manager and local indexer |
|
||||
| `scripts/mcp/` | MCP servers exposing bounded local context |
|
||||
| `scripts/memory/` | Project-agnostic interface for canonical memory operations |
|
||||
| `scripts/obsidian/` | Current Obsidian adapter |
|
||||
| `scripts/mattermost-proxy/` | Mattermost proxy mirror connector for local evidence capture |
|
||||
| `scripts/iphone-photo-inbox/` | Local photo inbox receiver |
|
||||
| `apps/mac/AIWorkspace/` | macOS menu bar app for service visibility and control |
|
||||
|
||||
---
|
||||
## Quick Start
|
||||
|
||||
## Reusable Architecture
|
||||
Run basic checks for the active profile:
|
||||
|
||||
### /project-knowledge
|
||||
```bash
|
||||
python3 scripts/aiw/services.py doctor --profile fidelity
|
||||
python3 scripts/aiw/services.py status --profile fidelity
|
||||
python3 scripts/aiw/indexer.py build --profile fidelity
|
||||
```
|
||||
|
||||
Canonical Obsidian second brain and transferable project knowledge.
|
||||
Start the read-only context MCP server:
|
||||
|
||||
- `00-start/` -> onboarding, glossary, and start-here
|
||||
- `01-current/` -> current work and active work-item summary
|
||||
- `02-work-items/` -> ticket/task notes with metadata properties
|
||||
- `03-context/` -> systems, workstreams, project-facing process, and iOS context
|
||||
- `04-people/` -> people, roles, and collaboration context
|
||||
- `05-decisions/` -> durable decisions
|
||||
- `06-daily/` -> daily notes
|
||||
- `07-maps/` -> graph hubs and semantic maps
|
||||
- `08-bases/` -> Obsidian Bases
|
||||
- `09-templates/` -> Obsidian templates
|
||||
- `attachments/` -> vault assets
|
||||
```bash
|
||||
python3 scripts/aiw/services.py start aiw-context-mcp --profile fidelity
|
||||
```
|
||||
|
||||
### /agent-memory
|
||||
HTTP endpoint:
|
||||
|
||||
Agent operating memory.
|
||||
```text
|
||||
http://127.0.0.1:8765/mcp
|
||||
```
|
||||
|
||||
- `behavior/` -> agent learning and self-maintenance rules
|
||||
- `memory/` -> promotion, correction, and context-maintenance rules
|
||||
- `integrations/` -> memory interface, Obsidian adapter, communication sources, and technical verification
|
||||
- `workflows/` -> AI-to-AI prompting and workspace behavior model
|
||||
- `maps/` -> agent-side navigation maps
|
||||
Health endpoint:
|
||||
|
||||
### /.agents
|
||||
```text
|
||||
http://127.0.0.1:8765/health
|
||||
```
|
||||
|
||||
Shared cross-platform workflow and rule source.
|
||||
## Documentation
|
||||
|
||||
- `workflows/` -> reusable workflow definitions used by OpenCode-compatible commands and Antigravity-compatible workflow views
|
||||
- `rules/` -> reusable skill/rule content
|
||||
- `skills/` -> skill-path compatibility layer pointing at `rules/`
|
||||
Start here:
|
||||
|
||||
### /.opencode
|
||||
- [Getting Started](docs/getting-started.md)
|
||||
- [Architecture](docs/architecture.md)
|
||||
- [Profiles](docs/profiles.md)
|
||||
- [Memory Model](docs/memory-model.md)
|
||||
- [MCP](docs/mcp.md)
|
||||
- [Services](docs/services.md)
|
||||
- [Local RAG Index](docs/local-rag-index.md)
|
||||
- [Security and Privacy](docs/security-and-privacy.md)
|
||||
|
||||
OpenCode runtime surface.
|
||||
Profile-specific project knowledge starts at:
|
||||
|
||||
- `commands/` -> OpenCode slash commands, currently linked to `.agents/workflows/`
|
||||
- `skills/` -> OpenCode skills, currently linked to shared `.agents/` content
|
||||
- `agents/` -> OpenCode agent definitions
|
||||
- `plugins/` -> OpenCode-specific plugins
|
||||
- `workspaces/fidelity/project-knowledge/00-start/start-here.md` for the current Fidelity vault
|
||||
- `profiles/fidelity/profile.md` for the Fidelity profile declaration
|
||||
- `profiles/example/profile.md` for a sanitized reusable profile example
|
||||
|
||||
### /core
|
||||
## Profiles
|
||||
|
||||
Project-independent workspace logic.
|
||||
A profile represents one project, client, team, or workflow. It declares project assumptions, context sources, local services, and workflow defaults.
|
||||
|
||||
- `README.md` -> reusable operating model
|
||||
- `memory/operational-memory.md` -> reusable memory classes, promotion rules, correction rules, self-maintenance rules
|
||||
- `integrations/communication-model.md` -> live communication and historical archive connector contract
|
||||
- `profiles/create-project-profile.md` -> checklist for adapting the workspace to another project
|
||||
Current profiles:
|
||||
|
||||
### /profiles
|
||||
```text
|
||||
profiles/fidelity/
|
||||
profiles/example/
|
||||
```
|
||||
|
||||
Project-specific configuration.
|
||||
Each profile resolves memory and inbox paths from `profiles/<profile>/workspace.json`. Fidelity data now lives under `workspaces/fidelity/`.
|
||||
|
||||
- `profiles/fidelity/` -> active Fidelity implementation profile
|
||||
- `profiles/example/` -> non-sensitive example profile for new projects
|
||||
## Memory Model
|
||||
|
||||
Profiles declare project assumptions, communication sources, work-item system, stakeholders, enabled commands, and enabled skills.
|
||||
The workspace separates memory by responsibility:
|
||||
|
||||
---
|
||||
- `workspaces/<profile>/project-knowledge/`: canonical project facts for humans and AI;
|
||||
- `workspaces/<profile>/inbox/`: raw evidence;
|
||||
- `agent-memory/`: rules for how agents behave;
|
||||
- `.aiw/indexes/`: derived local search indexes;
|
||||
- external systems such as mem9: optional agent recall, not project truth.
|
||||
|
||||
## Project Scope
|
||||
Do not treat generated connector output or vector indexes as authoritative memory. Promote durable facts into the smallest correct Markdown file.
|
||||
|
||||
Fidelity iOS ecosystem:
|
||||
## MCP Model
|
||||
|
||||
- Fid4
|
||||
- XFlowSDK
|
||||
- FTFrameworks
|
||||
- REST migration replacing GraphQL over time
|
||||
- Discourse and AO issues that require careful classification
|
||||
`aiw-context-mcp` exposes profile-bounded, read-only context through MCP tools and resources. It does not capture traffic, send messages, or promote memory.
|
||||
|
||||
---
|
||||
Current examples:
|
||||
|
||||
## Runtime Structure
|
||||
- `project_current_context`
|
||||
- `project_search_memory`
|
||||
- `memory_hybrid_search`
|
||||
- `communication_latest`
|
||||
- `communication_standup_context`
|
||||
- `photos_latest`
|
||||
|
||||
### /ai
|
||||
## Service Manager
|
||||
|
||||
Runtime inbox for communication evidence.
|
||||
The service manager provides a single local lifecycle surface:
|
||||
|
||||
- `inbox/` -> communication evidence and transient inbox files before promotion into `project-knowledge/`
|
||||
```bash
|
||||
python3 scripts/aiw/services.py start --profile fidelity
|
||||
python3 scripts/aiw/services.py stop --profile fidelity
|
||||
python3 scripts/aiw/services.py status --profile fidelity --json
|
||||
python3 scripts/aiw/services.py logs aiw-context-mcp --profile fidelity
|
||||
```
|
||||
|
||||
### /prompts
|
||||
Runtime logs, PID files, and state live under `.aiw/runtime/` and are ignored.
|
||||
|
||||
Reusable prompts for:
|
||||
## Local Index
|
||||
|
||||
- standups
|
||||
- Mattermost updates
|
||||
- manager communication
|
||||
- issue clarification
|
||||
Build a derived search index over canonical Markdown:
|
||||
|
||||
### /workflows
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py build --profile fidelity
|
||||
python3 scripts/aiw/indexer.py search "dismissal lifecycle" --profile fidelity
|
||||
```
|
||||
|
||||
Repeatable working guides for:
|
||||
Indexes live under `.aiw/indexes/` and are ignored because they are rebuildable local artifacts.
|
||||
|
||||
- daily context sync
|
||||
- flow debugging
|
||||
- external issue analysis
|
||||
## Security Defaults
|
||||
|
||||
### /scripts
|
||||
- Keep secrets in ignored `.env` files.
|
||||
- Do not commit raw tokens, cookies, session IDs, or captured headers.
|
||||
- Keep MCP read-only by default.
|
||||
- Treat inboxes and generated indexes as sensitive local artifacts.
|
||||
- Use cloud memory systems only with an explicit data policy.
|
||||
|
||||
Helpers for automation around memory access, context generation, communication drafting, and imports.
|
||||
## Tests
|
||||
|
||||
- `scripts/memory/` -> project-agnostic interface for canonical memory
|
||||
- `scripts/obsidian/` -> current Obsidian adapter and URI helpers
|
||||
- `scripts/mattermost/` -> live communication connector
|
||||
- `scripts/slack/` -> historical archive importer
|
||||
```bash
|
||||
python3 scripts/aiw/test_services.py
|
||||
python3 scripts/aiw/test_profile.py
|
||||
python3 scripts/aiw/test_indexer.py
|
||||
python3 scripts/mcp/aiw-context-mcp/test_server.py
|
||||
python3 scripts/iphone-photo-inbox/test_receiver.py
|
||||
```
|
||||
|
||||
### /project-knowledge/.obsidian
|
||||
## Adoption Strategy
|
||||
|
||||
Optional Obsidian vault configuration.
|
||||
Recommended order for new projects:
|
||||
|
||||
Open `project-knowledge/` as the Obsidian vault. Do not open the repository root as the vault.
|
||||
1. Create an isolated profile:
|
||||
|
||||
Portable vault configuration can be versioned, while local layout and plugin runtime files are ignored.
|
||||
```bash
|
||||
python3 scripts/aiw/profile.py create my-project --display-name "My Project"
|
||||
```
|
||||
|
||||
Obsidian is the current visual interface over canonical memory. The reusable memory access layer is `scripts/memory/`, so the workspace can later swap Obsidian for another Markdown knowledge tool without changing the memory model.
|
||||
2. Configure only the services the project needs.
|
||||
3. Keep raw evidence outside canonical memory.
|
||||
4. Build the local index.
|
||||
5. Connect AI clients through MCP.
|
||||
6. Promote durable facts into Markdown as work progresses.
|
||||
|
||||
---
|
||||
Validate the profile layout with:
|
||||
|
||||
## Daily Usage
|
||||
```bash
|
||||
python3 scripts/aiw/profile.py doctor --profile my-project
|
||||
```
|
||||
|
||||
### Start of day
|
||||
|
||||
Read:
|
||||
|
||||
- `project-knowledge/00-start/start-here.md`
|
||||
- `project-knowledge/01-current/current-work.md`
|
||||
- `project-knowledge/01-current/work-items.md`
|
||||
- `project-knowledge/03-context/project.md`
|
||||
- `project-knowledge/04-people/manager.md`
|
||||
- `project-knowledge/04-people/index.md`
|
||||
- latest file under `project-knowledge/06-daily/`
|
||||
|
||||
### During the day
|
||||
|
||||
Capture:
|
||||
|
||||
- implementation progress from the main development machine
|
||||
- Mattermost conversations that change scope or priorities
|
||||
- debugging findings
|
||||
- open questions, blockers, and follow-ups
|
||||
|
||||
Write updates in:
|
||||
|
||||
- `project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
|
||||
### Before sending a message
|
||||
|
||||
Confirm:
|
||||
|
||||
- context
|
||||
- current observation
|
||||
- requested or implied action
|
||||
- whether the issue is external behavior or regression
|
||||
- whether the flow is authenticated or non-authenticated
|
||||
|
||||
### End of day
|
||||
|
||||
Update:
|
||||
|
||||
- today log
|
||||
- current state
|
||||
- next communication needs for the current manager or stakeholder
|
||||
|
||||
---
|
||||
|
||||
## Expected Output
|
||||
|
||||
This workspace should help produce:
|
||||
|
||||
- high-signal standups
|
||||
- clearer Mattermost updates
|
||||
- concise supervisor communication
|
||||
- better issue framing
|
||||
- more reliable AI-generated English
|
||||
|
||||
---
|
||||
|
||||
## OpenCode Entry Point
|
||||
|
||||
This workspace is designed to work well with the OpenCode VS Code extension.
|
||||
|
||||
Recommended usage:
|
||||
|
||||
1. Open this repository as its own VS Code workspace.
|
||||
2. Start OpenCode from the integrated terminal at the repository root.
|
||||
3. Begin each session with `/workspace-context` or the Fidelity alias `/fidelity-context`.
|
||||
4. As new information appears during the day, update context before asking for drafting help.
|
||||
|
||||
Project commands live under `.opencode/commands/` and are intended to:
|
||||
|
||||
- load the reusable core plus active project profile
|
||||
- sync live communication context into the workspace inbox
|
||||
- draft standups
|
||||
- draft manager updates
|
||||
- draft prompts for another AI on the implementation machine
|
||||
- force-refresh and inspect latest communication messages
|
||||
- convert rough notes into daily log updates
|
||||
|
||||
This keeps AI output tied to the latest workspace state instead of relying on chat memory alone.
|
||||
|
||||
Cross-platform note:
|
||||
|
||||
- `.agents/` is the shared source of truth for reusable workflows/rules
|
||||
- `.opencode/` is the OpenCode execution layer
|
||||
- `.agent/` may exist as a naming alias for tools that look for singular agent directories
|
||||
- `GEMINI.md` is the Gemini CLI entrypoint for shared workspace context
|
||||
|
||||
---
|
||||
|
||||
## Generic Commands
|
||||
|
||||
- `/workspace-context` -> load core plus active profile
|
||||
- `/memory-health` -> check canonical memory and adapter health
|
||||
- `/memory-create` -> create a typed canonical note through the memory interface
|
||||
- `/communication-sync` -> sync live communication evidence and promote high-confidence memory
|
||||
- `/archive-import` -> import historical archive evidence
|
||||
- `/ai-prompt` -> generate a self-contained prompt for another AI
|
||||
- `/standup` -> generate a work-item-aware daily standup
|
||||
- `/manager-update` -> draft stakeholder-ready status
|
||||
- `/translate` -> rewrite rough notes into professional English
|
||||
- `/sync-context` -> incorporate new facts or corrections into memory
|
||||
|
||||
Compatibility aliases remain available for the Fidelity profile:
|
||||
|
||||
- `/fidelity-context`
|
||||
- `/mattermost-sync`
|
||||
- `/slack-import`
|
||||
- `/copilot-prompt`
|
||||
- `/swift-help`
|
||||
|
||||
---
|
||||
|
||||
## Communication Memory Flow
|
||||
|
||||
This workspace supports a live-memory pattern for communication sources such as Mattermost.
|
||||
|
||||
Recommended setup:
|
||||
|
||||
1. Use the workspace-local script at `scripts/mattermost/sync.sh`, or override it with `AIW_MATTERMOST_SYNC_CMD`.
|
||||
2. Let OpenCode run with the project plugins enabled.
|
||||
3. The Mattermost inbox plugin will periodically refresh `ai/inbox/mattermost-latest.md`.
|
||||
4. Promote durable facts from the inbox into `project-knowledge/06-daily/`, `project-knowledge/01-current/`, `project-knowledge/02-work-items/`, and `project-knowledge/03-context/`.
|
||||
|
||||
Use `/communication-sync` or `/mattermost-sync` when you want to force a refresh manually.
|
||||
|
||||
Generic environment variables:
|
||||
|
||||
- `AIW_PROJECT_PROFILE`
|
||||
- `AIW_CHANNEL_PREFIX`
|
||||
- `AIW_MATTERMOST_SYNC_CMD`
|
||||
- `AIW_MATTERMOST_SYNC_INTERVAL_MINUTES`
|
||||
- `AIW_SLACK_EXPORT_PATH`
|
||||
|
||||
The `FIDELITY_*` variables remain supported as Fidelity-profile aliases, but new reusable setup should prefer `AIW_*`.
|
||||
|
||||
---
|
||||
|
||||
## Project Knowledge Vault
|
||||
|
||||
Open `project-knowledge/` as the Obsidian vault. The repository root remains the technical workspace for OpenCode, scripts, profiles, runtime inboxes, and generated evidence.
|
||||
|
||||
Recommended entry point:
|
||||
|
||||
- `project-knowledge/00-start/start-here.md`
|
||||
- `project-knowledge/00-start/onboarding.md` for new members
|
||||
- `project-knowledge/00-start/glossary.md` for terminology
|
||||
- `project-knowledge/07-maps/` for graph hubs
|
||||
|
||||
Use Obsidian for:
|
||||
|
||||
- visual navigation
|
||||
- graph/backlink review
|
||||
- manual review of work items, people, decisions, and logs
|
||||
- lightweight editing of the same Markdown memory files
|
||||
|
||||
Do not use Obsidian as a second memory database. The source of truth remains the versioned Markdown files under `project-knowledge/`.
|
||||
|
||||
Runtime/evidence stays outside the vault:
|
||||
|
||||
- `.opencode/`
|
||||
- `scripts/`
|
||||
- `core/`
|
||||
- `profiles/`
|
||||
- `ai/inbox/`
|
||||
- `scripts/*/generated/`
|
||||
|
||||
Ignored Obsidian runtime files include workspace layout, plugin cache, snippets, and local plugin installs.
|
||||
|
||||
Project-agnostic memory helpers live under `scripts/memory/`:
|
||||
|
||||
- `scripts/memory/memory.sh create <type> <slug> [title]`
|
||||
- `scripts/memory/memory.sh search <query> [folder]`
|
||||
- `scripts/memory/memory.sh base-query <base-name> [format]`
|
||||
- `scripts/memory/memory.sh health`
|
||||
|
||||
Obsidian adapter helpers live under `scripts/obsidian/`:
|
||||
|
||||
- `scripts/obsidian/cli.sh <obsidian-cli-command>`
|
||||
- `scripts/obsidian/open.sh <vault-relative-path>`
|
||||
- `scripts/obsidian/daily.sh`
|
||||
- `scripts/obsidian/search.sh <query>`
|
||||
- `scripts/obsidian/uri.sh <action> key=value`
|
||||
|
||||
---
|
||||
|
||||
## Creating Another Project
|
||||
|
||||
1. Copy `profiles/example/` to `profiles/<project>/`.
|
||||
2. Fill in `profiles/<project>/profile.md`.
|
||||
3. Set `AIW_PROJECT_PROFILE=<project>`.
|
||||
4. Configure any communication connector with `AIW_*` variables.
|
||||
5. Create or adapt `project-knowledge/` for the project-specific canonical memory.
|
||||
6. Use `/workspace-context` to load the core plus active profile.
|
||||
|
||||
See `core/profiles/create-project-profile.md` for the full checklist.
|
||||
The reusable core should not depend on a company name, ticket prefix, channel name, programming stack, or AI client.
|
||||
|
||||
@@ -11,7 +11,7 @@ tags:
|
||||
|
||||
This folder contains the operating memory for the AI agent.
|
||||
|
||||
It is not Fidelity project documentation. Do not transfer this folder as project knowledge for a new engineer. Transfer `project-knowledge/` for the project second brain, and use this folder to explain how the agent should maintain that knowledge.
|
||||
It is not Fidelity project documentation. Do not transfer this folder as project knowledge for a new engineer. Transfer `workspaces/fidelity/project-knowledge/` for the project second brain, and use this folder to explain how the agent should maintain that knowledge.
|
||||
|
||||
---
|
||||
|
||||
@@ -28,8 +28,8 @@ It is not Fidelity project documentation. Do not transfer this folder as project
|
||||
|
||||
## Relationship To Project Knowledge
|
||||
|
||||
- `project-knowledge/` is the clean Obsidian vault and project second brain.
|
||||
- `workspaces/fidelity/project-knowledge/` is the clean Obsidian vault and project second brain.
|
||||
- `agent-memory/` is the agent operating manual.
|
||||
- `ai/inbox/` and connector `generated/` folders are evidence, not canonical memory.
|
||||
- `workspaces/fidelity/inbox/` and connector `generated/` folders are evidence, not canonical memory.
|
||||
- `scripts/memory/` is the project-agnostic interface for reading, searching, creating, querying, and validating project knowledge.
|
||||
- `scripts/obsidian/` is the current Obsidian adapter and must not become the core abstraction.
|
||||
|
||||
@@ -27,10 +27,10 @@ This applies to:
|
||||
- debugging discussions
|
||||
- corrections to previous understanding
|
||||
|
||||
The agent must not wait for a separate promotion command. The agent should proactively update `project-knowledge/` (including 01-current, 02-work-items, 03-context, 04-people, 06-daily) within the same conversational turn when new information is clear, durable, and the destination is obvious.
|
||||
The agent must not wait for a separate promotion command. The agent should proactively update `workspaces/fidelity/project-knowledge/` (including 01-current, 02-work-items, 03-context, 04-people, 06-daily) within the same conversational turn when new information is clear, durable, and the destination is obvious.
|
||||
|
||||
- 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/`.
|
||||
- When editing `workspaces/fidelity/project-knowledge/`, write as a human engineer maintaining shared project documentation.
|
||||
- Keep agent-operating logic out of `workspaces/fidelity/project-knowledge/`; store that logic in prompts, commands, skills, agents, or `agent-memory/`.
|
||||
- Answer-first rule: when the user's main goal is analysis, review, translation, or drafting, answer first unless persistence is required to avoid losing a clear durable fact.
|
||||
- Do not create a brand-new canonical note during the critical path of the answer unless the user explicitly asked to save the fact or the new note is the smallest correct update.
|
||||
- Prefer updating an existing canonical note over creating a new file when both are valid.
|
||||
@@ -71,7 +71,7 @@ Avoid low-value learning-session questions such as:
|
||||
- whether a specific PR was approved today
|
||||
- whether a ticket moved columns today
|
||||
- what the next standup line should be
|
||||
- temporary sequencing questions that belong in `project-knowledge/01-current/` or `project-knowledge/06-daily/`
|
||||
- temporary sequencing questions that belong in `workspaces/fidelity/project-knowledge/01-current/` or `workspaces/fidelity/project-knowledge/06-daily/`
|
||||
|
||||
Prefer high-value questions such as:
|
||||
|
||||
@@ -130,7 +130,7 @@ Examples:
|
||||
- A standup formatting correction should update `prompts/standup.md` and the shared workflow in `.agents/workflows/standup.md`.
|
||||
- A Mattermost freshness correction should update the Mattermost command/plugin instructions.
|
||||
- A Copilot prompt-structure correction should update `prompts/copilot-prompt.md`, `.agents/workflows/copilot-prompt.md`, or the shared skill/rule source.
|
||||
- A Swift answer-quality correction should update the relevant iOS skill or `project-knowledge/03-context/ios/` guidance.
|
||||
- A Swift answer-quality correction should update the relevant iOS skill or `workspaces/fidelity/project-knowledge/03-context/ios/` guidance.
|
||||
|
||||
Keep the daily log as evidence of what happened, but make the reusable behavior live in the file that controls that behavior.
|
||||
|
||||
@@ -138,7 +138,7 @@ Keep the daily log as evidence of what happened, but make the reusable behavior
|
||||
|
||||
## File Selection
|
||||
|
||||
### `project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
### `workspaces/fidelity/project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
|
||||
Default destination for:
|
||||
|
||||
@@ -148,7 +148,7 @@ Default destination for:
|
||||
- story and approval movement
|
||||
- context that is important now but may evolve later
|
||||
|
||||
### `project-knowledge/01-current/current-work.md`
|
||||
### `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
|
||||
Use when the fact changes the active work window, including:
|
||||
|
||||
@@ -157,28 +157,28 @@ Use when the fact changes the active work window, including:
|
||||
- current blockers or debugging constraints
|
||||
- manager direction that changes the next few days of work
|
||||
|
||||
### `project-knowledge/02-work-items/*.md` and `project-knowledge/01-current/work-items.md`
|
||||
### `workspaces/fidelity/project-knowledge/02-work-items/*.md` and `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
|
||||
Use `project-knowledge/02-work-items/*.md` as the canonical memory for current Jira-linked work that should remain easy to reference across sessions, especially:
|
||||
Use `workspaces/fidelity/project-knowledge/02-work-items/*.md` as the canonical memory for current Jira-linked work that should remain easy to reference across sessions, especially:
|
||||
|
||||
- Jira IDs
|
||||
- approved or explicit titles
|
||||
- currently relevant status notes
|
||||
- current points or scope notes
|
||||
|
||||
Use `project-knowledge/01-current/work-items.md` as the summary view of what is active now.
|
||||
Use `workspaces/fidelity/project-knowledge/01-current/work-items.md` as the summary view of what is active now.
|
||||
|
||||
These files should help standups and manager updates mention work items precisely.
|
||||
|
||||
### `project-knowledge/03-context/project.md`
|
||||
### `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
|
||||
Use for durable project knowledge that should survive beyond the current work window.
|
||||
|
||||
### `project-knowledge/04-people/manager.md`
|
||||
### `workspaces/fidelity/project-knowledge/04-people/manager.md`
|
||||
|
||||
Use only when a communication preference or manager expectation becomes stable enough to reuse repeatedly.
|
||||
|
||||
### `project-knowledge/04-people/index.md` and `project-knowledge/04-people/*.md`
|
||||
### `workspaces/fidelity/project-knowledge/04-people/index.md` and `workspaces/fidelity/project-knowledge/04-people/*.md`
|
||||
|
||||
Use these files for:
|
||||
|
||||
@@ -192,7 +192,7 @@ When the role is not explicit, store:
|
||||
- what kinds of topics they influence
|
||||
- how they affect approvals, scope, debugging, or communication
|
||||
|
||||
### `project-knowledge/05-decisions/*.md`
|
||||
### `workspaces/fidelity/project-knowledge/05-decisions/*.md`
|
||||
|
||||
Use for explicit confirmed decisions with ongoing impact.
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ The agent must keep the workspace behavior aligned with recurring user correctio
|
||||
- Update `.opencode/commands/` for slash-command behavior.
|
||||
- Update `prompts/` for reusable drafting shape.
|
||||
- Update `.opencode/agents/` and `AGENTS.md` for default agent behavior.
|
||||
- Update `.opencode/skills/` for specialized workflows.
|
||||
- Update `.agents/skills/` for specialized workflows.
|
||||
- Update `agent-memory/` for reusable agent operating rules.
|
||||
- Update `project-knowledge/` only when the correction changes project knowledge or project-facing process documentation.
|
||||
- Update `workspaces/fidelity/project-knowledge/` only when the correction changes project knowledge or project-facing process documentation.
|
||||
|
||||
---
|
||||
|
||||
@@ -32,4 +32,3 @@ The agent must keep the workspace behavior aligned with recurring user correctio
|
||||
- Agent implementation chatter.
|
||||
- Generic preference notes that only affect agent behavior.
|
||||
- Duplicate summaries of already-correct project facts.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: agent-integration
|
||||
status: active
|
||||
updated: 2026-04-17
|
||||
updated: 2026-05-20
|
||||
tags:
|
||||
- communication
|
||||
- evidence
|
||||
@@ -17,16 +17,24 @@ Communication connectors extract evidence. The agent decides what to promote.
|
||||
|
||||
Mattermost is the current live communication connector.
|
||||
|
||||
- Fresh output goes to `ai/inbox/mattermost-latest.md`.
|
||||
- Generated extraction artifacts stay under `scripts/mattermost/generated/`.
|
||||
- Primary local evidence is the Mattermost proxy mirror under `workspaces/fidelity/inbox/mattermost-mirror/` when present.
|
||||
- Prefer `workspaces/fidelity/inbox/mattermost-mirror/latest.md` / `latest.jsonl` for latest-message context, `by-date/YYYY/MM/YYYY-MM-DD.jsonl` for daily/standup context, `channels/<channel>/YYYY/MM/YYYY-MM-DD.jsonl` for channel-specific context, and `threads/<root-or-post-id>.jsonl` for thread-specific context.
|
||||
- Use `scripts/mattermost-proxy/read-context.py` from commands/workflows instead of reading ad hoc files; it prefers the profile proxy mirror and can read configured sync artifacts when a mirror is unavailable.
|
||||
- Legacy fresh output may still go to `workspaces/fidelity/inbox/mattermost-latest.md`.
|
||||
- Legacy generated extraction artifacts stay under `scripts/mattermost/generated/`.
|
||||
- Failed syncs must not update project knowledge.
|
||||
- Latest-message requests must refresh Mattermost before answering.
|
||||
- Latest-message requests are read-first. The agent may identify a memory update candidate, but should not edit `project-knowledge/` from the latest-message command unless the user explicitly asks to promote the fact.
|
||||
- Latest-message requests are read-first. The agent may identify a memory update candidate, but should not edit `workspaces/fidelity/project-knowledge/` from the latest-message command unless the user explicitly asks to promote the fact.
|
||||
- Standup generation is a separate required-refresh flow: it must fetch Mattermost before drafting, even though general prompts should not sync automatically.
|
||||
- Standup reads should use the focused reader mode, `scripts/mattermost-proxy/read-context.py --mode standup --today YYYY-MM-DD`, which reads date-bucketed previous-workday/today records and should use the active profile's configured `AIW_MATTERMOST_CONTEXT_CHANNELS` when available. Avoid loading broad mirror `latest.md` into standup prompts because it may include stale or unrelated channels and waste tokens. Keep project-specific channel names out of reusable connector code.
|
||||
- If adding MCP support for Mattermost, treat it as a read-only query wrapper over the existing proxy mirror and `read-context.py`, not as a replacement for the capture/mirror pipeline. Keep the mirror's file layout as canonical raw evidence and expose only narrow tools such as latest, standup/date, channel, and thread reads with channel filters and limits.
|
||||
- Do not build a write-capable Mattermost MCP or expose tokens, cookies, raw headers, or broad unfiltered raw dumps through MCP. MCP output should remain evidence for agent reasoning; promotion to `workspaces/fidelity/project-knowledge/` still follows normal memory rules.
|
||||
- If the proxy mirror is running, treat it as fresher than generated sync artifacts. Do not ignore mirror evidence merely because a sync command also ran.
|
||||
- Do not refresh Mattermost just because a prompt mentions a manager or stakeholder.
|
||||
- Treat document review, message polishing, translation, and "does this align with Jeff's expectations?" prompts as normal drafting tasks unless the user explicitly asks for the latest message or fresh Mattermost evidence.
|
||||
- The OpenCode plugin syncs automatically only for explicit latest-message requests by default.
|
||||
- Optional aggressive sync can be enabled with `AIW_MATTERMOST_SYNC_ON_SESSION=true` or `AIW_MATTERMOST_SYNC_ON_PROMPT=true`, but these should stay off for low-latency daily use.
|
||||
- When invoking Mattermost sync from OpenCode, do not use parameter expansion that places a command with spaces into a single shell word, such as `${VAR:-bash scripts/mattermost/sync.sh}`. Run configured command strings via `bash -lc "$AIW_MATTERMOST_SYNC_CMD"`, and run the built-in wrapper as separate words: `bash scripts/mattermost/sync.sh`.
|
||||
|
||||
---
|
||||
|
||||
@@ -34,6 +42,6 @@ Mattermost is the current live communication connector.
|
||||
|
||||
Slack export import is the current historical archive connector.
|
||||
|
||||
- Archive evidence stays outside `project-knowledge/`.
|
||||
- Archive evidence stays outside `workspaces/fidelity/project-knowledge/`.
|
||||
- Promote only durable project facts, people context, process rules, or historical architecture lessons.
|
||||
- Do not promote dated status details unless they explain current context.
|
||||
|
||||
77
agent-memory/integrations/mem9.md
Normal file
77
agent-memory/integrations/mem9.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
type: agent-integration
|
||||
status: proposed
|
||||
updated: 2026-05-05
|
||||
tags:
|
||||
- memory
|
||||
- integration
|
||||
- mem9
|
||||
---
|
||||
# mem9 Integration
|
||||
|
||||
## Goal
|
||||
|
||||
Use mem9 as a cross-session, cross-agent recall layer without replacing the workspace's auditable Markdown memory.
|
||||
|
||||
## Source Of Truth
|
||||
|
||||
`workspaces/fidelity/project-knowledge/` remains the canonical human-readable Fidelity project memory.
|
||||
|
||||
`agent-memory/` remains the canonical operating memory for agent behavior, workflows, promotion rules, and integration guidance.
|
||||
|
||||
mem9 should recall and surface relevant facts, but durable project updates must still be promoted into the correct Markdown file when they become canonical.
|
||||
|
||||
## Recommended Scope
|
||||
|
||||
Use a project-scoped mem9 profile for this workspace when possible so Fidelity context, agent behavior, and personal/global memories do not collapse into one undifferentiated pool.
|
||||
|
||||
Do not bulk-import raw inboxes, generated sync output, full chat transcripts, or broad project folders by default. Import only curated facts, stable preferences, and distilled summaries.
|
||||
|
||||
## What To Store
|
||||
|
||||
- Stable user/workspace preferences that should survive sessions.
|
||||
- Durable agent behavior rules that are useful across Codex/OpenCode sessions.
|
||||
- Verified project facts already present in canonical Markdown.
|
||||
- Short summaries of current work that help recall where to begin.
|
||||
|
||||
## What Not To Store
|
||||
|
||||
- Secrets, credentials, API keys, tokens, auth cookies, or private environment values.
|
||||
- Raw Mattermost/Slack inbox dumps.
|
||||
- Fidelity product source code or proprietary implementation snippets.
|
||||
- Unverified assumptions, temporary sync failures, or tooling chatter.
|
||||
- Duplicates of every daily note without curation.
|
||||
|
||||
## Efficient Use Pattern
|
||||
|
||||
1. Recall mem9 early for user preferences and relevant workspace history.
|
||||
2. Load hot Markdown context from `AGENTS.md` / `opencode.json` instructions.
|
||||
3. For current-work questions, still inspect `workspaces/fidelity/project-knowledge/01-current/current-work.md` and the latest relevant daily note.
|
||||
4. Answer or act from verified context.
|
||||
5. When the interaction adds durable knowledge, update canonical Markdown first; store a compact mem9 memory only if it improves future recall.
|
||||
|
||||
## Codex Setup Notes
|
||||
|
||||
The upstream mem9 Codex integration uses a marketplace plugin and managed hooks. `$mem9:setup` is the primary setup command. It manages shared profiles, credentials, user/project scope, and hook repair.
|
||||
|
||||
Expected local surfaces include:
|
||||
|
||||
- `$CODEX_HOME/hooks.json`
|
||||
- `$CODEX_HOME/config.toml`
|
||||
- `$CODEX_HOME/mem9/`
|
||||
- `$MEM9_HOME/.credentials.json`
|
||||
- `<project>/.codex/mem9/config.json` for project overrides
|
||||
|
||||
Keep `$MEM9_HOME/.credentials.json` outside the repository and never commit API keys.
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
- Confirm Codex CLI is at least the version required by the mem9 plugin.
|
||||
- Confirm Node.js 22 or newer is available to the Codex runtime.
|
||||
- Install the mem9 Codex plugin from the mem9 marketplace.
|
||||
- Run `$mem9:setup` and choose hosted API or self-hosted API.
|
||||
- Apply project scope for this workspace if using a dedicated Fidelity profile.
|
||||
- Verify `$mem9:recall` returns relevant memories.
|
||||
- Verify `$mem9:store` stores one approved non-sensitive memory.
|
||||
- Inspect mem9 dashboard / memory list for accidental sensitive content.
|
||||
- Keep canonical Markdown updates auditable through git.
|
||||
@@ -15,20 +15,16 @@ Use `scripts/memory/memory.sh` as the project-agnostic interface to project know
|
||||
|
||||
## Default Root
|
||||
|
||||
The primary project knowledge directory is `project-knowledge/`.
|
||||
The primary project knowledge directory is `workspaces/fidelity/project-knowledge/`.
|
||||
|
||||
Environment variable precedence:
|
||||
Configuration precedence:
|
||||
|
||||
1. `AIW_PROJECT_KNOWLEDGE_DIR`
|
||||
2. `AIW_MEMORY_VAULT_DIR`
|
||||
3. `AIW_OBSIDIAN_VAULT_DIR`
|
||||
4. `<workspace-root>/project-knowledge`
|
||||
|
||||
`AIW_MEMORY_VAULT_DIR` and `AIW_OBSIDIAN_VAULT_DIR` are transition aliases only.
|
||||
1. `AIW_PROJECT_PROFILE`
|
||||
2. `profiles/<profile>/workspace.json`
|
||||
3. optional local `AIW_PROJECT_KNOWLEDGE_DIR` override
|
||||
|
||||
---
|
||||
|
||||
## Agent Rule
|
||||
|
||||
Prefer the memory interface for typed note creation, search, Base queries, and health checks. Use direct Markdown edits when the adapter fails or when precise edits are simpler and safer.
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ Obsidian is the current interface over canonical Markdown memory. The workspace-
|
||||
|
||||
## Recommended Start
|
||||
|
||||
Open the `project-knowledge/` folder as the Obsidian vault, not the repository root and not `agent-memory/`.
|
||||
Open the `workspaces/fidelity/project-knowledge/` folder as the Obsidian vault, not the repository root and not `agent-memory/`.
|
||||
|
||||
Open:
|
||||
|
||||
- [Start Here](../../project-knowledge/00-start/start-here.md)
|
||||
- [New Member Onboarding](../../project-knowledge/00-start/onboarding.md)
|
||||
- [Knowledge Maps](../../project-knowledge/07-maps/index.md)
|
||||
- [Start Here](../../workspaces/fidelity/project-knowledge/00-start/start-here.md)
|
||||
- [New Member Onboarding](../../workspaces/fidelity/project-knowledge/00-start/onboarding.md)
|
||||
- [Knowledge Maps](../../workspaces/fidelity/project-knowledge/07-maps/index.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -32,26 +32,26 @@ Open:
|
||||
|
||||
Start with:
|
||||
|
||||
- [New Member Onboarding](../../project-knowledge/00-start/onboarding.md)
|
||||
- [Glossary](../../project-knowledge/00-start/glossary.md)
|
||||
- [Current Work Map](../../project-knowledge/07-maps/current-work.md)
|
||||
- [Fidelity Domain Map](../../project-knowledge/07-maps/fidelity-domain.md)
|
||||
- [New Member Onboarding](../../workspaces/fidelity/project-knowledge/00-start/onboarding.md)
|
||||
- [Glossary](../../workspaces/fidelity/project-knowledge/00-start/glossary.md)
|
||||
- [Current Work Map](../../workspaces/fidelity/project-knowledge/07-maps/current-work.md)
|
||||
- [Fidelity Domain Map](../../workspaces/fidelity/project-knowledge/07-maps/fidelity-domain.md)
|
||||
|
||||
### Daily Work View
|
||||
|
||||
Start with:
|
||||
|
||||
- [Current Work Map](../../project-knowledge/07-maps/current-work.md)
|
||||
- [Work Items Map](../../project-knowledge/07-maps/work-items.md)
|
||||
- [Daily Notes Index](../../project-knowledge/06-daily/index.md)
|
||||
- [Current Work Map](../../workspaces/fidelity/project-knowledge/07-maps/current-work.md)
|
||||
- [Work Items Map](../../workspaces/fidelity/project-knowledge/07-maps/work-items.md)
|
||||
- [Daily Notes Index](../../workspaces/fidelity/project-knowledge/06-daily/index.md)
|
||||
|
||||
### System Understanding View
|
||||
|
||||
Start with:
|
||||
|
||||
- [Fidelity Domain Map](../../project-knowledge/07-maps/fidelity-domain.md)
|
||||
- [Fidelity Apps Map](../../project-knowledge/07-maps/fidelity-apps.md)
|
||||
- [People Map](../../project-knowledge/07-maps/people.md)
|
||||
- [Fidelity Domain Map](../../workspaces/fidelity/project-knowledge/07-maps/fidelity-domain.md)
|
||||
- [Fidelity Apps Map](../../workspaces/fidelity/project-knowledge/07-maps/fidelity-apps.md)
|
||||
- [People Map](../../workspaces/fidelity/project-knowledge/07-maps/people.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -50,4 +50,4 @@ Reusable workspace logic and project-independent operating rules.
|
||||
## Project Profile
|
||||
|
||||
- Active project profile: `profiles/fidelity/profile.md`
|
||||
- Project knowledge vault: `project-knowledge/`
|
||||
- Project knowledge vault: `workspaces/fidelity/project-knowledge/`
|
||||
|
||||
@@ -51,11 +51,11 @@ Commands, prompts, skills, workflows, and automation surfaces that make the work
|
||||
## Skills
|
||||
|
||||
- Shared skills source: `.agents/skills/`
|
||||
- Skills index: `.opencode/skills/index.md`
|
||||
- Workspace memory curation: `.opencode/skills/workspace-memory-curation/SKILL.md`
|
||||
- Professional communication: `.opencode/skills/professional-communication/SKILL.md`
|
||||
- Status reporting: `.opencode/skills/status-reporting/SKILL.md`
|
||||
- AI prompt engineering: `.opencode/skills/ai-prompt-engineering/SKILL.md`
|
||||
- Skills index: `.agents/skills/index.md`
|
||||
- Workspace memory curation: `.agents/skills/workspace-memory-curation/SKILL.md`
|
||||
- Professional communication: `.agents/skills/professional-communication/SKILL.md`
|
||||
- Status reporting: `.agents/skills/status-reporting/SKILL.md`
|
||||
- AI prompt engineering: `.agents/skills/ai-prompt-engineering/SKILL.md`
|
||||
|
||||
---
|
||||
|
||||
@@ -75,5 +75,5 @@ Commands, prompts, skills, workflows, and automation surfaces that make the work
|
||||
- Project-agnostic memory scripts: `scripts/memory/`
|
||||
- Current Obsidian adapter: `scripts/obsidian/`
|
||||
- Obsidian MCP migration plan: `agent-memory/workflows/obsidian-mcp-migration.md`
|
||||
- Project knowledge vault: `project-knowledge/`
|
||||
- Project knowledge vault: `workspaces/fidelity/project-knowledge/`
|
||||
- Agent operating memory: `agent-memory/`
|
||||
|
||||
@@ -18,23 +18,23 @@ 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/`.
|
||||
- Keep `workspaces/fidelity/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 `workspaces/fidelity/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 `.agents/skills/` instead of `workspaces/fidelity/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.
|
||||
- Keep templates under `workspaces/fidelity/project-knowledge/09-templates/` out of real-note Bases by filtering the template folder.
|
||||
- Role mapping files should not use `type: person`; reserve `type: person` for actual people profiles.
|
||||
- Work-item notes should keep known `systems`, `workstreams`, `people`, and `related` properties current.
|
||||
- Daily notes should keep `focus`, `work-items`, and `blockers` properties current when the values are clear.
|
||||
- Use the smallest correct destination:
|
||||
- `project-knowledge/06-daily/YYYY-MM-DD.md` for daily progress and evolving findings
|
||||
- `project-knowledge/01-current/current-work.md` for near-term active work
|
||||
- `project-knowledge/02-work-items/*.md` for canonical Jira-linked active work
|
||||
- `project-knowledge/01-current/work-items.md` for the compact active-work summary
|
||||
- `project-knowledge/03-context/` for durable project knowledge
|
||||
- `project-knowledge/04-people/` for named person context
|
||||
- `.opencode/commands/`, `prompts/`, `.opencode/agents/`, `.opencode/skills/`, `agent-memory/`, `core/`, or `scripts/` for reusable behavior rules that control how the workspace responds
|
||||
- `workspaces/fidelity/project-knowledge/06-daily/YYYY-MM-DD.md` for daily progress and evolving findings
|
||||
- `workspaces/fidelity/project-knowledge/01-current/current-work.md` for near-term active work
|
||||
- `workspaces/fidelity/project-knowledge/02-work-items/*.md` for canonical Jira-linked active work
|
||||
- `workspaces/fidelity/project-knowledge/01-current/work-items.md` for the compact active-work summary
|
||||
- `workspaces/fidelity/project-knowledge/03-context/` for durable project knowledge
|
||||
- `workspaces/fidelity/project-knowledge/04-people/` for named person context
|
||||
- `.opencode/commands/`, `prompts/`, `.opencode/agents/`, `.agents/skills/`, `agent-memory/`, `core/`, or `scripts/` for reusable behavior rules that control how the workspace responds
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ The reusable model lives in `core/memory/operational-memory.md`. This file recor
|
||||
|
||||
## Memory Classes
|
||||
|
||||
- `daily`: dated progress and evidence in `project-knowledge/06-daily/`.
|
||||
- `state`: near-term active work in `project-knowledge/01-current/`.
|
||||
- `work-items`: ticket-scoped memory in `project-knowledge/02-work-items/`.
|
||||
- `stable-context`: durable systems, workstreams, process, and iOS context in `project-knowledge/03-context/`.
|
||||
- `people`: collaborators, stakeholders, and role mappings in `project-knowledge/04-people/`.
|
||||
- `decisions`: accepted durable decisions in `project-knowledge/05-decisions/`.
|
||||
- `daily`: dated progress and evidence in `workspaces/fidelity/project-knowledge/06-daily/`.
|
||||
- `state`: near-term active work in `workspaces/fidelity/project-knowledge/01-current/`.
|
||||
- `work-items`: ticket-scoped memory in `workspaces/fidelity/project-knowledge/02-work-items/`.
|
||||
- `stable-context`: durable systems, workstreams, process, and iOS context in `workspaces/fidelity/project-knowledge/03-context/`.
|
||||
- `people`: collaborators, stakeholders, and role mappings in `workspaces/fidelity/project-knowledge/04-people/`.
|
||||
- `decisions`: accepted durable decisions in `workspaces/fidelity/project-knowledge/05-decisions/`.
|
||||
- `tooling-behavior`: agent and workspace behavior in `agent-memory/`, `.opencode/`, `prompts/`, `scripts/`, and `core/`.
|
||||
|
||||
---
|
||||
@@ -31,9 +31,9 @@ The reusable model lives in `core/memory/operational-memory.md`. This file recor
|
||||
|
||||
Raw evidence stays outside project knowledge:
|
||||
|
||||
- `ai/inbox/`
|
||||
- `workspaces/fidelity/inbox/`
|
||||
- `scripts/mattermost/generated/`
|
||||
- `scripts/slack/generated/`
|
||||
|
||||
Only curated, high-confidence project facts should be promoted into `project-knowledge/`.
|
||||
Only curated, high-confidence project facts should be promoted into `workspaces/fidelity/project-knowledge/`.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ If a fact is ambiguous, skip it or keep it only in the daily log with appropriat
|
||||
|
||||
## File Selection
|
||||
|
||||
### Promote to `project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
### Promote to `workspaces/fidelity/project-knowledge/06-daily/YYYY-MM-DD.md`
|
||||
|
||||
Use the daily log for:
|
||||
|
||||
@@ -37,7 +37,7 @@ Use the daily log for:
|
||||
|
||||
Daily logs are the default destination for most promoted Mattermost facts.
|
||||
|
||||
### Promote to `project-knowledge/01-current/current-work.md`
|
||||
### Promote to `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
|
||||
Use current state only for facts that materially affect active work over the next few days, such as:
|
||||
|
||||
@@ -48,9 +48,9 @@ Use current state only for facts that materially affect active work over the nex
|
||||
|
||||
Do not copy every daily update into current state.
|
||||
|
||||
### Promote to `project-knowledge/02-work-items/*.md` and `project-knowledge/01-current/work-items.md`
|
||||
### Promote to `workspaces/fidelity/project-knowledge/02-work-items/*.md` and `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
|
||||
Use `project-knowledge/02-work-items/*.md` for:
|
||||
Use `workspaces/fidelity/project-knowledge/02-work-items/*.md` for:
|
||||
|
||||
- explicit Jira IDs
|
||||
- approved or explicit story titles
|
||||
@@ -60,9 +60,9 @@ Use `project-knowledge/02-work-items/*.md` for:
|
||||
|
||||
If a Jira item is likely to appear again in standups or manager updates, it belongs here.
|
||||
|
||||
Use `project-knowledge/01-current/work-items.md` as the compact summary of which ticket files are active.
|
||||
Use `workspaces/fidelity/project-knowledge/01-current/work-items.md` as the compact summary of which ticket files are active.
|
||||
|
||||
### Promote to `project-knowledge/03-context/project.md`
|
||||
### Promote to `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
|
||||
Use project context only for durable project knowledge that should survive beyond the current work window, such as:
|
||||
|
||||
@@ -73,11 +73,11 @@ Use project context only for durable project knowledge that should survive beyon
|
||||
|
||||
Do not promote story-specific daily movement into project context unless it changes durable project understanding.
|
||||
|
||||
### Promote to `project-knowledge/05-decisions/*.md`
|
||||
### Promote to `workspaces/fidelity/project-knowledge/05-decisions/*.md`
|
||||
|
||||
Use decisions only for explicit confirmed decisions with medium or long-term impact.
|
||||
|
||||
### Promote to `project-knowledge/04-people/index.md` and `project-knowledge/04-people/*.md`
|
||||
### Promote to `workspaces/fidelity/project-knowledge/04-people/index.md` and `workspaces/fidelity/project-knowledge/04-people/*.md`
|
||||
|
||||
Use these files when:
|
||||
|
||||
@@ -141,5 +141,5 @@ Given Mattermost updates like:
|
||||
Automatic behavior should be:
|
||||
|
||||
- add all of them to today's log if they are relevant to today's work
|
||||
- promote only the currently actionable subset to `project-knowledge/01-current/current-work.md`
|
||||
- keep story-specific details out of `project-knowledge/03-context/project.md` unless they reveal a durable project rule
|
||||
- promote only the currently actionable subset to `workspaces/fidelity/project-knowledge/01-current/current-work.md`
|
||||
- keep story-specific details out of `workspaces/fidelity/project-knowledge/03-context/project.md` unless they reveal a durable project rule
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: agent-workflow
|
||||
status: active
|
||||
updated: 2026-04-17
|
||||
updated: 2026-05-12
|
||||
tags:
|
||||
- process
|
||||
- ai-prompting
|
||||
@@ -58,6 +58,13 @@ Use this structure by default:
|
||||
- Include "Do not assume REST is active by default" for REST migration tasks.
|
||||
- Include "Separate external issue from regression" for AO/Discourse issues.
|
||||
- Include "Validate against Fid4/consumer path when needed" for XFlow integration tasks.
|
||||
- For VS Code multi-root Copilot workflows, preserve repo-provided customizations such as `.github/prompts`, `.github/instructions`, `.github/agents`, `.github/skills`, and `AGENTS.md`. Shared `fidelity-ai-copilot` customizations should supplement these repo files, while repo-specific instructions should be treated as the practical authority when they conflict.
|
||||
- For Fidelity Jira/Confluence access from GitHub Copilot CLI or VS Code, do not assume the approved access method. First have the target AI read the current Fidelity-provided human instructions from Confluence or local exported docs, then configure the smallest matching workflow. If those instructions require terminal `curl` with environment variables such as `COPILOT_JIRA_URL` and `COPILOT_JIRA_TOKEN`, enforce that path; otherwise follow the documented Fidelity-approved method. Never print, persist, or hardcode tokens.
|
||||
- Treat `fidelity-ai-copilot` as a self-improving AI harness rather than a static prompt dump: the target AI should notice recurring useful workflows, newly discovered internal instructions, and tool changes, then propose small auditable updates to instructions, skills, prompts, agents, specs, or validation checklists. It should ask before making broad changes and keep product repos clean.
|
||||
- For corporate-tool captures in `fidelity-ai-copilot`, prefer a single raw Charles Mirror source such as `archive/charles-mirror/` and treat it as read-only evidence organized by hostname. Generated Copilot outputs should be written to separate per-platform folders only when useful, with prompts requiring source inspection, narrow scope, local-only processing, and explicit evidence paths.
|
||||
- When advising on `fidelity-ai-copilot` customization, use this routing: keep global safety and repo role in `AGENTS.md` / `.github/copilot-instructions.md`; use `.github/instructions/*.instructions.md` for path-scoped rules such as `archive/**`; use `.github/prompts/*.prompt.md` for repeatable slash-command tasks; use `.github/agents/*.agent.md` for persistent personas with tool restrictions and handoffs; use `.github/skills/*/SKILL.md` for reusable multi-step capabilities with scripts, examples, or resources. Prefer small, composable artifacts over one large instruction file.
|
||||
- For read-only evidence prompts such as Discourse/Charles Mirror search, explicitly prevent the target AI from editing the prompt/configuration files while running the workflow. If Copilot changes `.github/prompts/*.prompt.md` during an evidence query, treat that as a workflow bug unless the user specifically asked to update the prompt.
|
||||
- When the user says they will handle dependency alignment, registry configuration, or compile/test execution manually on the development machine, generated Copilot follow-ups should not ask Copilot to solve those dependency/tooling issues or run broad builds. Instead, ask Copilot for the smallest source-level fix for the specific compiler error the user provides, state that the user will rerun validation manually, and request a concise summary of changed files and expected validation impact.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ tags: [obsidian, mcp, migration, memory]
|
||||
|
||||
Replace the current Obsidian CLI-backed adapter path with an Obsidian MCP-first integration while preserving the workspace memory model:
|
||||
|
||||
- `project-knowledge/` remains the canonical source of truth
|
||||
- `workspaces/fidelity/project-knowledge/` remains the canonical source of truth
|
||||
- `scripts/memory/` remains the stable workspace memory contract
|
||||
- direct Markdown edits remain the safe fallback for precise curation
|
||||
- Obsidian stays an adapter/navigation layer, not a second memory store
|
||||
@@ -66,7 +66,7 @@ The migration should change the adapter, not the memory model.
|
||||
|
||||
- Do not move canonical memory out of Markdown
|
||||
- Do not encode promotion rules into the MCP layer
|
||||
- Do not make `project-knowledge/` depend on Obsidian-only storage
|
||||
- Do not make `workspaces/fidelity/project-knowledge/` depend on Obsidian-only storage
|
||||
- Do not remove direct Markdown editing as a fallback
|
||||
- Do not delete the current scripts until MCP coverage is validated in real use
|
||||
|
||||
@@ -116,7 +116,7 @@ Current Phase 1 checklist:
|
||||
- [x] Add OpenCode MCP config using `OBSIDIAN_API_KEY` environment substitution.
|
||||
- [x] Export `OBSIDIAN_API_KEY` in the shell that launches OpenCode.
|
||||
- [x] Restart OpenCode and confirm `opencode mcp list` shows `obsidian` connected.
|
||||
- [x] Validate read/search tools against `project-knowledge/` notes.
|
||||
- [x] Validate read/search tools against `workspaces/fidelity/project-knowledge/` notes.
|
||||
- [x] Validate write/append/delete behavior on a disposable test note before touching canonical memory.
|
||||
- [ ] Determine whether Bases/properties/backlinks/template behavior needs to remain on the existing CLI/direct-Markdown path.
|
||||
|
||||
@@ -208,9 +208,9 @@ Delete later only if truly unused:
|
||||
|
||||
### Keep
|
||||
|
||||
- `project-knowledge/.obsidian/`
|
||||
- `project-knowledge/08-bases/*.base`
|
||||
- `project-knowledge/09-templates/`
|
||||
- `workspaces/fidelity/project-knowledge/.obsidian/`
|
||||
- `workspaces/fidelity/project-knowledge/08-bases/*.base`
|
||||
- `workspaces/fidelity/project-knowledge/09-templates/`
|
||||
- `scripts/memory/`
|
||||
|
||||
### Deprecate then remove
|
||||
|
||||
@@ -51,4 +51,4 @@ Capture reusable prompting lessons so the agent does not need to re-research the
|
||||
|
||||
- Treat prompt improvement as eval-driven iteration: identify the exact bad output pattern, add the smallest correction, and check whether it fixes the failure without bloating the prompt.
|
||||
- When a correction is about workspace behavior, update the controlling prompt or command immediately so the next run benefits.
|
||||
- Keep project memory clean while improving prompt quality; do not store agent heuristics in `project-knowledge/`.
|
||||
- Keep project memory clean while improving prompt quality; do not store agent heuristics in `workspaces/fidelity/project-knowledge/`.
|
||||
|
||||
@@ -11,7 +11,7 @@ related:
|
||||
|
||||
This repository separates project knowledge from agent operation:
|
||||
|
||||
- `project-knowledge/` is the clean Obsidian second brain and transferable project memory.
|
||||
- `workspaces/fidelity/project-knowledge/` is the clean Obsidian second brain and transferable project memory.
|
||||
- `agent-memory/` is the operating manual for the AI agent.
|
||||
- Everything else is technical runtime, reusable core, profile configuration, scripts, commands, prompts, or raw evidence.
|
||||
|
||||
@@ -42,10 +42,10 @@ These folders are intentionally outside Obsidian memory:
|
||||
- `core/` stores reusable workspace logic.
|
||||
- `profiles/` stores project-specific profile declarations.
|
||||
- `scripts/` stores connectors, importers, and wrappers.
|
||||
- `ai/inbox/` stores live evidence from communication sync.
|
||||
- `workspaces/fidelity/inbox/` stores live evidence from communication sync.
|
||||
- `scripts/*/generated/` stores extracted evidence.
|
||||
|
||||
Runtime and generated files can be used as evidence, but durable project facts should be promoted into `project-knowledge/`.
|
||||
Runtime and generated files can be used as evidence, but durable project facts should be promoted into `workspaces/fidelity/project-knowledge/`.
|
||||
|
||||
Agent behavior rules belong in `agent-memory/`, not in the project vault.
|
||||
|
||||
@@ -55,7 +55,7 @@ Agent behavior rules belong in `agent-memory/`, not in the project vault.
|
||||
|
||||
Use `scripts/memory/` as the platform-agnostic interface to canonical memory.
|
||||
|
||||
Obsidian is the current visual and CLI-backed adapter, but the source of truth remains Markdown under `project-knowledge/`.
|
||||
Obsidian is the current visual and CLI-backed adapter, but the source of truth remains Markdown under `workspaces/fidelity/project-knowledge/`.
|
||||
|
||||
- Agents use `scripts/memory/memory.sh create` when a new typed note is needed.
|
||||
- Agents use `scripts/memory/memory.sh search` or direct Markdown reads for context lookup.
|
||||
@@ -66,6 +66,6 @@ Obsidian is the current visual and CLI-backed adapter, but the source of truth r
|
||||
|
||||
## Memory Rule
|
||||
|
||||
Promoted memory lives in `project-knowledge/`.
|
||||
Promoted memory lives in `workspaces/fidelity/project-knowledge/`.
|
||||
|
||||
Raw inbox and generated connector evidence stays outside the vault until the agent promotes durable facts.
|
||||
|
||||
@@ -15,7 +15,7 @@ It separates reusable tooling, project knowledge, and agent operating memory:
|
||||
|
||||
- `core/` contains reusable project-independent operating rules
|
||||
- `profiles/<project>/` contains project-specific configuration and assumptions
|
||||
- `project-knowledge/` contains transferable project documentation and current work memory
|
||||
- `workspaces/fidelity/project-knowledge/` contains transferable project documentation and current work memory
|
||||
- `agent-memory/` contains agent behavior, learning, promotion, integration, and verification rules
|
||||
|
||||
---
|
||||
@@ -48,14 +48,14 @@ When the user corrects a recurring behavior, the workspace should update the fil
|
||||
|
||||
- `core/` for reusable project-independent behavior
|
||||
- `profiles/<project>/` for project-specific assumptions
|
||||
- `project-knowledge/.obsidian/` only for portable Obsidian configuration, not project memory content
|
||||
- `workspaces/fidelity/project-knowledge/.obsidian/` only for portable Obsidian configuration, not project memory content
|
||||
- `scripts/memory/` for project-agnostic memory access, creation, search, Base queries, and health checks
|
||||
- `scripts/obsidian/` for the current Obsidian adapter, not for core memory semantics
|
||||
- `.agents/workflows/` for slash commands (with `.opencode/commands/` for compatibility)
|
||||
- `prompts/` for reusable drafting templates
|
||||
- `.agents/rules/` and `AGENTS.md` for default agent behavior
|
||||
- `.agents/skills/` for specialized workflows (with `.opencode/skills/` for compatibility)
|
||||
- `project-knowledge/00-start/` and `project-knowledge/03-context/process/` for project-facing onboarding and process rules
|
||||
- `.agents/skills/` for specialized workflows. Do not mirror into `.opencode/skills/`; OpenCode discovers `.agents/skills/` directly.
|
||||
- `workspaces/fidelity/project-knowledge/00-start/` and `workspaces/fidelity/project-knowledge/03-context/process/` for project-facing onboarding and process rules
|
||||
- `agent-memory/` for agent-specific behavior, learning, promotion, verification, and self-maintenance rules
|
||||
|
||||
Daily logs can preserve evidence, but they should not be the only place where a reusable behavior rule lives.
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# Mattermost Inbox
|
||||
|
||||
This directory stores raw or semi-processed communication captured from Mattermost before it is promoted into the persistent workspace context.
|
||||
|
||||
Recommended usage:
|
||||
|
||||
- `mattermost-latest.md` contains the most recent capture
|
||||
- timestamped snapshots can be stored here if needed
|
||||
- durable facts should be promoted into `vault/06-daily/`, `vault/01-current/`, `vault/02-work-items/`, `vault/03-context/`, `vault/04-people/`, or `vault/05-decisions/`
|
||||
|
||||
This directory is intentionally treated as an inbox, not as the final source of truth.
|
||||
9
apps/mac/AIWorkspace/.gitignore
vendored
Normal file
9
apps/mac/AIWorkspace/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
.build/
|
||||
.swiftpm/
|
||||
dist/
|
||||
DerivedData/
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
xcuserdata/
|
||||
*.xcuserstate
|
||||
.DS_Store
|
||||
19
apps/mac/AIWorkspace/Package.swift
Normal file
19
apps/mac/AIWorkspace/Package.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
// swift-tools-version: 6.0
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "AIWorkspace",
|
||||
platforms: [
|
||||
.macOS(.v13)
|
||||
],
|
||||
products: [
|
||||
.executable(name: "AIWorkspace", targets: ["AIWorkspace"])
|
||||
],
|
||||
targets: [
|
||||
.executableTarget(
|
||||
name: "AIWorkspace",
|
||||
path: "Sources"
|
||||
)
|
||||
]
|
||||
)
|
||||
109
apps/mac/AIWorkspace/README.md
Normal file
109
apps/mac/AIWorkspace/README.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# AI Workspace macOS Menu Bar App
|
||||
|
||||
Minimal SwiftUI `MenuBarExtra` app for controlling local AI Workspace services.
|
||||
|
||||
The app is intentionally a thin UI over the service manager. It reads live status from:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/services.py status --profile fidelity --json
|
||||
```
|
||||
|
||||
and sends lifecycle actions through `scripts/aiw/services.py`.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
swift build --package-path apps/mac/AIWorkspace
|
||||
```
|
||||
|
||||
## Package as `.app`
|
||||
|
||||
```bash
|
||||
apps/mac/AIWorkspace/scripts/package-app.sh
|
||||
```
|
||||
|
||||
Install to `~/Applications/AIWorkspace.app`:
|
||||
|
||||
```bash
|
||||
apps/mac/AIWorkspace/scripts/package-app.sh --install
|
||||
```
|
||||
|
||||
The script defaults to the per-user install location because this workspace is a
|
||||
developer-local utility and frequent rebuilds should not require `sudo`. To
|
||||
install system-wide instead, pass an explicit install directory:
|
||||
|
||||
```bash
|
||||
INSTALL_DIR=/Applications apps/mac/AIWorkspace/scripts/package-app.sh --install
|
||||
APP_PATH=/Applications/AIWorkspace.app apps/mac/AIWorkspace/scripts/install-start-at-login.sh
|
||||
```
|
||||
|
||||
Avoid keeping both `~/Applications/AIWorkspace.app` and
|
||||
`/Applications/AIWorkspace.app` installed unless you are intentionally comparing
|
||||
builds. They share the same bundle identifier (`com.aiworkspace.menu`) and can
|
||||
confuse LaunchServices, login item registration, and which copy opens at login.
|
||||
If both exist, quit any running AI Workspace instances and remove the stale copy.
|
||||
|
||||
## Build a DMG
|
||||
|
||||
```bash
|
||||
apps/mac/AIWorkspace/scripts/build-dmg.sh
|
||||
```
|
||||
|
||||
This creates:
|
||||
|
||||
```text
|
||||
apps/mac/AIWorkspace/dist/AIWorkspace.dmg
|
||||
```
|
||||
|
||||
The DMG contains `AIWorkspace.app` and an `Applications` shortcut for drag-and-drop installation.
|
||||
|
||||
One-step local install, optionally enabling start at login and opening the app:
|
||||
|
||||
```bash
|
||||
apps/mac/AIWorkspace/scripts/install.sh --start-at-login --open
|
||||
```
|
||||
|
||||
## Start at login
|
||||
|
||||
Preferred: open the installed app and use the **Start at Login** toggle in the UI. The app uses macOS `SMAppService` for login item registration.
|
||||
|
||||
Development fallback after installing the app bundle:
|
||||
|
||||
```bash
|
||||
apps/mac/AIWorkspace/scripts/install-start-at-login.sh
|
||||
```
|
||||
|
||||
To remove the login item:
|
||||
|
||||
```bash
|
||||
apps/mac/AIWorkspace/scripts/uninstall-start-at-login.sh
|
||||
```
|
||||
|
||||
## Run during development
|
||||
|
||||
```bash
|
||||
swift run --package-path apps/mac/AIWorkspace AIWorkspace
|
||||
```
|
||||
|
||||
## Current actions
|
||||
|
||||
- Refresh status
|
||||
- Start Fidelity services
|
||||
- Stop Fidelity services
|
||||
- Restart Context MCP
|
||||
- Open Mattermost through the service manager
|
||||
- Open Mattermost through the local proxy-managed launcher
|
||||
- Run Doctor
|
||||
- Copy Doctor JSON
|
||||
- Copy Photo Inbox URL
|
||||
- Copy recent logs
|
||||
- Open MCP Health
|
||||
- Open logs folder
|
||||
- Open project knowledge
|
||||
|
||||
## Notes
|
||||
|
||||
- This is not yet packaged as a signed `.app` bundle.
|
||||
- Start at login should be implemented later through a LaunchAgent or app login item.
|
||||
- Start at Login is available in the app UI through `SMAppService`. The LaunchAgent scripts are retained as development fallback utilities.
|
||||
- The app should remain a UI layer; service lifecycle remains in `scripts/aiw/services.py`.
|
||||
599
apps/mac/AIWorkspace/Sources/main.swift
Normal file
599
apps/mac/AIWorkspace/Sources/main.swift
Normal file
@@ -0,0 +1,599 @@
|
||||
import AppKit
|
||||
import Foundation
|
||||
import ServiceManagement
|
||||
import SwiftUI
|
||||
|
||||
private let workspaceRoot = URL(fileURLWithPath: "/Users/david/Developer/fidelity-ai-workspace", isDirectory: true)
|
||||
|
||||
struct ProfileConfig {
|
||||
let id: String
|
||||
let displayName: String
|
||||
let knowledgeDir: String
|
||||
|
||||
static func discoverDefault() -> ProfileConfig {
|
||||
let profilesRoot = workspaceRoot.appendingPathComponent("profiles", isDirectory: true)
|
||||
let candidates = (try? FileManager.default.contentsOfDirectory(at: profilesRoot, includingPropertiesForKeys: nil)) ?? []
|
||||
let configs = candidates.compactMap { directory -> ProfileConfig? in
|
||||
let configURL = directory.appendingPathComponent("workspace.json")
|
||||
guard let data = try? Data(contentsOf: configURL),
|
||||
let decoded = try? JSONDecoder().decode(ProfileWorkspaceConfig.self, from: data)
|
||||
else { return nil }
|
||||
return ProfileConfig(
|
||||
id: decoded.profile ?? directory.lastPathComponent,
|
||||
displayName: decoded.displayName ?? decoded.profile ?? directory.lastPathComponent,
|
||||
knowledgeDir: decoded.knowledgeDir ?? "workspaces/\(decoded.profile ?? directory.lastPathComponent)/project-knowledge"
|
||||
)
|
||||
}
|
||||
if let fidelity = configs.first(where: { $0.id == "fidelity" }) {
|
||||
return fidelity
|
||||
}
|
||||
if let first = configs.sorted(by: { $0.id < $1.id }).first {
|
||||
return first
|
||||
}
|
||||
return ProfileConfig(id: "fidelity", displayName: "Fidelity", knowledgeDir: "workspaces/fidelity/project-knowledge")
|
||||
}
|
||||
}
|
||||
|
||||
private struct ProfileWorkspaceConfig: Decodable {
|
||||
let profile: String?
|
||||
let displayName: String?
|
||||
let knowledgeDir: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case profile
|
||||
case displayName = "display_name"
|
||||
case knowledgeDir = "knowledge_dir"
|
||||
}
|
||||
}
|
||||
|
||||
@main
|
||||
struct AIWorkspaceApp: App {
|
||||
@StateObject private var model = ServiceStatusModel()
|
||||
|
||||
var body: some Scene {
|
||||
MenuBarExtra {
|
||||
ServiceMenuView(model: model)
|
||||
.task {
|
||||
await model.refresh()
|
||||
}
|
||||
} label: {
|
||||
Label("AI Workspace", systemImage: model.menuBarSymbol)
|
||||
}
|
||||
.menuBarExtraStyle(.window)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class ServiceStatusModel: ObservableObject {
|
||||
@Published private(set) var report: StatusReport?
|
||||
@Published private(set) var lastError: String?
|
||||
@Published private(set) var lanIP: String?
|
||||
@Published private(set) var loginItemStatus: SMAppService.Status = .notRegistered
|
||||
@Published private(set) var isRefreshing = false
|
||||
@Published private(set) var activeAction: String?
|
||||
|
||||
let profile: ProfileConfig
|
||||
|
||||
init() {
|
||||
self.profile = ProfileConfig.discoverDefault()
|
||||
}
|
||||
|
||||
var menuBarSymbol: String {
|
||||
guard let report else { return "circle.dashed" }
|
||||
if report.services.contains(where: { $0.status == "unhealthy" || ($0.enabled && $0.status == "stopped") }) {
|
||||
return "exclamationmark.triangle"
|
||||
}
|
||||
if report.services.contains(where: { $0.status == "running" }) {
|
||||
return "checkmark.circle"
|
||||
}
|
||||
return "circle"
|
||||
}
|
||||
|
||||
func refresh() async {
|
||||
isRefreshing = true
|
||||
defer { isRefreshing = false }
|
||||
do {
|
||||
let data = try await ServiceManager.run(["status", "--profile", profile.id, "--json"])
|
||||
report = try JSONDecoder().decode(StatusReport.self, from: data)
|
||||
lanIP = await NetworkInfo.primaryLANIP()
|
||||
loginItemStatus = SMAppService.mainApp.status
|
||||
lastError = nil
|
||||
} catch {
|
||||
lastError = String(describing: error)
|
||||
}
|
||||
}
|
||||
|
||||
var startAtLoginEnabled: Bool {
|
||||
loginItemStatus == .enabled
|
||||
}
|
||||
|
||||
var startAtLoginStatusText: String {
|
||||
switch loginItemStatus {
|
||||
case .enabled: "enabled"
|
||||
case .notRegistered: "off"
|
||||
case .notFound: "not found"
|
||||
case .requiresApproval: "requires approval"
|
||||
@unknown default: "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func setStartAtLogin(_ enabled: Bool) {
|
||||
do {
|
||||
if enabled {
|
||||
try SMAppService.mainApp.register()
|
||||
} else {
|
||||
try SMAppService.mainApp.unregister()
|
||||
}
|
||||
loginItemStatus = SMAppService.mainApp.status
|
||||
lastError = nil
|
||||
} catch {
|
||||
loginItemStatus = SMAppService.mainApp.status
|
||||
lastError = "Start at Login: \(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
|
||||
func startProfile() {
|
||||
runAction("Starting services…", ["start", "--profile", profile.id])
|
||||
}
|
||||
|
||||
func stopProfile() {
|
||||
runAction("Stopping services…", ["stop", "--profile", profile.id])
|
||||
}
|
||||
|
||||
func primaryServiceAction() {
|
||||
if allManagedServicesRunning {
|
||||
stopProfile()
|
||||
} else {
|
||||
startProfile()
|
||||
}
|
||||
}
|
||||
|
||||
func restartMCP() {
|
||||
runAction("Restarting MCP…", ["restart", "aiw-context-mcp", "--profile", profile.id])
|
||||
}
|
||||
|
||||
func runDoctor() {
|
||||
runAction("Running doctor…", ["doctor", "--profile", profile.id])
|
||||
}
|
||||
|
||||
func copyDoctorJSON() {
|
||||
Task {
|
||||
do {
|
||||
let data = try await ServiceManager.run(["doctor", "--profile", profile.id, "--json"])
|
||||
copyToPasteboard(String(data: data, encoding: .utf8) ?? "")
|
||||
} catch {
|
||||
lastError = String(describing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func copyPhotoInboxURL() {
|
||||
let host = lanIP ?? "127.0.0.1"
|
||||
copyToPasteboard("http://\(host):8787/upload")
|
||||
}
|
||||
|
||||
func copyRecentLogs() {
|
||||
Task {
|
||||
do {
|
||||
var chunks: [String] = []
|
||||
for service in report?.services ?? [] {
|
||||
let data = try await ServiceManager.run(["logs", service.name, "--profile", profile.id, "--lines", "30"])
|
||||
if let text = String(data: data, encoding: .utf8), !text.isEmpty {
|
||||
chunks.append(text)
|
||||
}
|
||||
}
|
||||
copyToPasteboard(chunks.joined(separator: "\n\n"))
|
||||
} catch {
|
||||
lastError = String(describing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func openMCPHealth() {
|
||||
if let url = URL(string: "http://127.0.0.1:8765/health") {
|
||||
NSWorkspace.shared.open(url)
|
||||
}
|
||||
}
|
||||
|
||||
func openLogsFolder() {
|
||||
NSWorkspace.shared.open(workspaceRoot.appendingPathComponent(".aiw/runtime/logs/\(profile.id)", isDirectory: true))
|
||||
}
|
||||
|
||||
func openProjectKnowledge() {
|
||||
NSWorkspace.shared.open(workspaceRoot.appendingPathComponent(profile.knowledgeDir, isDirectory: true))
|
||||
}
|
||||
|
||||
func openMattermost() {
|
||||
runAction("Launching Mattermost…", ["start", "mattermost-desktop", "--profile", profile.id])
|
||||
}
|
||||
|
||||
var allManagedServicesRunning: Bool {
|
||||
guard let services = report?.services else { return false }
|
||||
let managed = services.filter { $0.enabled && $0.kind != "app-launcher" }
|
||||
return !managed.isEmpty && managed.allSatisfy { $0.status == "running" || $0.status == "externally running" }
|
||||
}
|
||||
|
||||
var primaryActionTitle: String {
|
||||
allManagedServicesRunning ? "Stop Services" : "Start Services"
|
||||
}
|
||||
|
||||
var primaryActionSymbol: String {
|
||||
allManagedServicesRunning ? "stop.fill" : "play.fill"
|
||||
}
|
||||
|
||||
var isBusy: Bool {
|
||||
isRefreshing || activeAction != nil
|
||||
}
|
||||
|
||||
private func copyToPasteboard(_ value: String) {
|
||||
NSPasteboard.general.clearContents()
|
||||
NSPasteboard.general.setString(value, forType: .string)
|
||||
}
|
||||
|
||||
private func runAction(_ label: String, _ arguments: [String]) {
|
||||
Task {
|
||||
activeAction = label
|
||||
defer { activeAction = nil }
|
||||
do {
|
||||
_ = try await ServiceManager.run(arguments)
|
||||
await refresh()
|
||||
} catch {
|
||||
lastError = String(describing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ServiceMenuView: View {
|
||||
@ObservedObject var model: ServiceStatusModel
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
HStack(alignment: .firstTextBaseline) {
|
||||
VStack(alignment: .leading, spacing: 3) {
|
||||
Text("AI Workspace")
|
||||
.font(.title3.bold())
|
||||
Text("Profile: \(model.profile.displayName)")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
if model.isBusy {
|
||||
ProgressView()
|
||||
.controlSize(.small)
|
||||
}
|
||||
Button {
|
||||
Task { await model.refresh() }
|
||||
} label: {
|
||||
Image(systemName: "arrow.clockwise")
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.disabled(model.isBusy)
|
||||
.help("Refresh")
|
||||
}
|
||||
|
||||
if let activeAction = model.activeAction {
|
||||
Label(activeAction, systemImage: "hourglass")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
if let report = model.report {
|
||||
VStack(spacing: 8) {
|
||||
ForEach(report.services) { service in
|
||||
ServiceRow(service: service)
|
||||
}
|
||||
}
|
||||
} else if let error = model.lastError {
|
||||
Label("Status unavailable", systemImage: "exclamationmark.triangle")
|
||||
Text(error)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(3)
|
||||
} else {
|
||||
Label("Loading status...", systemImage: "hourglass")
|
||||
}
|
||||
|
||||
if let lanIP = model.lanIP {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "wifi")
|
||||
.foregroundStyle(.secondary)
|
||||
Text("Photo Inbox LAN")
|
||||
Spacer()
|
||||
Text("http://\(lanIP):8787/upload")
|
||||
.font(.caption.monospaced())
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Button(role: model.allManagedServicesRunning ? .destructive : nil, action: model.primaryServiceAction) {
|
||||
Label(model.primaryActionTitle, systemImage: model.primaryActionSymbol)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.controlSize(.large)
|
||||
.disabled(model.isBusy)
|
||||
|
||||
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 8) {
|
||||
ActionButton(title: "Restart MCP", systemImage: "arrow.triangle.2.circlepath", disabled: model.isBusy, action: model.restartMCP)
|
||||
ActionButton(title: "Mattermost via Proxy", systemImage: "message.badge", disabled: model.isBusy, action: model.openMattermost)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 8) {
|
||||
ActionButton(title: "Run Doctor", systemImage: "stethoscope", disabled: model.isBusy, action: model.runDoctor)
|
||||
ActionButton(title: "Copy Doctor JSON", systemImage: "doc.on.doc", disabled: model.isBusy, action: model.copyDoctorJSON)
|
||||
ActionButton(title: "Copy Photo URL", systemImage: "link", action: model.copyPhotoInboxURL)
|
||||
ActionButton(title: "Copy Logs", systemImage: "doc.text", disabled: model.isBusy, action: model.copyRecentLogs)
|
||||
ActionButton(title: "MCP Health", systemImage: "heart.text.square", action: model.openMCPHealth)
|
||||
ActionButton(title: "Logs Folder", systemImage: "folder", action: model.openLogsFolder)
|
||||
}
|
||||
|
||||
ActionButton(title: "Open Project Knowledge", systemImage: "books.vertical", action: model.openProjectKnowledge)
|
||||
|
||||
Divider()
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Toggle(isOn: Binding(
|
||||
get: { model.startAtLoginEnabled },
|
||||
set: { model.setStartAtLogin($0) }
|
||||
)) {
|
||||
Label("Start at Login", systemImage: "poweron")
|
||||
}
|
||||
.toggleStyle(.switch)
|
||||
|
||||
Text("Login item: \(model.startAtLoginStatusText)")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
Divider()
|
||||
HStack {
|
||||
if let error = model.lastError {
|
||||
Label(error, systemImage: "exclamationmark.triangle")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.orange)
|
||||
.lineLimit(2)
|
||||
}
|
||||
Spacer()
|
||||
Button("Quit") {
|
||||
NSApplication.shared.terminate(nil)
|
||||
}
|
||||
.keyboardShortcut("q")
|
||||
}
|
||||
}
|
||||
.padding(18)
|
||||
.frame(width: 430)
|
||||
}
|
||||
}
|
||||
|
||||
struct ActionButton: View {
|
||||
let title: String
|
||||
let systemImage: String
|
||||
var role: ButtonRole?
|
||||
var disabled = false
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(role: role, action: action) {
|
||||
Label(title, systemImage: systemImage)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.controlSize(.small)
|
||||
.disabled(disabled)
|
||||
}
|
||||
}
|
||||
|
||||
struct ServiceRow: View {
|
||||
let service: ServiceStatus
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 10) {
|
||||
Image(systemName: symbol)
|
||||
.foregroundStyle(color)
|
||||
.frame(width: 16, alignment: .center)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(service.displayName)
|
||||
.font(.body.weight(.medium))
|
||||
Text(service.detail)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Spacer(minLength: 12)
|
||||
StatusBadge(text: service.compactStatus, color: color)
|
||||
}
|
||||
.padding(.vertical, 7)
|
||||
.padding(.horizontal, 10)
|
||||
.background(.quaternary.opacity(0.6), in: RoundedRectangle(cornerRadius: 10, style: .continuous))
|
||||
.help(service.detail)
|
||||
}
|
||||
|
||||
private var symbol: String {
|
||||
switch service.status {
|
||||
case "running": "checkmark.circle"
|
||||
case "launcher": "arrow.up.forward.app"
|
||||
case "externally running": "link.circle"
|
||||
case "unhealthy": "exclamationmark.triangle"
|
||||
case "disabled": "minus.circle"
|
||||
default: "xmark.circle"
|
||||
}
|
||||
}
|
||||
|
||||
private var color: Color {
|
||||
switch service.status {
|
||||
case "running", "launcher", "externally running": .green
|
||||
case "unhealthy": .orange
|
||||
case "disabled": .secondary
|
||||
default: .red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StatusBadge: View {
|
||||
let text: String
|
||||
let color: Color
|
||||
|
||||
var body: some View {
|
||||
Text(text)
|
||||
.font(.caption.weight(.semibold))
|
||||
.foregroundStyle(color)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 4)
|
||||
.background(color.opacity(0.14), in: Capsule())
|
||||
}
|
||||
}
|
||||
|
||||
enum ServiceManager {
|
||||
static func run(_ arguments: [String]) async throws -> Data {
|
||||
try await Task.detached(priority: .userInitiated) {
|
||||
let process = Process()
|
||||
process.currentDirectoryURL = workspaceRoot
|
||||
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
|
||||
process.arguments = ["python3", "scripts/aiw/services.py"] + arguments
|
||||
var environment = ProcessInfo.processInfo.environment
|
||||
let guiSafePATH = "/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||
if let existingPATH = environment["PATH"], !existingPATH.isEmpty {
|
||||
environment["PATH"] = "\(guiSafePATH):\(existingPATH)"
|
||||
} else {
|
||||
environment["PATH"] = guiSafePATH
|
||||
}
|
||||
environment["AIW_WORKSPACE_ROOT"] = workspaceRoot.path
|
||||
process.environment = environment
|
||||
|
||||
let output = Pipe()
|
||||
let error = Pipe()
|
||||
process.standardOutput = output
|
||||
process.standardError = error
|
||||
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
|
||||
let data = output.fileHandleForReading.readDataToEndOfFile()
|
||||
let errorData = error.fileHandleForReading.readDataToEndOfFile()
|
||||
guard process.terminationStatus == 0 else {
|
||||
let message = String(data: errorData.isEmpty ? data : errorData, encoding: .utf8) ?? "service command failed"
|
||||
throw ServiceManagerError.commandFailed(message.trimmingCharacters(in: .whitespacesAndNewlines))
|
||||
}
|
||||
return data
|
||||
}.value
|
||||
}
|
||||
}
|
||||
|
||||
enum NetworkInfo {
|
||||
static func primaryLANIP() async -> String? {
|
||||
for interface in ["en0", "en1"] {
|
||||
if let value = try? await runIPConfig(interface), !value.isEmpty {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func runIPConfig(_ interface: String) async throws -> String {
|
||||
try await Task.detached(priority: .utility) {
|
||||
let process = Process()
|
||||
process.executableURL = URL(fileURLWithPath: "/usr/sbin/ipconfig")
|
||||
process.arguments = ["getifaddr", interface]
|
||||
let output = Pipe()
|
||||
process.standardOutput = output
|
||||
process.standardError = Pipe()
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
let data = output.fileHandleForReading.readDataToEndOfFile()
|
||||
guard process.terminationStatus == 0 else { return "" }
|
||||
return String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
}.value
|
||||
}
|
||||
}
|
||||
|
||||
enum ServiceManagerError: LocalizedError {
|
||||
case commandFailed(String)
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .commandFailed(let message): message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StatusReport: Decodable {
|
||||
let profile: String
|
||||
let workspace: String
|
||||
let runtime: String
|
||||
let services: [ServiceStatus]
|
||||
}
|
||||
|
||||
struct ServiceStatus: Decodable, Identifiable {
|
||||
var id: String { name }
|
||||
|
||||
let name: String
|
||||
let enabled: Bool
|
||||
let kind: String
|
||||
let status: String
|
||||
let pid: Int?
|
||||
let command: [String]
|
||||
let health: Health
|
||||
let state: [String: JSONValue]
|
||||
|
||||
var displayName: String {
|
||||
switch name {
|
||||
case "aiw-context-mcp": "Context MCP"
|
||||
case "mattermost-proxy": "Mattermost Proxy"
|
||||
case "mattermost-desktop": "Mattermost Desktop via Proxy"
|
||||
case "photo-inbox": "Photo Inbox"
|
||||
default: name
|
||||
}
|
||||
}
|
||||
|
||||
var detail: String {
|
||||
if name == "mattermost-desktop" {
|
||||
return "Launches Mattermost through local proxy 127.0.0.1:8080"
|
||||
}
|
||||
return health.detail
|
||||
}
|
||||
|
||||
var compactStatus: String {
|
||||
switch status {
|
||||
case "externally running": "external"
|
||||
default: status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Health: Decodable {
|
||||
let ok: Bool?
|
||||
let detail: String
|
||||
}
|
||||
|
||||
enum JSONValue: Decodable {
|
||||
case string(String)
|
||||
case number(Double)
|
||||
case bool(Bool)
|
||||
case object([String: JSONValue])
|
||||
case array([JSONValue])
|
||||
case null
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
if container.decodeNil() {
|
||||
self = .null
|
||||
} else if let value = try? container.decode(Bool.self) {
|
||||
self = .bool(value)
|
||||
} else if let value = try? container.decode(Double.self) {
|
||||
self = .number(value)
|
||||
} else if let value = try? container.decode(String.self) {
|
||||
self = .string(value)
|
||||
} else if let value = try? container.decode([String: JSONValue].self) {
|
||||
self = .object(value)
|
||||
} else {
|
||||
self = .array(try container.decode([JSONValue].self))
|
||||
}
|
||||
}
|
||||
}
|
||||
27
apps/mac/AIWorkspace/scripts/build-dmg.sh
Normal file
27
apps/mac/AIWorkspace/scripts/build-dmg.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
APP_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
APP_NAME="AIWorkspace"
|
||||
DIST_DIR="$APP_ROOT/dist"
|
||||
APP_BUNDLE="$DIST_DIR/$APP_NAME.app"
|
||||
DMG_STAGING="$DIST_DIR/dmg-staging"
|
||||
DMG_PATH="$DIST_DIR/$APP_NAME.dmg"
|
||||
|
||||
bash "$SCRIPT_DIR/package-app.sh"
|
||||
|
||||
rm -rf "$DMG_STAGING" "$DMG_PATH"
|
||||
mkdir -p "$DMG_STAGING"
|
||||
cp -R "$APP_BUNDLE" "$DMG_STAGING/$APP_NAME.app"
|
||||
ln -s /Applications "$DMG_STAGING/Applications"
|
||||
|
||||
hdiutil create \
|
||||
-volname "AI Workspace" \
|
||||
-srcfolder "$DMG_STAGING" \
|
||||
-ov \
|
||||
-format UDZO \
|
||||
"$DMG_PATH"
|
||||
|
||||
rm -rf "$DMG_STAGING"
|
||||
echo "Built $DMG_PATH"
|
||||
40
apps/mac/AIWorkspace/scripts/install-start-at-login.sh
Normal file
40
apps/mac/AIWorkspace/scripts/install-start-at-login.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
APP_PATH="${APP_PATH:-$HOME/Applications/AIWorkspace.app}"
|
||||
PLIST_PATH="$HOME/Library/LaunchAgents/com.aiworkspace.menu.plist"
|
||||
|
||||
if [[ ! -d "$APP_PATH" ]]; then
|
||||
echo "App not found: $APP_PATH" >&2
|
||||
echo "Run apps/mac/AIWorkspace/scripts/package-app.sh --install first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/Library/LaunchAgents"
|
||||
|
||||
cat > "$PLIST_PATH" <<PLIST
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.aiworkspace.menu</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/bin/open</string>
|
||||
<string>-a</string>
|
||||
<string>$APP_PATH</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>$HOME/Library/Logs/AIWorkspace-menu.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>$HOME/Library/Logs/AIWorkspace-menu.err.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
PLIST
|
||||
|
||||
launchctl unload "$PLIST_PATH" >/dev/null 2>&1 || true
|
||||
launchctl load "$PLIST_PATH"
|
||||
echo "Installed and loaded LaunchAgent: $PLIST_PATH"
|
||||
35
apps/mac/AIWorkspace/scripts/install.sh
Normal file
35
apps/mac/AIWorkspace/scripts/install.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
INSTALL_LOGIN_ITEM=0
|
||||
OPEN_APP=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--start-at-login)
|
||||
INSTALL_LOGIN_ITEM=1
|
||||
;;
|
||||
--open)
|
||||
OPEN_APP=1
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $arg" >&2
|
||||
echo "Usage: $0 [--start-at-login] [--open]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
bash "$SCRIPT_DIR/package-app.sh" --install
|
||||
|
||||
if [[ "$INSTALL_LOGIN_ITEM" == "1" ]]; then
|
||||
bash "$SCRIPT_DIR/install-start-at-login.sh"
|
||||
fi
|
||||
|
||||
if [[ "$OPEN_APP" == "1" ]]; then
|
||||
open "$HOME/Applications/AIWorkspace.app"
|
||||
fi
|
||||
|
||||
echo "AI Workspace app install complete."
|
||||
64
apps/mac/AIWorkspace/scripts/package-app.sh
Normal file
64
apps/mac/AIWorkspace/scripts/package-app.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
APP_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
WORKSPACE_ROOT="$(cd "$APP_ROOT/../../.." && pwd)"
|
||||
|
||||
CONFIGURATION="${CONFIGURATION:-release}"
|
||||
APP_NAME="AIWorkspace"
|
||||
BUILD_DIR="$APP_ROOT/.build/$CONFIGURATION"
|
||||
OUTPUT_DIR="$APP_ROOT/dist"
|
||||
APP_BUNDLE="$OUTPUT_DIR/$APP_NAME.app"
|
||||
INSTALL_DIR="${INSTALL_DIR:-$HOME/Applications}"
|
||||
|
||||
INSTALL=0
|
||||
if [[ "${1:-}" == "--install" ]]; then
|
||||
INSTALL=1
|
||||
fi
|
||||
|
||||
swift build --package-path "$APP_ROOT" -c "$CONFIGURATION"
|
||||
|
||||
rm -rf "$APP_BUNDLE"
|
||||
mkdir -p "$APP_BUNDLE/Contents/MacOS" "$APP_BUNDLE/Contents/Resources"
|
||||
cp "$BUILD_DIR/$APP_NAME" "$APP_BUNDLE/Contents/MacOS/$APP_NAME"
|
||||
|
||||
cat > "$APP_BUNDLE/Contents/Info.plist" <<PLIST
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$APP_NAME</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.aiworkspace.menu</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>AI Workspace</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Local AI Workspace utility.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
PLIST
|
||||
|
||||
echo "Built $APP_BUNDLE"
|
||||
|
||||
if [[ "$INSTALL" == "1" ]]; then
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
rm -rf "$INSTALL_DIR/$APP_NAME.app"
|
||||
cp -R "$APP_BUNDLE" "$INSTALL_DIR/$APP_NAME.app"
|
||||
echo "Installed $INSTALL_DIR/$APP_NAME.app"
|
||||
fi
|
||||
7
apps/mac/AIWorkspace/scripts/uninstall-start-at-login.sh
Normal file
7
apps/mac/AIWorkspace/scripts/uninstall-start-at-login.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PLIST_PATH="$HOME/Library/LaunchAgents/com.aiworkspace.menu.plist"
|
||||
launchctl unload "$PLIST_PATH" >/dev/null 2>&1 || true
|
||||
rm -f "$PLIST_PATH"
|
||||
echo "Removed LaunchAgent: $PLIST_PATH"
|
||||
@@ -51,7 +51,7 @@ See `core/memory/operational-memory.md` for the detailed rules.
|
||||
|
||||
Integrations extract evidence. They do not decide what becomes memory.
|
||||
|
||||
- live communication connectors write recent evidence to `ai/inbox/`
|
||||
- live communication connectors write recent evidence to `workspaces/<profile>/inbox/`
|
||||
- historical archive connectors write selected evidence to `scripts/<source>/generated/`
|
||||
- the agent promotes only high-confidence, project-relevant facts into memory
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Expected behavior:
|
||||
|
||||
- fetch recent messages from configured channels or conversations
|
||||
- support a forced refresh for "latest message" prompts
|
||||
- write the latest evidence to `ai/inbox/`
|
||||
- write the latest evidence to `workspaces/<profile>/inbox/`
|
||||
- write status separately from project memory
|
||||
- fail safely without updating logs, state, or context
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Obsidian is the current human-facing implementation, but the workspace should no
|
||||
|
||||
### Canonical Memory
|
||||
|
||||
The source of truth is plain Markdown under `project-knowledge/`.
|
||||
The source of truth is plain Markdown under `workspaces/<profile>/project-knowledge/`.
|
||||
|
||||
Agents should edit canonical notes directly when precision matters because direct edits produce auditable diffs.
|
||||
|
||||
@@ -31,16 +31,16 @@ Use `scripts/memory/memory.sh` for project-knowledge operations:
|
||||
|
||||
The current adapter is Obsidian CLI through `scripts/obsidian/cli.sh`.
|
||||
|
||||
If Obsidian CLI is unavailable or fails, `scripts/memory/memory.sh` falls back to direct Markdown operations unless `AIW_MEMORY_BACKEND=obsidian` is explicitly set.
|
||||
If Obsidian CLI is unavailable or fails, `scripts/memory/memory.sh` uses direct Markdown operations unless `AIW_MEMORY_BACKEND=obsidian` is explicitly set.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
- `AIW_PROJECT_KNOWLEDGE_DIR`: canonical project knowledge directory. Defaults to `<workspace-root>/project-knowledge`.
|
||||
- `AIW_MEMORY_VAULT_DIR`: transition alias for the canonical project knowledge directory.
|
||||
- `AIW_PROJECT_PROFILE`: selected profile. Defaults to `fidelity` in this workspace.
|
||||
- `profiles/<profile>/workspace.json`: canonical source for `knowledge_dir`, `inbox_dir`, and `index_dir`.
|
||||
- `AIW_PROJECT_KNOWLEDGE_DIR`: optional local override for the canonical project knowledge directory.
|
||||
- `AIW_MEMORY_BACKEND`: `auto`, `files`, or `obsidian`. Defaults to `auto`.
|
||||
- `AIW_OBSIDIAN_VAULT_DIR`: Obsidian-specific transition alias, still supported by the adapter.
|
||||
- `AIW_OBSIDIAN_VAULT_NAME`: Obsidian URI vault name override for URI wrappers.
|
||||
|
||||
Backend meanings:
|
||||
@@ -55,15 +55,15 @@ Backend meanings:
|
||||
|
||||
The memory interface owns type-to-folder routing:
|
||||
|
||||
- `daily` -> `project-knowledge/06-daily/`
|
||||
- `work-item` -> `project-knowledge/02-work-items/`
|
||||
- `person` -> `project-knowledge/04-people/`
|
||||
- `decision` -> `project-knowledge/05-decisions/`
|
||||
- `system` -> `project-knowledge/03-context/systems/`
|
||||
- `workstream` -> `project-knowledge/03-context/workstreams/`
|
||||
- `meeting-note` -> `project-knowledge/06-daily/`
|
||||
- `daily` -> `workspaces/<profile>/project-knowledge/06-daily/`
|
||||
- `work-item` -> `workspaces/<profile>/project-knowledge/02-work-items/`
|
||||
- `person` -> `workspaces/<profile>/project-knowledge/04-people/`
|
||||
- `decision` -> `workspaces/<profile>/project-knowledge/05-decisions/`
|
||||
- `system` -> `workspaces/<profile>/project-knowledge/03-context/systems/`
|
||||
- `workstream` -> `workspaces/<profile>/project-knowledge/03-context/workstreams/`
|
||||
- `meeting-note` -> `workspaces/<profile>/project-knowledge/06-daily/`
|
||||
|
||||
Templates live in `project-knowledge/09-templates/`.
|
||||
Templates live in `workspaces/<profile>/project-knowledge/09-templates/`.
|
||||
|
||||
This gives agents an automatic destination for new notes without coupling the rule to Obsidian.
|
||||
|
||||
@@ -77,7 +77,7 @@ This gives agents an automatic destination for new notes without coupling the ru
|
||||
- Edit Markdown directly for precise memory curation, corrections, and content updates.
|
||||
- Do not treat Obsidian CLI failure as project context.
|
||||
- Do not require Obsidian to be running for core workspace operation.
|
||||
- Keep raw evidence outside `project-knowledge/`; promote only curated memory.
|
||||
- Keep raw evidence outside `workspaces/<profile>/project-knowledge/`; promote only curated memory.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ Obsidian should not become a second memory store.
|
||||
|
||||
## Recommended Vault
|
||||
|
||||
Open the `project-knowledge/` folder as the Obsidian vault:
|
||||
Open the `workspaces/<profile>/project-knowledge/` folder as the Obsidian vault:
|
||||
|
||||
```text
|
||||
<workspace-root>/project-knowledge/
|
||||
<workspace-root>/workspaces/<profile>/project-knowledge/
|
||||
```
|
||||
|
||||
This keeps one source of truth:
|
||||
@@ -30,14 +30,14 @@ This keeps one source of truth:
|
||||
|
||||
Canonical project knowledge lives in:
|
||||
|
||||
- `project-knowledge/00-start/`
|
||||
- `project-knowledge/01-current/`
|
||||
- `project-knowledge/02-work-items/`
|
||||
- `project-knowledge/03-context/`
|
||||
- `project-knowledge/04-people/`
|
||||
- `project-knowledge/05-decisions/`
|
||||
- `project-knowledge/06-daily/`
|
||||
- `project-knowledge/07-maps/`
|
||||
- `workspaces/<profile>/project-knowledge/00-start/`
|
||||
- `workspaces/<profile>/project-knowledge/01-current/`
|
||||
- `workspaces/<profile>/project-knowledge/02-work-items/`
|
||||
- `workspaces/<profile>/project-knowledge/03-context/`
|
||||
- `workspaces/<profile>/project-knowledge/04-people/`
|
||||
- `workspaces/<profile>/project-knowledge/05-decisions/`
|
||||
- `workspaces/<profile>/project-knowledge/06-daily/`
|
||||
- `workspaces/<profile>/project-knowledge/07-maps/`
|
||||
|
||||
Technical runtime remains outside the vault:
|
||||
|
||||
@@ -46,11 +46,11 @@ Technical runtime remains outside the vault:
|
||||
- `scripts/`
|
||||
- `core/`
|
||||
- `profiles/`
|
||||
- `ai/inbox/`
|
||||
- `workspaces/<profile>/inbox/`
|
||||
- `scripts/*/generated/`
|
||||
- archives and local virtual environments
|
||||
|
||||
Communication evidence may exist under `ai/inbox/` or connector `generated/` folders, but promoted memory belongs in `project-knowledge/`.
|
||||
Communication evidence may exist under `workspaces/<profile>/inbox/` or connector `generated/` folders, but promoted memory belongs in the profile's project knowledge vault.
|
||||
|
||||
---
|
||||
|
||||
@@ -58,25 +58,25 @@ Communication evidence may exist under `ai/inbox/` or connector `generated/` fol
|
||||
|
||||
Version portable Obsidian configuration only when it improves the workspace for every clone:
|
||||
|
||||
- `project-knowledge/.obsidian/app.json`
|
||||
- `project-knowledge/.obsidian/core-plugins.json`
|
||||
- `project-knowledge/.obsidian/graph.json`
|
||||
- `project-knowledge/.obsidian/appearance.json`
|
||||
- `project-knowledge/.obsidian/daily-notes.json`
|
||||
- `project-knowledge/.obsidian/templates.json`
|
||||
- `project-knowledge/.obsidian/bookmarks.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/app.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/core-plugins.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/graph.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/appearance.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/daily-notes.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/templates.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/bookmarks.json`
|
||||
|
||||
Do not version local runtime state:
|
||||
|
||||
- `project-knowledge/.obsidian/workspace*.json`
|
||||
- `project-knowledge/.obsidian/workspace-mobile*.json`
|
||||
- `project-knowledge/.obsidian/plugins/`
|
||||
- `project-knowledge/.obsidian/snippets/`
|
||||
- `project-knowledge/.obsidian/cache/`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/workspace*.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/workspace-mobile*.json`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/plugins/`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/snippets/`
|
||||
- `workspaces/<profile>/project-knowledge/.obsidian/cache/`
|
||||
|
||||
Recommended graph and search exclusions:
|
||||
|
||||
- `ai/inbox/`
|
||||
- `workspaces/<profile>/inbox/`
|
||||
- `archives/`
|
||||
- `scripts/**/generated/`
|
||||
- `scripts/**/.venv/`
|
||||
@@ -107,7 +107,7 @@ The agent should not treat Obsidian runtime layout changes as project context.
|
||||
|
||||
If Obsidian metadata or properties are added, use them selectively for high-value notes such as work items, decisions, and index pages. Do not mass-convert existing files just to add metadata.
|
||||
|
||||
Use map notes under `project-knowledge/07-maps/` as graph hubs. This keeps the graph navigable without forcing every file into Obsidian-specific wiki-link syntax.
|
||||
Use map notes under `workspaces/<profile>/project-knowledge/07-maps/` as graph hubs. This keeps the graph navigable without forcing every file into Obsidian-specific wiki-link syntax.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -80,14 +80,14 @@ Default path patterns:
|
||||
```text
|
||||
.opencode/commands/*.md
|
||||
.opencode/agents/*.md
|
||||
.opencode/skills/*/SKILL.md
|
||||
.agents/skills/*/SKILL.md
|
||||
prompts/*.md
|
||||
agent-memory/**/*.md
|
||||
core/**/*.md
|
||||
scripts/**/*.md
|
||||
```
|
||||
|
||||
Raw evidence stays outside `project-knowledge/`; promoted memory is written to `project-knowledge/`.
|
||||
Raw evidence stays outside `workspaces/<profile>/project-knowledge/`; promoted memory is written to `workspaces/<profile>/project-knowledge/`.
|
||||
|
||||
---
|
||||
|
||||
@@ -178,7 +178,7 @@ The agent should also identify recurring quality gaps proactively. If an answer
|
||||
|
||||
For technical topics, recurring gaps often belong in:
|
||||
|
||||
- domain-specific guidance under `project-knowledge/03-context/`
|
||||
- reusable skills under `.opencode/skills/`
|
||||
- domain-specific guidance under `workspaces/<profile>/project-knowledge/03-context/`
|
||||
- reusable skills under `.agents/skills/`
|
||||
- agent behavior rules under `.opencode/agents/`, `AGENTS.md`, or `agent-memory/`
|
||||
- source anchors for official/current documentation
|
||||
|
||||
@@ -48,7 +48,7 @@ project-knowledge/09-templates/
|
||||
|
||||
Keep project-specific facts out of `core/`.
|
||||
|
||||
Treat `project-knowledge/` as canonical project memory. Keep connector inboxes and generated evidence outside the project knowledge vault.
|
||||
Treat `workspaces/<profile>/project-knowledge/` as canonical project memory. Keep connector inboxes and generated evidence outside the project knowledge vault.
|
||||
|
||||
---
|
||||
|
||||
@@ -102,15 +102,15 @@ Before using the workspace for real work:
|
||||
|
||||
## 6. Obsidian Vault
|
||||
|
||||
Open `project-knowledge/` as the Obsidian vault.
|
||||
Open `workspaces/<profile>/project-knowledge/` as the Obsidian vault.
|
||||
|
||||
Use `scripts/memory/` as the project-agnostic memory interface. Obsidian is the default visual and CLI-backed adapter, but profile logic should not depend on Obsidian.
|
||||
|
||||
Recommended rules:
|
||||
|
||||
- keep `project-knowledge/` as the clean canonical project knowledge
|
||||
- keep runtime evidence, scripts, profiles, and generated files outside `project-knowledge/`
|
||||
- version only portable `project-knowledge/.obsidian` configuration
|
||||
- keep `workspaces/<profile>/project-knowledge/` as the clean canonical project knowledge
|
||||
- keep runtime evidence, scripts, profiles, and generated files outside `workspaces/<profile>/project-knowledge/`
|
||||
- version only portable `workspaces/<profile>/project-knowledge/.obsidian` configuration
|
||||
- ignore local Obsidian workspace state and plugin runtime files
|
||||
- create or update map notes under `project-knowledge/07-maps/` for human navigation
|
||||
- create Bases under `project-knowledge/08-bases/` using simple `type` properties
|
||||
- create or update map notes under `workspaces/<profile>/project-knowledge/07-maps/` for human navigation
|
||||
- create Bases under `workspaces/<profile>/project-knowledge/08-bases/` using simple `type` properties
|
||||
|
||||
102
core/services/local-rag-index.md
Normal file
102
core/services/local-rag-index.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
type: service-design
|
||||
status: active
|
||||
updated: 2026-05-21
|
||||
tags:
|
||||
- ai-workspace
|
||||
- rag
|
||||
- index
|
||||
---
|
||||
|
||||
# Local RAG Index
|
||||
|
||||
## Goal
|
||||
|
||||
Add retrieval over canonical workspace memory without replacing the human-readable profile project knowledge vault.
|
||||
|
||||
The local index is derived and disposable. If the index disagrees with Markdown, the Markdown wins.
|
||||
|
||||
---
|
||||
|
||||
## Current Implementation
|
||||
|
||||
The first implementation is dependency-free and lexical:
|
||||
|
||||
```text
|
||||
scripts/aiw/indexer.py
|
||||
```
|
||||
|
||||
It reads:
|
||||
|
||||
```text
|
||||
workspaces/<profile>/project-knowledge/**/*.md
|
||||
```
|
||||
|
||||
and writes:
|
||||
|
||||
```text
|
||||
.aiw/indexes/<profile>/project-knowledge.jsonl
|
||||
.aiw/indexes/<profile>/manifest.json
|
||||
```
|
||||
|
||||
It skips:
|
||||
|
||||
```text
|
||||
workspaces/<profile>/project-knowledge/09-templates/
|
||||
```
|
||||
|
||||
so Obsidian templates do not appear as real memory.
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
Build the index:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py build --profile fidelity
|
||||
```
|
||||
|
||||
Check index status:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py status --profile fidelity
|
||||
```
|
||||
|
||||
Search the index:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py search "dismissal lifecycle" --profile fidelity
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Exposure
|
||||
|
||||
`aiw-context-mcp` exposes:
|
||||
|
||||
```text
|
||||
memory_hybrid_search
|
||||
```
|
||||
|
||||
Current behavior:
|
||||
|
||||
- searches the derived local index when it exists
|
||||
- returns cited paths, headings, snippets, scores, hashes, and mtimes
|
||||
- falls back to live Markdown search when no index exists
|
||||
- remains read-only
|
||||
|
||||
---
|
||||
|
||||
## Future Upgrade Path
|
||||
|
||||
This layer can later add:
|
||||
|
||||
- full-text ranking
|
||||
- embeddings
|
||||
- Qdrant or Chroma as a local vector store
|
||||
- hybrid lexical + semantic search
|
||||
- reranking
|
||||
- Mattermost evidence indexing with strict source filters
|
||||
|
||||
Do not make the vector store canonical. It should remain rebuildable from Markdown and selected evidence.
|
||||
67
core/services/macos-installation-model.md
Normal file
67
core/services/macos-installation-model.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# macOS Installation Model
|
||||
|
||||
## How production macOS utilities commonly do it
|
||||
|
||||
Apps such as Cloudflare WARP, VPN clients, Docker Desktop, and device agents usually separate:
|
||||
|
||||
- a user-facing app or menu bar app;
|
||||
- one or more background services;
|
||||
- launchd configuration for automatic startup;
|
||||
- privileged helpers only when system-level networking, drivers, packet filtering, or protected paths are required.
|
||||
|
||||
Common mechanisms:
|
||||
|
||||
- `LaunchAgent` in `~/Library/LaunchAgents` for per-user background/login startup.
|
||||
- `LaunchDaemon` in `/Library/LaunchDaemons` for root/system services.
|
||||
- `SMAppService` / login items for sandboxed or App Store-aligned apps.
|
||||
- Privileged helper tools via `SMJobBless` when admin-level installation is required.
|
||||
- `.pkg` installers when the install needs privileged locations, daemons, receipts, or managed deployment.
|
||||
|
||||
## Recommended AI Workspace approach
|
||||
|
||||
Use a staged model:
|
||||
|
||||
1. **Current local developer install**
|
||||
- Build a real `.app` bundle into `apps/mac/AIWorkspace/dist/`.
|
||||
- Install to `~/Applications/AIWorkspace.app`.
|
||||
- Install a per-user `LaunchAgent` for start at login.
|
||||
|
||||
2. **Production-ready local install**
|
||||
- Keep using a per-user LaunchAgent because services are local user tools and do not require root.
|
||||
- Add a one-step installer script that builds, installs, optionally enables start at login, and opens the app.
|
||||
- Avoid privileged helpers until a real system-level requirement appears.
|
||||
|
||||
3. **Future polished distribution**
|
||||
- Create a signed/notarized `.app` distributed in a `.dmg` with an Applications shortcut, or a `.pkg` only if privileged installation becomes necessary.
|
||||
- Use `SMAppService` for login item management from inside the app so the user can toggle Start at Login in the UI instead of running `launchctl` scripts manually.
|
||||
- Add a small daemon API if the UI needs richer lifecycle control than shelling out to `services.py`.
|
||||
|
||||
## Desired user-grade install flow
|
||||
|
||||
For a Cloudflare/Docker-like local experience, the target should be:
|
||||
|
||||
1. User opens `AIWorkspace.dmg`.
|
||||
2. User drags `AIWorkspace.app` to `/Applications` or `~/Applications`.
|
||||
3. User launches the app.
|
||||
4. App shows service status and a **Start at Login** toggle.
|
||||
5. App registers/unregisters itself as a login item using `SMAppService`.
|
||||
6. App starts/stops workspace services through the service manager.
|
||||
|
||||
The existing shell scripts remain useful for development and bootstrap, but should not be the primary end-user experience once the app handles login item registration itself.
|
||||
|
||||
## Current implementation state
|
||||
|
||||
- `AIWorkspace.app` can be packaged from `apps/mac/AIWorkspace/scripts/package-app.sh`.
|
||||
- `AIWorkspace.dmg` can be built from `apps/mac/AIWorkspace/scripts/build-dmg.sh`.
|
||||
- The app UI includes a **Start at Login** toggle backed by `SMAppService.mainApp`.
|
||||
- LaunchAgent scripts remain as development fallbacks, not the preferred user path.
|
||||
|
||||
## Why not LaunchDaemon now
|
||||
|
||||
The current services are user-context services:
|
||||
|
||||
- Mattermost Desktop launching must happen in the user's GUI session.
|
||||
- Photo Inbox writes to user-owned folders and uses clipboard/notifications.
|
||||
- The MCP and proxy bind localhost ports and do not require root.
|
||||
|
||||
A root daemon would add unnecessary permission prompts and security risk. A per-user LaunchAgent is the correct production-leaning step for this stage.
|
||||
81
core/services/menu-bar-app-design.md
Normal file
81
core/services/menu-bar-app-design.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# AI Workspace Menu Bar App Design
|
||||
|
||||
## Goal
|
||||
|
||||
Provide a small native macOS control surface for the AI Workspace Service Manager.
|
||||
|
||||
The app should not reimplement service logic. It should call the service manager/daemon API or CLI and display status, actions, and diagnostics.
|
||||
|
||||
## Recommended Shape
|
||||
|
||||
- SwiftUI `MenuBarExtra` app.
|
||||
- Local-only, no cloud dependency.
|
||||
- Start at login optional through `LaunchAgent` later.
|
||||
- Read-only status by default; explicit user actions for start/stop/restart.
|
||||
- The UI should not own MCP profile selection. AI clients pass profiles to MCP tools/resources; the menu bar app is only a local operations surface.
|
||||
|
||||
## Initial UI
|
||||
|
||||
```text
|
||||
AI Workspace ▾
|
||||
Profile: Fidelity
|
||||
|
||||
Services
|
||||
✓ Context MCP Running
|
||||
✓ Mattermost Proxy Running
|
||||
✓ Mattermost Desktop Launched
|
||||
✓ Photo Inbox Running
|
||||
|
||||
Actions
|
||||
Start Fidelity
|
||||
Stop Fidelity
|
||||
Restart Context MCP
|
||||
Open Mattermost
|
||||
Open Photo Inbox Folder
|
||||
Copy Photo Inbox Upload URL
|
||||
Copy Recent Logs
|
||||
Open Project Knowledge
|
||||
Open Logs
|
||||
|
||||
Diagnostics
|
||||
Run Doctor
|
||||
Copy Doctor JSON
|
||||
Show Recent Errors
|
||||
|
||||
Settings
|
||||
Start at Login
|
||||
Open Config Folder
|
||||
```
|
||||
|
||||
## Backend Contract
|
||||
|
||||
The first version can shell out to:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/services.py status --profile fidelity
|
||||
python3 scripts/aiw/services.py status --profile fidelity --json
|
||||
python3 scripts/aiw/services.py doctor --profile fidelity --json
|
||||
python3 scripts/aiw/services.py start --profile fidelity
|
||||
python3 scripts/aiw/services.py stop --profile fidelity
|
||||
python3 scripts/aiw/services.py restart aiw-context-mcp --profile fidelity
|
||||
```
|
||||
|
||||
Use `status --json` for frequent UI refreshes and `doctor --json` for explicit diagnostics. Longer term, prefer a small local daemon HTTP/Unix-socket API so the UI does not parse terminal text.
|
||||
|
||||
## Production-Ready Rules
|
||||
|
||||
- Do not store secrets in the app bundle.
|
||||
- Do not expose services beyond localhost unless explicitly configured.
|
||||
- Show whether a process is managed or externally running.
|
||||
- Surface missing dependencies from doctor checks.
|
||||
- Never let the app promote project memory automatically.
|
||||
- Keep capture services and context MCP separate; the app only orchestrates lifecycle.
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
1. CLI-backed SwiftUI menu bar app using `status --json` for live status and `doctor --json` for diagnostics.
|
||||
2. Add profile selector and service action buttons.
|
||||
3. Add LaunchAgent support for start at login.
|
||||
4. Replace shell parsing with a daemon API if daily use proves stable.
|
||||
|
||||
See `multi-profile-runtime-model.md` for how this should evolve when multiple profiles run in parallel.
|
||||
49
core/services/multi-profile-runtime-model.md
Normal file
49
core/services/multi-profile-runtime-model.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Multi-Profile Runtime Model
|
||||
|
||||
## Principle
|
||||
|
||||
Profiles are selected by clients and services, not by the menu bar UI.
|
||||
|
||||
The menu bar app is a local operations surface for the current operator machine. It can monitor the local services that are enabled now, but it should not become the source of truth for which project an AI client is allowed to query.
|
||||
|
||||
## Desired Model
|
||||
|
||||
- MCP clients choose the profile at call time, for example `{"profile":"fidelity"}`.
|
||||
- Multiple profiles may run in parallel when their service ports and inbox paths do not conflict.
|
||||
- Capture services can be profile-specific or shared:
|
||||
- shared service: one Mattermost mirror with profile-scoped query filters;
|
||||
- profile-specific service: separate mirror/output path/port per profile.
|
||||
- The MCP query layer should remain profile-aware and read from profile manifests/config.
|
||||
- The menu bar app should show local runtime health, not force a single global profile selection.
|
||||
|
||||
## Current Fidelity Setup
|
||||
|
||||
The first menu bar version targets the Fidelity service set because that is the active local workflow. This does not prevent MCP clients from querying other profiles when those profiles have canonical memory or context-source config.
|
||||
|
||||
## Parallel Profile Requirements
|
||||
|
||||
Before running another profile in parallel, define unique values for any conflicting service:
|
||||
|
||||
- MCP HTTP port if using separate MCP instances.
|
||||
- Mattermost proxy listen port if using separate proxy instances.
|
||||
- Photo Inbox port if using separate upload receivers.
|
||||
- Mirror/inbox output directory.
|
||||
- Profile-specific context channels.
|
||||
|
||||
Example future split:
|
||||
|
||||
```text
|
||||
fidelity:
|
||||
aiw-context-mcp: 127.0.0.1:8765
|
||||
mattermost-proxy: 127.0.0.1:8080
|
||||
photo-inbox: 0.0.0.0:8787
|
||||
|
||||
it-support:
|
||||
aiw-context-mcp: same shared MCP, profile argument selects context
|
||||
mattermost-proxy: 127.0.0.1:8081 if a separate capture session is needed
|
||||
photo-inbox: 0.0.0.0:8788 if a separate receiver is needed
|
||||
```
|
||||
|
||||
## Menu Bar Direction
|
||||
|
||||
The menu bar app should evolve toward showing service groups or all running profiles, but not a manual profile selector for MCP query behavior. Profile selection belongs in the MCP tool/resource arguments and client prompts.
|
||||
28
core/services/service-manager.md
Normal file
28
core/services/service-manager.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# AI Workspace Service Manager
|
||||
|
||||
## Principle
|
||||
|
||||
The AI Workspace should unify local service lifecycle without collapsing service responsibilities.
|
||||
|
||||
- Service manager: starts, stops, checks, and logs local services.
|
||||
- Context MCP: exposes bounded read-only context to AI clients.
|
||||
- Capture services: produce local evidence such as Mattermost mirror records or photo inbox files.
|
||||
- Canonical memory remains under `workspaces/<profile>/project-knowledge/` and is updated by the agent using memory rules.
|
||||
|
||||
## Service Types
|
||||
|
||||
- `process`: long-running local command with PID, logs, and optional health check.
|
||||
- `app-launcher`: one-shot command that opens an application or helper.
|
||||
- `mcp`: a process service that exposes an MCP-compatible context interface.
|
||||
|
||||
## Profile Manifests
|
||||
|
||||
Project-specific services should be declared under `profiles/<profile>/services.json`.
|
||||
|
||||
Manifests should avoid project facts in reusable code. Profile-specific channel names, paths, ports, and enabled services belong in the profile manifest or local `.env` files.
|
||||
|
||||
## Responsibility Boundaries
|
||||
|
||||
Do not put capture lifecycle inside the context MCP. The MCP should query local evidence produced by capture services. The service manager may start both the MCP and capture services as one profile-level operation.
|
||||
|
||||
This keeps the same core usable for Fidelity, IT support, or another project with different communication sources.
|
||||
31
docs/README.md
Normal file
31
docs/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# AIWorkspace Documentation
|
||||
|
||||
AIWorkspace is a local context platform for developers. It connects project evidence, canonical human-readable memory, local services, and AI clients without making any single AI tool the source of truth.
|
||||
|
||||
This documentation describes the target production architecture: reusable AIWorkspace core separated from project-specific AI context packs.
|
||||
|
||||
## Start Here
|
||||
|
||||
- [Concepts: Overview](concepts/overview.md)
|
||||
- [Concepts: Workspace vs Context Pack](concepts/workspace-vs-context-pack.md)
|
||||
- [Architecture: Storage Model](architecture/storage-model.md)
|
||||
- [Guide: Quick Start](guides/quick-start.md)
|
||||
- [Reference: Project Manifest](reference/project-manifest.md)
|
||||
|
||||
## Documentation Map
|
||||
|
||||
```text
|
||||
docs/
|
||||
concepts/ Product concepts and user-facing mental model
|
||||
architecture/ System boundaries, storage, services, and security
|
||||
guides/ Task-oriented setup and usage guides
|
||||
reference/ File formats, CLI, manifests, and environment variables
|
||||
```
|
||||
|
||||
## Core Principle
|
||||
|
||||
```text
|
||||
AIWorkspace provides context. Project context packs own project memory.
|
||||
```
|
||||
|
||||
The core product should remain reusable and shareable. Project-specific facts, connector settings, people, channels, raw evidence, and prompts belong in separate context packs.
|
||||
68
docs/architecture.md
Normal file
68
docs/architecture.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Architecture
|
||||
|
||||
AI Workspace is organized around explicit boundaries: profile configuration, raw evidence, canonical memory, derived retrieval, local services, and AI client adapters.
|
||||
|
||||
## System Flow
|
||||
|
||||
```text
|
||||
Communication / screenshots / archives / manual notes
|
||||
↓
|
||||
Raw inbox evidence
|
||||
↓
|
||||
Agent or human curation
|
||||
↓
|
||||
Canonical Markdown project knowledge
|
||||
↓
|
||||
Derived local index
|
||||
↓
|
||||
Read-only MCP context server
|
||||
↓
|
||||
AI clients and agent workflows
|
||||
```
|
||||
|
||||
## Responsibility Boundaries
|
||||
|
||||
| Layer | Responsibility | Canonical? |
|
||||
|---|---|---|
|
||||
| `core/` | Reusable architecture and operating model | yes, for workspace design |
|
||||
| `profiles/<profile>/` | Project-specific configuration and assumptions | yes, for profile config |
|
||||
| `workspaces/<profile>/project-knowledge/` | Human-readable project memory for the active profile | yes, for project facts |
|
||||
| `workspaces/<profile>/inbox/` | Raw evidence captured from connectors | no |
|
||||
| `.aiw/indexes/` | Rebuildable search indexes | no |
|
||||
| `.aiw/runtime/` | PID files, logs, local service state | no |
|
||||
| `scripts/aiw/` | Profile-aware service/index utilities | code source |
|
||||
| `scripts/mcp/` | MCP servers exposing local context | code source |
|
||||
| `apps/` | Local UI surfaces such as the macOS menu bar app | code source |
|
||||
|
||||
## Current Repository Shape
|
||||
|
||||
Profile-owned data lives under `workspaces/<profile>/`. Reusable code must resolve paths from `profiles/<profile>/workspace.json` rather than hardcoding profile-specific locations.
|
||||
|
||||
Current data layout:
|
||||
|
||||
```text
|
||||
profiles/<profile>/workspace.json # where profile data lives
|
||||
workspaces/<profile>/project-knowledge/
|
||||
workspaces/<profile>/inbox/
|
||||
.aiw/indexes/<profile>/
|
||||
```
|
||||
|
||||
## Design Principles
|
||||
|
||||
- Keep the smallest useful context loaded by default.
|
||||
- Prefer just-in-time retrieval over dumping the entire workspace into prompts.
|
||||
- Keep human-readable Markdown as the project source of truth.
|
||||
- Keep raw evidence outside canonical memory until explicitly promoted.
|
||||
- Keep profile-specific facts out of `core/` and generic scripts.
|
||||
- Make local services observable through a single service manager.
|
||||
- Treat cloud memory systems as optional, not authoritative.
|
||||
|
||||
## Why This Shape
|
||||
|
||||
Current AI workflow guidance emphasizes context engineering: the model should receive the smallest high-signal context needed for the task. This workspace supports that by combining:
|
||||
|
||||
- structured Markdown memory for durable facts;
|
||||
- raw evidence stores for auditability;
|
||||
- local indexes for retrieval;
|
||||
- MCP tools/resources for AI clients;
|
||||
- profile-specific boundaries for reuse across projects.
|
||||
98
docs/architecture/storage-model.md
Normal file
98
docs/architecture/storage-model.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Storage Model
|
||||
|
||||
AIWorkspace uses different storage locations for different kinds of data. This keeps the product shareable, the project context auditable, and local runtime state disposable.
|
||||
|
||||
## Storage Responsibilities
|
||||
|
||||
| Data | Target Location | Git? | Notes |
|
||||
|---|---|---:|---|
|
||||
| Core product code | `~/Developer/ai-workspace` | yes | Shared reusable product. |
|
||||
| Project manifest | `<context-pack>/aiw.project.json` | yes | Project identity and relative paths. |
|
||||
| Canonical memory | `<context-pack>/knowledge/` | usually yes | Human-readable Markdown. |
|
||||
| Raw evidence | `<context-pack>/inbox/` | usually no/private | Captured messages, screenshots, exports. |
|
||||
| Connector config | `<context-pack>/connectors/` | depends | Safe config can be tracked; secrets must not be tracked. |
|
||||
| Project prompts/agents | `<context-pack>/prompts/`, `<context-pack>/agents/` | depends | Track if safe for the team. |
|
||||
| User registry | `~/Library/Application Support/AIWorkspace/` | no | Local project registration and preferences. |
|
||||
| Logs | `~/Library/Logs/AIWorkspace/` | no | Service and app logs. |
|
||||
| Caches/indexes | `~/Library/Caches/AIWorkspace/` | no | Rebuildable derived data. |
|
||||
| Runtime/PIDs | `~/Library/Application Support/AIWorkspace/runtime/` | no | Local service state. |
|
||||
|
||||
## Canonical Memory
|
||||
|
||||
Canonical memory is the durable project source of truth for humans and AI.
|
||||
|
||||
Target structure:
|
||||
|
||||
```text
|
||||
knowledge/
|
||||
current/
|
||||
work-items/
|
||||
systems/
|
||||
workstreams/
|
||||
people/
|
||||
decisions/
|
||||
daily/
|
||||
templates/
|
||||
```
|
||||
|
||||
Canonical memory should be:
|
||||
|
||||
- readable without AIWorkspace;
|
||||
- reviewable in Git when shared;
|
||||
- explicit about uncertainty;
|
||||
- updated by humans or agents using small auditable changes.
|
||||
|
||||
## Raw Evidence
|
||||
|
||||
Raw evidence is input, not truth.
|
||||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
inbox/
|
||||
mattermost/
|
||||
slack/
|
||||
photos/
|
||||
documents/
|
||||
screenshots/
|
||||
```
|
||||
|
||||
Raw evidence should not be promoted automatically into durable memory unless a workflow explicitly classifies it as high-confidence and project-relevant.
|
||||
|
||||
## Derived Indexes
|
||||
|
||||
Indexes are rebuildable.
|
||||
|
||||
They should live outside the context pack by default:
|
||||
|
||||
```text
|
||||
~/Library/Caches/AIWorkspace/indexes/<project>/
|
||||
```
|
||||
|
||||
This prevents large derived artifacts from polluting project memory repositories.
|
||||
|
||||
## Runtime State
|
||||
|
||||
Service logs, PID files, and health snapshots should be local machine state.
|
||||
|
||||
Target locations:
|
||||
|
||||
```text
|
||||
~/Library/Logs/AIWorkspace/
|
||||
~/Library/Application Support/AIWorkspace/runtime/
|
||||
```
|
||||
|
||||
Runtime state should not be used as project memory.
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets should not be stored in context packs unless they are encrypted and explicitly supported.
|
||||
|
||||
Preferred approaches:
|
||||
|
||||
- macOS Keychain references;
|
||||
- ignored local `.env` files;
|
||||
- environment variables;
|
||||
- enterprise-approved credential stores.
|
||||
|
||||
Documentation, manifests, and generated configs should refer to secret names, not secret values.
|
||||
65
docs/concepts/overview.md
Normal file
65
docs/concepts/overview.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# AIWorkspace Overview
|
||||
|
||||
AIWorkspace helps developers give AI tools the right project context at the right time.
|
||||
|
||||
It is designed for teams and individuals who use multiple AI clients—OpenCode, GitHub Copilot, Claude Code, Cursor, VS Code, or others—but do not want project knowledge scattered across chat histories, prompt files, and product repositories.
|
||||
|
||||
## What AIWorkspace Does
|
||||
|
||||
AIWorkspace provides a local platform to:
|
||||
|
||||
- connect communication and evidence sources;
|
||||
- keep canonical project memory in human-readable Markdown;
|
||||
- index that memory for fast retrieval;
|
||||
- expose bounded context through MCP;
|
||||
- generate AI client configuration when needed;
|
||||
- run local services such as context servers, capture proxies, and inbox receivers;
|
||||
- keep raw evidence separate from curated project knowledge.
|
||||
|
||||
## What AIWorkspace Is Not
|
||||
|
||||
AIWorkspace is not:
|
||||
|
||||
- a replacement for a product repository;
|
||||
- a replacement for project documentation;
|
||||
- a cloud memory system;
|
||||
- a single-agent framework that forces one AI workflow;
|
||||
- a place to store secrets in Git;
|
||||
- a dumping ground for raw chat exports.
|
||||
|
||||
## Target User Flow
|
||||
|
||||
```text
|
||||
Developer installs AIWorkspace
|
||||
↓
|
||||
Registers or creates a project context pack
|
||||
↓
|
||||
Connects evidence sources and local repos
|
||||
↓
|
||||
AIWorkspace captures evidence and maintains indexes
|
||||
↓
|
||||
AI clients ask AIWorkspace MCP for project context
|
||||
↓
|
||||
Humans and agents update canonical project memory
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Concept | Meaning |
|
||||
|---|---|
|
||||
| AIWorkspace Core | The reusable app, CLI, scripts, MCP server, connectors, templates, and documentation. |
|
||||
| User Registry | Local app configuration that remembers registered projects, paths, preferences, and service state. |
|
||||
| Project Context Pack | A project-specific folder or repo containing canonical memory, connector config, prompts, and optional raw evidence. |
|
||||
| Canonical Memory | Human-readable Markdown that represents current durable project knowledge. |
|
||||
| Raw Evidence | Captured messages, screenshots, exports, logs, or documents before curation. |
|
||||
| AI Client | Any tool that consumes context: OpenCode, Copilot, Claude Code, Cursor, VS Code, etc. |
|
||||
|
||||
## Design Goal
|
||||
|
||||
AIWorkspace should be plug-and-play for a new developer:
|
||||
|
||||
1. install the app and CLI;
|
||||
2. register an existing context pack or create a new one;
|
||||
3. connect sources such as Mattermost, Slack, tickets, email, calendar, or local folders;
|
||||
4. let AIWorkspace detect repositories and services;
|
||||
5. use any AI client with project-aware context through MCP.
|
||||
127
docs/concepts/workspace-vs-context-pack.md
Normal file
127
docs/concepts/workspace-vs-context-pack.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Workspace vs Context Pack
|
||||
|
||||
AIWorkspace separates the installed product, user-local settings, and project memory.
|
||||
|
||||
This distinction keeps the system simple, shareable, and safe for unrelated projects such as `client-mobile` and `it-support`.
|
||||
|
||||
## Three-Layer Model
|
||||
|
||||
```text
|
||||
AIWorkspace Core
|
||||
reusable installed product
|
||||
|
||||
User/App Registry
|
||||
local machine settings and registered context packs
|
||||
|
||||
Project Context Packs
|
||||
one isolated context package per project, client, or workstream
|
||||
```
|
||||
|
||||
## AIWorkspace Core
|
||||
|
||||
The core is the reusable product. It can be shared with a team.
|
||||
|
||||
Typical location during development:
|
||||
|
||||
```text
|
||||
~/Developer/ai-workspace
|
||||
```
|
||||
|
||||
It contains:
|
||||
|
||||
```text
|
||||
apps/
|
||||
scripts/
|
||||
connectors/
|
||||
templates/
|
||||
docs/
|
||||
examples/
|
||||
```
|
||||
|
||||
It should not contain real project memory, captured messages, customer names, ticket details, or private prompts.
|
||||
|
||||
## User/App Registry
|
||||
|
||||
The registry is local to one developer machine. It records which context packs are available and which project is active.
|
||||
|
||||
On macOS, the target location is:
|
||||
|
||||
```text
|
||||
~/Library/Application Support/AIWorkspace/
|
||||
```
|
||||
|
||||
Example registry:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "aiworkspace.projects.v1",
|
||||
"default_project": "client-mobile",
|
||||
"projects": [
|
||||
{
|
||||
"id": "client-mobile",
|
||||
"context_path": "/Users/david/Developer/client-mobile-ai-context"
|
||||
},
|
||||
{
|
||||
"id": "it-support",
|
||||
"context_path": "/Users/david/Developer/it-support-ai-context"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The registry is not intended for Git.
|
||||
|
||||
## Project Context Pack
|
||||
|
||||
A context pack is the portable project-specific unit. It may be a private repo, a team-shared repo, or a local folder.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
client-mobile-ai-context/
|
||||
aiw.project.json
|
||||
knowledge/
|
||||
inbox/
|
||||
connectors/
|
||||
agents/
|
||||
prompts/
|
||||
```
|
||||
|
||||
Each context pack owns its own:
|
||||
|
||||
- canonical memory;
|
||||
- raw evidence;
|
||||
- connector definitions;
|
||||
- people/channel/system maps;
|
||||
- prompts and agent instructions specific to that project.
|
||||
|
||||
## Why Not Store Everything In One Workspace Repo?
|
||||
|
||||
One developer can work on unrelated projects. A single monolithic workspace can accidentally mix:
|
||||
|
||||
- channels from different organizations;
|
||||
- people maps from unrelated clients;
|
||||
- raw evidence with different privacy rules;
|
||||
- prompts that only make sense for one domain;
|
||||
- AI behavior learned from one project but harmful in another.
|
||||
|
||||
Context packs prevent this by making project boundaries explicit.
|
||||
|
||||
## Optional Product Repository Binding
|
||||
|
||||
Product repositories should stay clean by default. If useful, a repo can contain a small optional binding file:
|
||||
|
||||
```text
|
||||
.aiworkspace.json
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": "client-mobile",
|
||||
"context_path": "/Users/david/Developer/client-mobile-ai-context"
|
||||
}
|
||||
```
|
||||
|
||||
This file should point to context. It should not contain memory, secrets, or raw evidence.
|
||||
63
docs/getting-started.md
Normal file
63
docs/getting-started.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Getting Started
|
||||
|
||||
AI Workspace is a local, profile-based context system for AI-assisted work. It keeps project memory, raw evidence, local services, and AI client integrations organized without making any single AI tool the source of truth.
|
||||
|
||||
## Core Idea
|
||||
|
||||
Use the workspace as a companion repo beside your real project or client work:
|
||||
|
||||
```text
|
||||
implementation repo / corporate tools / chat evidence
|
||||
↓
|
||||
AI Workspace inbox and memory curation
|
||||
↓
|
||||
human-readable project knowledge
|
||||
↓
|
||||
local index and MCP context server
|
||||
↓
|
||||
OpenCode / Claude Code / Copilot / other AI clients
|
||||
```
|
||||
|
||||
## First Run
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/services.py doctor --profile fidelity
|
||||
python3 scripts/aiw/services.py status --profile fidelity
|
||||
python3 scripts/aiw/indexer.py build --profile fidelity
|
||||
```
|
||||
|
||||
The `fidelity` profile is the first real project profile in this repo. New projects should follow the same shape but keep their own profile configuration and project memory isolated.
|
||||
|
||||
Create a new isolated profile with:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/profile.py create my-project --display-name "My Project"
|
||||
python3 scripts/aiw/profile.py doctor --profile my-project
|
||||
```
|
||||
|
||||
## Daily Use
|
||||
|
||||
1. Open the project knowledge vault in Obsidian or your Markdown editor.
|
||||
2. Start only the local services needed for the profile.
|
||||
3. Capture raw evidence into the profile inbox.
|
||||
4. Promote useful, verified facts into canonical Markdown.
|
||||
5. Let AI clients query context through MCP or direct file reads.
|
||||
|
||||
## Key Rules
|
||||
|
||||
- Canonical project memory is Markdown, not chat history or vector storage.
|
||||
- Inboxes contain evidence, not promoted memory.
|
||||
- Indexes are derived and rebuildable.
|
||||
- MCP is read-only by default.
|
||||
- Secrets belong in ignored local `.env` files.
|
||||
|
||||
## Next Reading
|
||||
|
||||
- [Architecture](architecture.md)
|
||||
- [Profiles](profiles.md)
|
||||
- [Memory Model](memory-model.md)
|
||||
- [MCP](mcp.md)
|
||||
- [Services](services.md)
|
||||
- [Security and Privacy](security-and-privacy.md)
|
||||
121
docs/guides/quick-start.md
Normal file
121
docs/guides/quick-start.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Quick Start
|
||||
|
||||
This guide describes the target production flow for a new developer using AIWorkspace.
|
||||
|
||||
The current repository still contains an active project-specific implementation. During refactor, these commands may be implemented incrementally.
|
||||
|
||||
## 1. Install AIWorkspace
|
||||
|
||||
Install the app, CLI, and local services from the reusable core repo:
|
||||
|
||||
```bash
|
||||
git clone <team-ai-workspace-repo> ~/Developer/ai-workspace
|
||||
cd ~/Developer/ai-workspace
|
||||
```
|
||||
|
||||
The target CLI entry point is:
|
||||
|
||||
```bash
|
||||
aiw
|
||||
```
|
||||
|
||||
During development, commands may still be run through Python scripts.
|
||||
|
||||
## 2. Register Or Create A Project Context Pack
|
||||
|
||||
Register an existing context pack:
|
||||
|
||||
```bash
|
||||
aiw project register ~/Developer/client-mobile-ai-context
|
||||
```
|
||||
|
||||
Or create a new one:
|
||||
|
||||
```bash
|
||||
aiw project create it-support --display-name "IT Support" --path ~/Developer/it-support-ai-context
|
||||
```
|
||||
|
||||
The context pack contains project memory and project-specific connector configuration.
|
||||
|
||||
## 3. Connect Evidence Sources
|
||||
|
||||
Add only the connectors this project needs:
|
||||
|
||||
```bash
|
||||
aiw connector add mattermost --project client-mobile
|
||||
aiw connector add photos --project client-mobile
|
||||
```
|
||||
|
||||
For another project, the connector set may be completely different:
|
||||
|
||||
```bash
|
||||
aiw connector add tickets --project it-support
|
||||
aiw connector add calendar --project it-support
|
||||
```
|
||||
|
||||
## 4. Detect Local Repositories
|
||||
|
||||
AIWorkspace should help detect local repos and associate them with projects:
|
||||
|
||||
```bash
|
||||
aiw repo scan ~/Developer --project it-support
|
||||
```
|
||||
|
||||
For projects whose source code lives on another machine, the context pack should say so explicitly in `aiw.project.json`.
|
||||
|
||||
## 5. Start Context Services
|
||||
|
||||
Start services for the active project:
|
||||
|
||||
```bash
|
||||
aiw services start --project client-mobile
|
||||
aiw services status --project client-mobile
|
||||
```
|
||||
|
||||
The service manager should start only capabilities configured for that project.
|
||||
|
||||
## 6. Configure AI Clients
|
||||
|
||||
Generate AI client integration files on demand:
|
||||
|
||||
```bash
|
||||
aiw agent configure opencode --project client-mobile
|
||||
aiw agent configure copilot --project client-mobile
|
||||
aiw mcp config --client vscode
|
||||
```
|
||||
|
||||
The preferred integration path is MCP, so AI clients can request current context without copying memory into product repositories.
|
||||
|
||||
## 7. Use AIWorkspace From Any AI Tool
|
||||
|
||||
The AI client should call MCP with a project id:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": "client-mobile"
|
||||
}
|
||||
```
|
||||
|
||||
Example tool calls:
|
||||
|
||||
```text
|
||||
project_current_context(project="client-mobile")
|
||||
project_search_memory(project="it-support", query="printer onboarding")
|
||||
communication_latest(project="client-mobile")
|
||||
```
|
||||
|
||||
## 8. Keep Canonical Memory Clean
|
||||
|
||||
Project memory lives in the context pack:
|
||||
|
||||
```text
|
||||
<context-pack>/knowledge/
|
||||
```
|
||||
|
||||
Raw evidence lives separately:
|
||||
|
||||
```text
|
||||
<context-pack>/inbox/
|
||||
```
|
||||
|
||||
Do not treat raw captures, indexes, logs, or AI chat history as canonical memory.
|
||||
67
docs/local-rag-index.md
Normal file
67
docs/local-rag-index.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Local RAG Index
|
||||
|
||||
The local RAG index is the first retrieval layer over canonical Markdown memory.
|
||||
|
||||
## Purpose
|
||||
|
||||
It helps AI clients quickly find relevant snippets without loading the whole project knowledge vault into context.
|
||||
|
||||
```text
|
||||
project-knowledge/ Markdown
|
||||
↓
|
||||
scripts/aiw/indexer.py
|
||||
↓
|
||||
.aiw/indexes/<profile>/project-knowledge.jsonl
|
||||
↓
|
||||
MCP tool: memory_hybrid_search
|
||||
```
|
||||
|
||||
## Current Implementation
|
||||
|
||||
The current indexer is dependency-free and lexical. It is intentionally simple so it can run on a new machine without a vector database.
|
||||
|
||||
Build:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py build --profile fidelity
|
||||
```
|
||||
|
||||
Status:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py status --profile fidelity
|
||||
```
|
||||
|
||||
Search:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/indexer.py search "dismissal lifecycle" --profile fidelity
|
||||
```
|
||||
|
||||
## What It Stores
|
||||
|
||||
- source path;
|
||||
- heading;
|
||||
- text chunk;
|
||||
- mtime;
|
||||
- content hash;
|
||||
- chunk id.
|
||||
|
||||
## What It Does Not Do
|
||||
|
||||
- It does not replace Markdown.
|
||||
- It does not write project facts.
|
||||
- It does not index templates as real notes.
|
||||
- It does not send data to a cloud service.
|
||||
|
||||
## Future Options
|
||||
|
||||
Future phases may add:
|
||||
|
||||
- better full-text ranking;
|
||||
- semantic embeddings;
|
||||
- Qdrant or Chroma as optional local vector stores;
|
||||
- hybrid lexical + semantic search;
|
||||
- index status in the menu bar app.
|
||||
|
||||
Keep this as a derived layer. The project knowledge vault remains canonical.
|
||||
73
docs/mcp.md
Normal file
73
docs/mcp.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# MCP Integration
|
||||
|
||||
The Model Context Protocol (MCP) is the workspace's standard interface for exposing local context to AI clients.
|
||||
|
||||
## Role In AI Workspace
|
||||
|
||||
`aiw-context-mcp` is a read-only context server. It exposes bounded profile context through MCP tools and resources.
|
||||
|
||||
It should not:
|
||||
|
||||
- capture communication traffic;
|
||||
- send messages;
|
||||
- write canonical memory;
|
||||
- promote facts automatically;
|
||||
- expose secrets or raw credentials.
|
||||
|
||||
## MCP Concepts
|
||||
|
||||
MCP uses a host/client/server model:
|
||||
|
||||
- **Host**: the AI app, such as OpenCode, Claude Code, VS Code, Copilot, or another client.
|
||||
- **Client**: the connection the host opens to a server.
|
||||
- **Server**: a local or remote program that exposes context.
|
||||
|
||||
Servers expose primitives such as:
|
||||
|
||||
- **Tools**: callable functions.
|
||||
- **Resources**: readable context objects.
|
||||
- **Prompts**: reusable prompt templates.
|
||||
|
||||
AI Workspace currently focuses on tools and resources.
|
||||
|
||||
## Current Tools
|
||||
|
||||
Examples:
|
||||
|
||||
- `context_profiles`
|
||||
- `project_current_context`
|
||||
- `project_search_memory`
|
||||
- `memory_hybrid_search`
|
||||
- `communication_latest`
|
||||
- `communication_date_context`
|
||||
- `communication_standup_context`
|
||||
- `photos_latest`
|
||||
|
||||
## Current Resources
|
||||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
aiw://profiles/fidelity/current-work
|
||||
aiw://profiles/fidelity/work-items
|
||||
aiw://profiles/fidelity/mattermost/latest
|
||||
aiw://profiles/fidelity/photos/latest
|
||||
```
|
||||
|
||||
## Security Posture
|
||||
|
||||
MCP tools can be model-controlled in many clients, so this workspace defaults to read-only context tools. If write tools are added later, they should require clear user intent, narrow scope, and audit-friendly outputs.
|
||||
|
||||
## Start The MCP Server
|
||||
|
||||
HTTP transport:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/services.py start aiw-context-mcp --profile fidelity
|
||||
```
|
||||
|
||||
stdio transport:
|
||||
|
||||
```bash
|
||||
python3 scripts/mcp/aiw-context-mcp/server.py --transport stdio
|
||||
```
|
||||
69
docs/memory-model.md
Normal file
69
docs/memory-model.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Memory Model
|
||||
|
||||
AI Workspace separates memory by purpose so that human-readable knowledge, raw evidence, agent behavior, and derived indexes do not collapse into one opaque store.
|
||||
|
||||
## Memory Layers
|
||||
|
||||
| Layer | Purpose | Examples | Canonical? |
|
||||
|---|---|---|---|
|
||||
| Canonical project memory | Durable project facts for humans and AI | current work, work items, people, decisions, daily notes | yes |
|
||||
| Raw evidence | Captured data before curation | Mattermost mirror, photos, archives | no |
|
||||
| Agent operating memory | Rules for agent behavior and workflows | promotion rules, communication style, verification rules | yes for agent behavior |
|
||||
| Derived index | Fast retrieval over canonical memory | `.aiw/indexes/<profile>/` | no |
|
||||
| External agent memory | Optional cross-agent recall | mem9, tool auto-memory | no for project truth |
|
||||
|
||||
## Canonical Markdown
|
||||
|
||||
The project knowledge vault should be readable without any AI tool:
|
||||
|
||||
```text
|
||||
project-knowledge/
|
||||
00-start/
|
||||
01-current/
|
||||
02-work-items/
|
||||
03-context/
|
||||
04-people/
|
||||
05-decisions/
|
||||
06-daily/
|
||||
07-maps/
|
||||
08-bases/
|
||||
09-templates/
|
||||
```
|
||||
|
||||
For future multi-profile setups, this same structure should live under a profile-specific workspace path.
|
||||
|
||||
## Evidence Promotion
|
||||
|
||||
Connectors write evidence. They do not decide what becomes memory.
|
||||
|
||||
Promotion flow:
|
||||
|
||||
```text
|
||||
inbox evidence → verified fact → smallest correct Markdown file
|
||||
```
|
||||
|
||||
Do not promote:
|
||||
|
||||
- secrets;
|
||||
- sync status;
|
||||
- generic chatter;
|
||||
- unverified guesses;
|
||||
- raw transcripts without curation.
|
||||
|
||||
## Local Index
|
||||
|
||||
The local RAG index is derived from canonical Markdown. It helps AI clients find relevant snippets quickly, but it is not the source of truth.
|
||||
|
||||
If index output conflicts with Markdown, Markdown wins.
|
||||
|
||||
## mem9 And Similar Memory Systems
|
||||
|
||||
mem9 can be useful as an optional cross-agent recall layer for preferences, reusable workflow habits, and non-sensitive operational memory. It should not replace the project knowledge vault.
|
||||
|
||||
Recommended stance:
|
||||
|
||||
```text
|
||||
project-knowledge/ wins over mem9, vector stores, and chat memory.
|
||||
```
|
||||
|
||||
For sensitive or corporate projects, avoid cloud memory ingestion unless the data policy is explicit and approved.
|
||||
99
docs/profiles.md
Normal file
99
docs/profiles.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Profiles
|
||||
|
||||
Profiles make the workspace reusable across projects, clients, or personal workflows.
|
||||
|
||||
Each profile should describe what the project is, where its memory lives, which communication sources matter, which local services are enabled, and how AI clients should access context.
|
||||
|
||||
## Current Profile Layout
|
||||
|
||||
```text
|
||||
profiles/
|
||||
fidelity/
|
||||
profile.md
|
||||
services.json
|
||||
context-sources.json
|
||||
example/
|
||||
profile.md
|
||||
```
|
||||
|
||||
## Recommended Future Layout
|
||||
|
||||
```text
|
||||
profiles/<profile>/
|
||||
profile.md # human-readable project profile
|
||||
workspace.json # profile paths and defaults
|
||||
services.json # local services for this profile
|
||||
context-sources.json # communication/source filters
|
||||
|
||||
workspaces/<profile>/
|
||||
project-knowledge/ # canonical Markdown vault
|
||||
inbox/ # raw evidence for this profile
|
||||
```
|
||||
|
||||
## Profile Files
|
||||
|
||||
### `profile.md`
|
||||
|
||||
Human-readable summary for agents and developers:
|
||||
|
||||
- project name;
|
||||
- workspace role;
|
||||
- communication sources;
|
||||
- work-item system;
|
||||
- stakeholders or roles;
|
||||
- important domain themes;
|
||||
- enabled workflows or skills.
|
||||
|
||||
### `workspace.json`
|
||||
|
||||
Profile path configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"profile": "example",
|
||||
"display_name": "Example Project",
|
||||
"knowledge_dir": "workspaces/example/project-knowledge",
|
||||
"inbox_dir": "workspaces/example/inbox",
|
||||
"index_dir": ".aiw/indexes/example"
|
||||
}
|
||||
```
|
||||
|
||||
Reusable scripts should resolve these paths through `scripts/aiw/profile.py`.
|
||||
|
||||
### `services.json`
|
||||
|
||||
Profile-specific local service manifest for `scripts/aiw/services.py`.
|
||||
|
||||
Examples:
|
||||
|
||||
- context MCP;
|
||||
- communication proxy/mirror;
|
||||
- photo inbox;
|
||||
- future indexer or dashboard services.
|
||||
|
||||
### `context-sources.json`
|
||||
|
||||
Source filters for profile-bounded reads. For example, a Mattermost profile can define which channels count as high-signal context.
|
||||
|
||||
## Adding A New Project
|
||||
|
||||
1. Create the isolated profile and workspace:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/profile.py create my-project --display-name "My Project"
|
||||
```
|
||||
|
||||
2. Define services only for integrations the project actually uses.
|
||||
3. Put connector secrets in ignored `.env` files.
|
||||
4. Validate the layout:
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/profile.py doctor --profile my-project
|
||||
```
|
||||
|
||||
5. Build the local index.
|
||||
6. Connect AI clients through the MCP server.
|
||||
|
||||
## Migration Rule
|
||||
|
||||
Reusable code should accept a `--profile` argument and resolve paths through profile configuration. Avoid adding hardcoded references to Fidelity, channel names, ticket prefixes, or company-specific folders in generic scripts.
|
||||
125
docs/reference/project-manifest.md
Normal file
125
docs/reference/project-manifest.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Project Manifest Reference
|
||||
|
||||
Each project context pack is described by an `aiw.project.json` file at the root of the context pack.
|
||||
|
||||
The manifest defines project identity, storage paths, connectors, code locations, and AI client preferences. Paths are relative to the context pack unless explicitly absolute.
|
||||
|
||||
## Minimal Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "aiworkspace.project.v1",
|
||||
"id": "my-project",
|
||||
"display_name": "My Project",
|
||||
"knowledge_dir": "knowledge",
|
||||
"inbox_dir": "inbox"
|
||||
}
|
||||
```
|
||||
|
||||
## Full Example
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "aiworkspace.project.v1",
|
||||
"id": "client-mobile",
|
||||
"display_name": "Client Mobile",
|
||||
"description": "Project context pack for a mobile application team.",
|
||||
"knowledge_dir": "knowledge",
|
||||
"inbox_dir": "inbox",
|
||||
"connectors_dir": "connectors",
|
||||
"prompts_dir": "prompts",
|
||||
"agents_dir": "agents",
|
||||
"connectors": {
|
||||
"mattermost": {
|
||||
"enabled": true,
|
||||
"config": "connectors/mattermost.json"
|
||||
},
|
||||
"photos": {
|
||||
"enabled": true,
|
||||
"config": "connectors/photos.json"
|
||||
}
|
||||
},
|
||||
"code_locations": [
|
||||
{
|
||||
"name": "Development machine",
|
||||
"availability": "remote-machine"
|
||||
}
|
||||
],
|
||||
"ai_clients": {
|
||||
"opencode": {
|
||||
"enabled": true
|
||||
},
|
||||
"copilot": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---:|---|
|
||||
| `schema` | yes | Manifest schema version. Current target: `aiworkspace.project.v1`. |
|
||||
| `id` | yes | Stable lowercase project id used by CLI and MCP. |
|
||||
| `display_name` | yes | Human-friendly project name. |
|
||||
| `description` | no | Short project description. |
|
||||
| `knowledge_dir` | yes | Canonical Markdown memory directory. |
|
||||
| `inbox_dir` | yes | Raw evidence directory. |
|
||||
| `connectors_dir` | no | Directory for connector configs. Defaults to `connectors`. |
|
||||
| `prompts_dir` | no | Directory for project prompts. Defaults to `prompts`. |
|
||||
| `agents_dir` | no | Directory for project agent config. Defaults to `agents`. |
|
||||
| `connectors` | no | Connector registry for this project. |
|
||||
| `code_locations` | no | Local or remote code locations associated with this project. |
|
||||
| `ai_clients` | no | AI client integration preferences. |
|
||||
|
||||
## Code Locations
|
||||
|
||||
Code may be local, remote, or unavailable on the current machine.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "iOS App",
|
||||
"path": "/Users/dev/Developer/app-ios",
|
||||
"role": "consumer-app",
|
||||
"availability": "local"
|
||||
}
|
||||
```
|
||||
|
||||
Supported target availability values:
|
||||
|
||||
- `local`
|
||||
- `remote-machine`
|
||||
- `not-configured`
|
||||
- `unknown`
|
||||
|
||||
## Connector Configs
|
||||
|
||||
Connector definitions should describe source behavior without storing secrets.
|
||||
|
||||
Example `connectors/mattermost.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "aiworkspace.connector.mattermost.v1",
|
||||
"enabled": true,
|
||||
"context_channels": [
|
||||
"team-standup",
|
||||
"team-code-review"
|
||||
],
|
||||
"secret_refs": {
|
||||
"session": "keychain:aiworkspace/mattermost/session"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Validation Rules
|
||||
|
||||
A production-ready manifest validator should check:
|
||||
|
||||
- required fields exist;
|
||||
- project id is stable and path-safe;
|
||||
- configured directories exist or can be created;
|
||||
- connector config files exist when enabled;
|
||||
- secrets are referenced, not embedded;
|
||||
- code locations are explicit about local vs remote availability.
|
||||
63
docs/security-and-privacy.md
Normal file
63
docs/security-and-privacy.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Security And Privacy
|
||||
|
||||
AI Workspace is designed for local-first, auditable context management. Treat it as a companion workspace that may contain sensitive project metadata and communication evidence.
|
||||
|
||||
## Rules
|
||||
|
||||
- Do not commit secrets, tokens, cookies, API keys, headers, or session IDs.
|
||||
- Keep connector credentials in ignored `.env` files.
|
||||
- Keep raw evidence outside canonical project memory until curated.
|
||||
- Keep MCP read-only unless a write tool has explicit safety rules.
|
||||
- Treat generated indexes as local artifacts because they may contain snippets from project notes.
|
||||
- Prefer local services for corporate or confidential projects.
|
||||
|
||||
## Ignored Local State
|
||||
|
||||
Examples of local-only data:
|
||||
|
||||
```text
|
||||
.aiw/runtime/
|
||||
.aiw/indexes/
|
||||
workspaces/*/inbox/mattermost-mirror/
|
||||
scripts/*/.env
|
||||
```
|
||||
|
||||
## Cloud Memory Systems
|
||||
|
||||
Tools such as mem9 or managed vector stores can be useful, but they introduce a data boundary.
|
||||
|
||||
Before enabling them for a project, decide:
|
||||
|
||||
- what data may be stored;
|
||||
- whether cloud storage is allowed;
|
||||
- whether self-hosting is required;
|
||||
- who can inspect/delete memories;
|
||||
- what happens when cloud memory conflicts with Markdown.
|
||||
|
||||
Default recommendation:
|
||||
|
||||
```text
|
||||
Use cloud memory only for non-sensitive preferences unless a project policy approves broader use.
|
||||
```
|
||||
|
||||
## MCP Safety
|
||||
|
||||
MCP clients may let models invoke tools automatically. For that reason, workspace MCP tools should stay read-only by default and return bounded, source-attributed context.
|
||||
|
||||
If future MCP write tools are added, require:
|
||||
|
||||
- explicit user intent;
|
||||
- narrow target paths;
|
||||
- clear diffs or summaries;
|
||||
- no secret exposure;
|
||||
- easy audit through git.
|
||||
|
||||
## Sharing The Repo
|
||||
|
||||
Before sharing or open-sourcing a reusable version:
|
||||
|
||||
1. Remove or isolate project-specific profile data.
|
||||
2. Confirm ignored inbox/runtime files are not tracked.
|
||||
3. Replace real profile examples with sanitized examples.
|
||||
4. Keep reusable architecture docs in `docs/` and `core/`.
|
||||
5. Keep confidential project knowledge in private profile/workspace data.
|
||||
61
docs/services.md
Normal file
61
docs/services.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Services
|
||||
|
||||
The AI Workspace Service Manager provides one profile-aware lifecycle surface for local services.
|
||||
|
||||
## Responsibility
|
||||
|
||||
The service manager starts, stops, checks, and tails logs. It does not merge service responsibilities.
|
||||
|
||||
```text
|
||||
Service Manager → process lifecycle/status/logs
|
||||
MCP Server → read-only context access
|
||||
Connectors → raw evidence capture
|
||||
Agent/Human → memory promotion
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
python3 scripts/aiw/services.py status --profile fidelity
|
||||
python3 scripts/aiw/services.py status --profile fidelity --json
|
||||
python3 scripts/aiw/services.py doctor --profile fidelity
|
||||
python3 scripts/aiw/services.py start --profile fidelity
|
||||
python3 scripts/aiw/services.py stop --profile fidelity
|
||||
python3 scripts/aiw/services.py logs aiw-context-mcp --profile fidelity
|
||||
```
|
||||
|
||||
## Service Manifest
|
||||
|
||||
Services are declared per profile:
|
||||
|
||||
```text
|
||||
profiles/<profile>/services.json
|
||||
```
|
||||
|
||||
A service can define:
|
||||
|
||||
- command;
|
||||
- kind;
|
||||
- groups;
|
||||
- dependencies;
|
||||
- restart policy;
|
||||
- doctor checks;
|
||||
- health checks.
|
||||
|
||||
## Current Service Types
|
||||
|
||||
- `process`: long-running command with PID/log tracking.
|
||||
- `app-launcher`: one-shot command that opens an app/helper.
|
||||
- `mcp`: process service exposing an MCP-compatible context server.
|
||||
|
||||
## Runtime Files
|
||||
|
||||
Runtime artifacts are local and ignored:
|
||||
|
||||
```text
|
||||
.aiw/runtime/pids/
|
||||
.aiw/runtime/logs/
|
||||
.aiw/runtime/state/
|
||||
```
|
||||
|
||||
These files are operational state, not project memory.
|
||||
@@ -23,6 +23,11 @@
|
||||
"OBSIDIAN_HOST": "127.0.0.1",
|
||||
"OBSIDIAN_PORT": "27124"
|
||||
}
|
||||
},
|
||||
"aiw-context-mcp": {
|
||||
"type": "remote",
|
||||
"url": "http://127.0.0.1:8765/mcp",
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"permission": {
|
||||
|
||||
@@ -38,9 +38,9 @@ Non-sensitive example profile showing how a new project can reuse the workspace
|
||||
|
||||
## Context
|
||||
|
||||
Project-specific durable context should live under `project-knowledge/03-context/`.
|
||||
Project-specific durable context should live under `workspaces/example/project-knowledge/03-context/`.
|
||||
|
||||
People, decisions, daily notes, maps, and templates should live under the corresponding `project-knowledge/` folders.
|
||||
People, decisions, daily notes, maps, and templates should live under the corresponding `workspaces/example/project-knowledge/` folders.
|
||||
|
||||
Do not place company secrets, raw exports, credentials, or private communication transcripts in the profile.
|
||||
|
||||
|
||||
8
profiles/example/workspace.json
Normal file
8
profiles/example/workspace.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profile": "example",
|
||||
"display_name": "Example Project",
|
||||
"description": "Sanitized example profile for adapting AI Workspace to a new project.",
|
||||
"knowledge_dir": "workspaces/example/project-knowledge",
|
||||
"inbox_dir": "workspaces/example/inbox",
|
||||
"index_dir": ".aiw/indexes/example"
|
||||
}
|
||||
15
profiles/fidelity/context-sources.json
Normal file
15
profiles/fidelity/context-sources.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"profile": "fidelity",
|
||||
"communication_sources": {
|
||||
"mattermost": {
|
||||
"type": "mattermost_mirror",
|
||||
"context_channels": [
|
||||
"fidelity-preguntas",
|
||||
"fidelity-standup",
|
||||
"fidelity-code-review",
|
||||
"fidelity-interface-meetings-on-calendar-outlook-team-etc",
|
||||
"dm-david--jeff"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,17 +20,13 @@ It keeps Fidelity-specific context, integrations, commands, and skills separate
|
||||
## Communication Sources
|
||||
|
||||
- Live communication: Mattermost
|
||||
- Preferred local Mattermost evidence source: proxy mirror under `workspaces/fidelity/inbox/mattermost-mirror/` when present; legacy `workspaces/fidelity/inbox/mattermost-latest.md` and `scripts/mattermost/generated/` are fallback evidence.
|
||||
- Historical archive: Slack export
|
||||
- Preferred channel naming: readable channel names instead of raw IDs
|
||||
- Current high-signal channel: `fidelity-preguntas`
|
||||
- Focused Mattermost context for standups/latest project reads should come from configured profile/environment channels, not hardcoded connector defaults. For this profile, the useful context-channel set is currently `fidelity-preguntas`, `fidelity-standup`, `fidelity-code-review`, `fidelity-interface-meetings-on-calendar-outlook-team-etc`, and `dm-david--jeff`; keep that list in local `.env` as `AIW_MATTERMOST_CONTEXT_CHANNELS` or an equivalent profile setup when using the reusable Mattermost reader.
|
||||
|
||||
Compatibility environment variables:
|
||||
|
||||
- `FIDELITY_MATTERMOST_SYNC_CMD`
|
||||
- `FIDELITY_MATTERMOST_SYNC_INTERVAL_MINUTES`
|
||||
- `FIDELITY_SLACK_EXPORT_PATH`
|
||||
|
||||
Generic variables should be preferred for new setup:
|
||||
Generic workspace variables:
|
||||
|
||||
- `AIW_PROJECT_KNOWLEDGE_DIR`
|
||||
- `AIW_MATTERMOST_SYNC_CMD`
|
||||
@@ -38,22 +34,23 @@ Generic variables should be preferred for new setup:
|
||||
- `AIW_SLACK_EXPORT_PATH`
|
||||
- `AIW_CHANNEL_PREFIX=fidelity`
|
||||
- `AIW_PROJECT_PROFILE=fidelity`
|
||||
- `AIW_MATTERMOST_CONTEXT_CHANNELS=fidelity-preguntas,fidelity-standup,fidelity-code-review,fidelity-interface-meetings-on-calendar-outlook-team-etc,dm-david--jeff`
|
||||
|
||||
---
|
||||
|
||||
## Work System
|
||||
|
||||
- Work items are Jira-linked when available
|
||||
- Active ticket memory lives in `project-knowledge/02-work-items/`
|
||||
- Compact active summary lives in `project-knowledge/01-current/work-items.md`
|
||||
- Active ticket memory lives in `workspaces/fidelity/project-knowledge/02-work-items/`
|
||||
- Compact active summary lives in `workspaces/fidelity/project-knowledge/01-current/work-items.md`
|
||||
- Jira IDs and approved titles should remain visible for standups and manager updates
|
||||
|
||||
---
|
||||
|
||||
## Stakeholders
|
||||
|
||||
- Current manager mapping lives in `project-knowledge/04-people/manager.md`
|
||||
- Person-specific collaboration context lives in `project-knowledge/04-people/`
|
||||
- Current manager mapping lives in `workspaces/fidelity/project-knowledge/04-people/manager.md`
|
||||
- Person-specific collaboration context lives in `workspaces/fidelity/project-knowledge/04-people/`
|
||||
- Manager-facing messages should be concise, explicit, and natural professional US English
|
||||
|
||||
---
|
||||
@@ -62,14 +59,14 @@ Generic variables should be preferred for new setup:
|
||||
|
||||
Core Fidelity context remains in:
|
||||
|
||||
- `project-knowledge/03-context/project.md`
|
||||
- `project-knowledge/03-context/systems/`
|
||||
- `project-knowledge/03-context/workstreams/`
|
||||
- `project-knowledge/03-context/ios/`
|
||||
- `project-knowledge/03-context/process/`
|
||||
- `project-knowledge/05-decisions/`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/project.md`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/systems/`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/workstreams/`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/ios/`
|
||||
- `workspaces/fidelity/project-knowledge/03-context/process/`
|
||||
- `workspaces/fidelity/project-knowledge/05-decisions/`
|
||||
|
||||
Raw communication evidence remains outside the project knowledge vault under `ai/inbox/` and generated connector folders.
|
||||
Raw communication evidence remains outside the project knowledge vault under `workspaces/fidelity/inbox/` and generated connector folders.
|
||||
|
||||
Memory access should go through the project-agnostic `scripts/memory/` interface for note creation, search, Base queries, and health checks. Obsidian is the current visual and CLI adapter, not a Fidelity-specific dependency.
|
||||
|
||||
|
||||
69
profiles/fidelity/services.json
Normal file
69
profiles/fidelity/services.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"profile": "fidelity",
|
||||
"description": "Local AI Workspace services for the Fidelity profile.",
|
||||
"services": {
|
||||
"aiw-context-mcp": {
|
||||
"enabled": true,
|
||||
"kind": "mcp",
|
||||
"description": "Read-only AI Workspace context MCP server.",
|
||||
"command": ["python3", "scripts/mcp/aiw-context-mcp/server.py", "--transport", "http"],
|
||||
"groups": ["mcp", "context"],
|
||||
"restart": "on-failure",
|
||||
"doctor": {
|
||||
"required_commands": ["python3"],
|
||||
"required_paths": ["scripts/mcp/aiw-context-mcp/server.py"]
|
||||
},
|
||||
"health": {
|
||||
"type": "http",
|
||||
"url": "http://127.0.0.1:8765/health"
|
||||
}
|
||||
},
|
||||
"mattermost-proxy": {
|
||||
"enabled": true,
|
||||
"kind": "process",
|
||||
"description": "Local mitmproxy mirror that captures normalized Mattermost evidence.",
|
||||
"command": ["scripts/mattermost-proxy/run-mirror.sh"],
|
||||
"groups": ["communication", "mattermost", "capture"],
|
||||
"restart": "on-failure",
|
||||
"doctor": {
|
||||
"required_commands": ["mitmdump"],
|
||||
"optional_paths": ["scripts/mattermost-proxy/.env"]
|
||||
},
|
||||
"health": {
|
||||
"type": "tcp",
|
||||
"host": "127.0.0.1",
|
||||
"port": 8080
|
||||
}
|
||||
},
|
||||
"mattermost-desktop": {
|
||||
"enabled": true,
|
||||
"kind": "app-launcher",
|
||||
"description": "Launch Mattermost Desktop through the local proxy.",
|
||||
"command": ["scripts/mattermost-proxy/launch-mattermost.sh"],
|
||||
"groups": ["communication", "mattermost"],
|
||||
"depends_on": ["mattermost-proxy"],
|
||||
"restart": "never",
|
||||
"doctor": {
|
||||
"required_paths": ["/Applications/Mattermost.app"],
|
||||
"optional_paths": ["scripts/mattermost-proxy/.env"]
|
||||
}
|
||||
},
|
||||
"photo-inbox": {
|
||||
"enabled": true,
|
||||
"kind": "process",
|
||||
"description": "macOS HTTP receiver for iPhone photo uploads into the local inbox.",
|
||||
"command": ["scripts/iphone-photo-inbox/run.sh"],
|
||||
"groups": ["inbox", "photos", "capture"],
|
||||
"restart": "on-failure",
|
||||
"doctor": {
|
||||
"required_commands": ["python3"],
|
||||
"optional_commands": ["swiftc"],
|
||||
"optional_paths": ["scripts/iphone-photo-inbox/.env"]
|
||||
},
|
||||
"health": {
|
||||
"type": "http",
|
||||
"url": "http://127.0.0.1:8787/health"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user