Status: Implemented Date: 2026-02-19 Deciders: Augur Team Related: ADR-109 (Filesystem-Driven Dashboard), ADR-105 (Hub-Driven Plugin Architecture), ADR-112 (Plugin Completeness), ADR-121 (Hub Ownership Validation), ADR-083 (Colocate Plugin Data), ADR-087 (Eliminate data/ Directory)
Augur's core value proposition is that users can add, remove, and compose skills with zero friction — drop a folder, get a plugin. Today, several gaps undermine this:
-
No detection of new skills: When a user creates a new folder under
plugins/{bundle}/skills/, nothing happens until they manually runmount-pluginsand restart the dashboard. There is no guided onboarding for the new skill. -
No detection of deleted skills: Removing a skill folder can leave orphan routes, stale nav entries, and broken dependency references that surface only at build time.
-
Centralized enable/disable: Plugin state lives in
config/system/plugin_state.json(dashboard) andconfig.yamlskills_state.disabledlist (Python). Two separate files, neither colocated with the plugin. This violates the self-containment principle (ADR-083) and makes it impossible togit mva plugin between machines without also migrating config. -
No uninstall/archive: The "Uninstall" button on the plugin page has no defined behavior. Users who want to remove a skill must manually delete files, with no recovery path.
-
No bundle-level lifecycle: Users cannot create or remove an entire hub by simply creating or deleting a directory — they must also update mount config and navigation.
-
CLI-first users are unsupported: All plugin management requires the web GUI. Users who prefer terminal workflows have no structured path for skill lifecycle operations.
These gaps make Augur's plugin system feel fragile and config-heavy instead of filesystem-native.
We will implement a fully filesystem-driven plugin lifecycle where the filesystem IS the source of truth. No central configuration files for plugin state. Every plugin is self-contained.
A new daemon service plugin_watcher.py runs under the unified daemon (plugins/observability/skills/daemon/scripts/unified_daemon.py) with a 10-second polling interval.
What it watches:
plugins/*/skills/*/— skill-level folders (creation, deletion, rename)plugins/*/— bundle-level folders (creation, deletion)
How it detects changes:
- Maintains a snapshot file at
runtime/plugin_watcher_snapshot.jsoncontaining the last-known set of{bundle}/{skill}paths and their mtimes. - Each poll cycle: scan filesystem, diff against snapshot, emit events for
skill_added,skill_removed,bundle_added,bundle_removed. - Snapshot is updated after events are processed.
Event output:
- Writes events to
runtime/plugin_events.json(append-only, max 100 entries, FIFO). - Each event:
{ type, bundle, skill?, timestamp, acknowledged: false }.
When the dashboard detects unacknowledged events in runtime/plugin_events.json (via polling API route /api/plugin-events):
For skill_added:
- Shows a toast notification: "New skill detected:
{skill}in{bundle}" - Notification button opens the Skill Wizard modal with options:
- Quick Setup: Auto-generates minimal
dashboard.yaml,SKILL.md, and a starter page. Runsmount-pluginsto mount immediately. - Configure Manually: Opens the skill folder in the user's editor (respects ADR-114 editor settings).
- Ignore: Dismisses; marks event as acknowledged.
- Quick Setup: Auto-generates minimal
For skill_removed:
- Shows a toast notification: "Skill removed:
{skill}from{bundle}" - Notification button opens the Removal Wizard modal:
- Shows impacted dependencies (required/optional from other skills'
dashboard.yaml). - Clean Up: Runs
mount-plugins --cleanto remove stale mounts. Updates nav. - Undo: If skill was archived (see Section 6), offers one-click restore.
- Shows impacted dependencies (required/optional from other skills'
For bundle_added:
- Shows toast: "New hub detected:
{bundle}" - Opens wizard that creates a minimal starter skill with
dashboard.yaml(role: primary), aSKILL.md, and a "Start Here" overview page. Adds to nav automatically on next mount.
For bundle_removed:
- Shows toast: "Hub removed:
{bundle}(N skills)" - Opens removal wizard showing all skills that were in the bundle and their downstream dependencies.
When the watcher detects a change, it also creates a TODO marker file alongside the event:
For new skill: Creates plugins/{bundle}/skills/{skill}/TODO_NEWSKILL with contents:
# New skill detected by Augur plugin watcher
# Created: {timestamp}
#
# This skill needs setup. Options:
# 1. Run /skill-setup {bundle}/{skill} to auto-generate scaffold
# 2. Create dashboard.yaml and SKILL.md manually
# 3. Delete this file to dismiss
#
# The dashboard will show a setup wizard for this skill until
# this TODO is resolved (file deleted or skill configured).
For removed skill: Creates runtime/todos/TODO_SKILL_REMOVED_{bundle}_{skill} with details about what was removed and impacted dependencies.
The nightly marker scanner (scan_code_markers.py) already picks up TODO_* files — these will appear in the daily report.
- Once a TODO marker exists for a skill, the GUI will NOT re-notify for the same skill unless the folder's mtime changes (indicating the user modified it again).
- The acknowledgement flow:
- Watcher detects change → writes event + creates TODO
- GUI shows notification → user can open wizard or ignore
- Ignoring marks the event as
acknowledged: trueinplugin_events.json - The TODO file persists until the user resolves it (configures the skill or deletes the TODO)
- If the user modifies the folder again (new files added), the watcher creates a fresh event (new timestamp) which triggers a new notification
Disable a skill: Create a .disabled marker file in the skill folder:
plugins/{bundle}/skills/{skill}/.disabled
Disable an entire bundle: Create .disabled in the bundle root:
plugins/{bundle}/.disabled
Marker file contents (optional, for human readability):
# Disabled by user on 2026-02-19T14:30:00Z
# Reason: Testing alternative skill
Mount system integration:
mount-plugins.tsdiscoverPlugins()checks for.disabledfile before processing each skill/bundle.skill_registry.py_iter_skill_dirs()checks for.disabledfile and setsdisabled=True.plugin_tools.pyMCP tool discovery skips.disabledskills.
Migration from centralized config:
- One-time migration script reads
config/system/plugin_state.jsonandconfig.yamlskills_state.disabled, creates corresponding.disabledfiles, then removes the old config entries. - After migration,
plugin_state.jsonandconfig.yamlskills_statesection are no longer read for enable/disable state.
GUI plugin page integration:
- "Disable" button on plugin page → creates
.disabledfile in skill folder. - "Enable" button → deletes
.disabledfile. - Disabled skills appear grayed out in nav with a "disabled" badge.
When a user clicks "Uninstall" on the plugin page for a skill:
- The skill folder is moved (not deleted) to an archive directory:
plugins/.archive/{bundle}/skills/{skill}/ - Archive preserves the full folder structure including
dashboard/,api/,data/,scripts/,SKILL.md,dashboard.yaml, etc. - A metadata file is created at
plugins/.archive/{bundle}/skills/{skill}/.archive-meta.json:{ "archived_at": "2026-02-19T14:30:00Z", "original_path": "plugins/career/skills/resume-writer", "reason": "user_uninstall", "version": "1.0.0" } - Mount system runs cleanup to remove stale routes.
- The watcher detects the removal and creates a
skill_removedevent.
For bundle uninstall:
- Entire bundle folder moves to
plugins/.archive/{bundle}/. - All skills within it are archived together.
Recovery:
- GUI "Archived Skills" section (under Settings/Plugins page) lists archived skills with a "Restore" button.
- Restore moves the folder back to its original path and triggers
skill_addedevent. - CLI:
mv plugins/.archive/{bundle}/skills/{skill} plugins/{bundle}/skills/{skill}— the watcher detects it as a new skill.
New bundle creation (user creates plugins/mytools/):
- Watcher detects new directory with no
skills/subdirectory yet. - Waits one poll cycle (10s) to see if user is still setting up.
- If
skills/subdirectory appears, processes normally. - If no
skills/after 2 cycles, creates a starter skill:plugins/mytools/skills/overview/ ├── SKILL.md (minimal frontmatter) ├── dashboard.yaml (role: primary, hub.id: mytools) └── dashboard/ └── page.tsx ("Start Here" page with setup instructions) - Runs mount to add to nav immediately.
Bundle deletion (user deletes plugins/mytools/):
- Watcher detects removal of all skills in the bundle.
- Emits
bundle_removedevent. - Mount cleanup removes all routes and nav entries for the bundle.
- Dependency checker runs — if any other skills declared
dependencies.requiredreferencing skills in this bundle, they are flagged withTODO_BROKEN_DEP.
When a skill or bundle is removed (deleted or archived), the system checks all remaining skills' dashboard.yaml dependencies section:
requireddependency broken: The dependent skill's page shows a warning banner: "Required dependency{skill}is missing. Some features may not work." ATODO_BROKEN_DEPmarker is created.optionaldependency broken: No warning, no TODO. The dependent skill gracefully degrades (this is already the expected behavior per ADR-112).
This mirrors the existing behavior but adds proactive detection at removal time instead of waiting for build failures.
The mount system (mount-plugins.ts) gains these checks in its discovery phase:
For each plugins/{bundle}/:
├── Skip if .disabled exists at bundle level
├── For each skills/{skill}/:
│ ├── Skip if .disabled exists at skill level
│ ├── Skip if no dashboard.yaml (not a dashboard skill)
│ ├── Validate hub ownership (ADR-121)
│ └── Mount normally
└── After mounting: delete stale mounts for skills/bundles that no longer exist
New API routes for the dashboard:
| Route | Method | Purpose |
|---|---|---|
/api/plugin-events |
GET | Poll for unacknowledged plugin events |
/api/plugin-events/acknowledge |
POST | Mark event as acknowledged |
/api/plugin-lifecycle/disable |
POST | Create .disabled file |
/api/plugin-lifecycle/enable |
POST | Remove .disabled file |
/api/plugin-lifecycle/uninstall |
POST | Move skill to archive |
/api/plugin-lifecycle/restore |
POST | Restore skill from archive |
/api/plugin-lifecycle/archive |
GET | List archived skills |
/api/plugin-lifecycle/scaffold |
POST | Generate minimal skill scaffold |
- Zero-config plugin management: Drop a folder = get a plugin. Delete a folder = clean removal. No config files to edit.
- Self-contained plugins: Every piece of state (enabled, disabled, archived) lives in the plugin's own directory.
git clone+git mvworks perfectly. - CLI-first workflow: TODO markers and folder operations give terminal users first-class support.
- Safe uninstall: Archive with one-click restore eliminates fear of losing work.
- Bundle-level operations: Creating a new hub is as simple as
mkdir plugins/mytools. - Proactive dependency management: Removal impact is shown before damage occurs.
- Daemon polling overhead: 10-second filesystem polls add ~0.1% CPU. Acceptable for the responsiveness gained.
- Migration required: One-time migration from
plugin_state.jsonandconfig.yamlto.disabledfiles. - Archive directory growth:
plugins/.archive/can grow unbounded. Nightly cleanup can prune archives older than 90 days. - Race conditions: User modifying files while watcher processes events. Mitigated by snapshot-based diffing (not inotify).
- Existing
mount-plugins.tsflow remains the same — we add pre-checks, not replace the pipeline. - Existing
dashboard.yamlschema unchanged —.disabledis a separate file, not a field. - ADR-121 hub ownership validation runs as before — this ADR adds lifecycle events on top.
Phase 1: Filesystem Watcher
├── Step 1: Create plugin_watcher.py daemon service
├── Step 2: Implement snapshot diffing and event emission
└── Step 3: Register in unified_daemon.py service list
Phase 2: Filesystem-Based Disable (depends on Phase 1)
├── Step 4: Add .disabled check to mount-plugins.ts discoverPlugins()
├── Step 5: Add .disabled check to skill_registry.py _iter_skill_dirs()
├── Step 6: Add .disabled check to plugin_tools.py MCP discovery
├── Step 7: Write migration script from plugin_state.json → .disabled files
└── Step 8: Update plugin page Enable/Disable buttons to use .disabled files
Phase 3: Archive System (depends on Phase 2)
├── Step 9: Implement archive move logic (skill + bundle level)
├── Step 10: Create archive metadata and .archive-meta.json
├── Step 11: Implement restore logic
└── Step 12: Add "Archived Skills" section to Settings/Plugins page
Phase 4: GUI Wizard & Notifications (depends on Phase 1)
├── Step 13: Create /api/plugin-events polling route
├── Step 14: Build Skill Wizard modal component
├── Step 15: Build Removal Wizard modal component
├── Step 16: Build toast notification system for plugin events
└── Step 17: Wire notifications to wizard modals
Phase 5: TODO Markers & CLI Integration (depends on Phase 1)
├── Step 18: Emit TODO_NEWSKILL files on skill_added events
├── Step 19: Emit TODO_SKILL_REMOVED files on skill_removed events
├── Step 20: Create /skill-setup slash command for CLI scaffold
└── Step 21: Verify scan_code_markers.py picks up new TODO types
Phase 6: Bundle Lifecycle (depends on Phases 1-4)
├── Step 22: Implement bundle detection (new/removed) in watcher
├── Step 23: Auto-generate starter skill for new bundles
├── Step 24: Implement bundle-level archive
└── Step 25: Dependency impact checker for removals
Phase 7: Verification (depends on all)
├── Step 26: Run full test suite
├── Step 27: Verify mount-plugins with .disabled skills
├── Step 28: Verify archive/restore round-trip
├── Step 29: Run stale path scanner
└── Step 30: Update ADR status
The implementation prompt maps every step to a model tier. Here is the cost impact of tiered model selection vs running everything on Opus.
| Tier | Model | Steps | Percentage of Work |
|---|---|---|---|
| Low | Haiku ($0.25/$1.25 per M) | 14 | 46.7% |
| Medium | Sonnet ($3/$15 per M) | 16 | 53.3% |
| High | Opus ($15/$75 per M) | 0 | 0% (orchestrator only) |
| Approach | Cost | Savings |
|---|---|---|
| All Opus (naive) | $21.15 | — |
| Tiered (this ADR) | $4.68 | $16.47 (78% saved) |
- 14 haiku steps (file moves, marker creation, verification checks): 98.3% cheaper than Opus. These tasks are mechanical — model capability is irrelevant.
- 16 sonnet steps (React components, migration scripts, watcher logic): 80% cheaper than Opus. Standard coding tasks where Sonnet matches Opus quality.
- 0 opus worker steps: Opus reserved exclusively for orchestration (team lead), where broad context awareness matters. Orchestrator budget: ~$2.25.
The tier mapping is the critical design artifact. Without it, the same ADR execution costs 4.5x more with zero quality improvement.
Rejected because:
- Platform-specific (inotify on Linux, FSEvents on macOS, ReadDirectoryChangesW on Windows)
- Adds native dependency complexity
- 10-second polling is fast enough for human-scale operations (creating/deleting folders)
- Snapshot-based diffing is simpler, testable, and cross-platform
Rejected because:
- Violates the self-containment principle — plugin state should live with the plugin
- Makes
git mvof plugins between machines require config migration - Two sources of truth (folder exists + config says enabled) create conflicts
.disabledmarker file is simpler, more portable, and needs no parsing
Rejected because:
- Only detects changes at commit time, not at folder-creation time
- Users expect immediate feedback when they create a folder
- Not all Augur installations use git for plugin management
src/dashboard/scripts/mount-plugins.ts— Current mount pipelinesrc/dashboard/lib/plugin-state.ts— Current centralized plugin statesrc/plugins/skill_registry.py— Python skill discoveryplugins/observability/skills/daemon/scripts/unified_daemon.py— Daemon service runnerconfig/system/plugin_state.json— Current plugin state (to be migrated).github/scripts/scan_code_markers.py— TODO marker scanner
Paste this into Claude Code to execute this ADR using Agent Teams. Auto-generated by
/write-adr. Edit if needed before running.
You are implementing ADR-122: Filesystem-Driven Plugin Lifecycle Management.
Read the full ADR: docs/decisions/ADR-122-filesystem-driven-plugin-lifecycle.md
Create a team and spawn teammates to execute the plan below:
- Create team:
TeamCreate(team_name="adr-122-plugin-lifecycle", description="Implementing ADR-122: Filesystem-Driven Plugin Lifecycle Management") - Create tasks: For each step in the Execution Plan, create a task via
TaskCreate. Setblocked_byfor PIPELINE dependencies. - Spawn teammates: For each unique agent role in the Execution Plan, spawn a teammate:
Task(subagent_type="general-purpose", team_name="adr-122-plugin-lifecycle", name="{role}", model="{tier-model}", prompt="You are '{role}' on the adr-122 team. Read your profile: .claude/agents/{role}.md Check TaskList for your assigned tasks. After each task: TaskUpdate to complete, SendMessage to team lead. If blocked, move to next available task.") - Profile loading: Each teammate MUST read
.claude/agents/{name}.mdfor iron laws and constraints - Communication: Teammates use
SendMessageto report completion, request reviews, and debate - Dependencies: PARALLEL phases -> spawn all at once. PIPELINE phases -> use task blocking
- Review cycle: After implementation, validator reviews changes and debates with developer via
SendMessage - Shutdown: When all phases pass, send
shutdown_requestto all teammates, thenTeamDelete()
Model mapping: low -> haiku, medium -> sonnet, high -> opus
Team name: adr-122-plugin-lifecycle
Strategy: PIPELINE Agents:
| Step | Agent | Tier | Task | Files |
|---|---|---|---|---|
| 1.1 | developer | medium | Create plugin_watcher.py daemon service — poll plugins/*/skills/*/ every 10s, diff against snapshot, emit events to runtime/plugin_events.json |
plugins/observability/skills/daemon/scripts/plugin_watcher.py |
| 1.2 | developer | low | Create snapshot schema and event schema (runtime/plugin_watcher_snapshot.json, runtime/plugin_events.json) with FIFO capping at 100 entries |
plugins/observability/skills/daemon/scripts/plugin_watcher.py |
| 1.3 | devops | low | Register plugin_watcher.py in unified daemon service list as a persistent service with 10s interval |
plugins/observability/skills/daemon/scripts/unified_daemon.py |
Strategy: PARALLEL (Steps 2.1-2.3 can run concurrently, then 2.4-2.5 sequentially) Agents:
| Step | Agent | Tier | Task | Files |
|---|---|---|---|---|
| 2.1 | developer | medium | Add .disabled file check to discoverPlugins() in mount-plugins.ts — skip skill if {skillDir}/.disabled exists, skip bundle if {bundleDir}/.disabled exists |
src/dashboard/scripts/mount-plugins.ts |
| 2.2 | developer | medium | Add .disabled file check to _iter_skill_dirs() in skill_registry.py — set disabled=True if .disabled exists in skill or parent bundle dir |
src/plugins/skill_registry.py |
| 2.3 | developer | low | Add .disabled file check to MCP plugin tool discovery — skip skills with .disabled |
src/mcp/augur_mcp/plugin_tools.py |
| 2.4 | developer | medium | Write migration script migrate_plugin_state.py — reads config/system/plugin_state.json + config.yaml skills_state.disabled, creates .disabled files, removes old config entries |
src/scripts/migrate_plugin_state.py |
| 2.5 | developer | medium | Update plugin page Enable/Disable buttons to create/delete .disabled files via new API route instead of writing to plugin_state.json |
src/dashboard/app/admin/settings/plugins/, src/dashboard/app/api/plugin-lifecycle/ |
Strategy: PIPELINE Agents:
| Step | Agent | Tier | Task | Files |
|---|---|---|---|---|
| 3.1 | developer | medium | Implement archive move logic — POST /api/plugin-lifecycle/uninstall moves skill folder to plugins/.archive/{bundle}/skills/{skill}/, creates .archive-meta.json |
src/dashboard/app/api/plugin-lifecycle/uninstall/route.ts |
| 3.2 | developer | medium | Implement restore logic — POST /api/plugin-lifecycle/restore moves folder back from archive, triggers mount |
src/dashboard/app/api/plugin-lifecycle/restore/route.ts |
| 3.3 | developer | medium | Implement bundle-level archive — moves entire bundle to plugins/.archive/{bundle}/ |
src/dashboard/app/api/plugin-lifecycle/uninstall/route.ts |
| 3.4 | developer | medium | Add "Archived Skills" section to Settings/Plugins page — lists archived skills from plugins/.archive/ with Restore button |
plugins/admin/skills/settings/dashboard/plugins/ |
Strategy: PIPELINE Agents:
| Step | Agent | Tier | Task | Files |
|---|---|---|---|---|
| 4.1 | developer | low | Create GET /api/plugin-events route — reads runtime/plugin_events.json, returns unacknowledged events |
src/dashboard/app/api/plugin-events/route.ts |
| 4.2 | developer | low | Create POST /api/plugin-events/acknowledge route — marks events as acknowledged |
src/dashboard/app/api/plugin-events/acknowledge/route.ts |
| 4.3 | developer | medium | Build Skill Wizard modal component — Quick Setup (scaffold + mount), Configure Manually (open editor), Ignore | src/dashboard/components/plugin-wizard/SkillWizard.tsx |
| 4.4 | developer | medium | Build Removal Wizard modal component — shows dependency impact, Clean Up, Undo (if archived) | src/dashboard/components/plugin-wizard/RemovalWizard.tsx |
| 4.5 | developer | medium | Build toast notification system — polls /api/plugin-events every 15s, shows toasts, opens wizards |
src/dashboard/components/plugin-wizard/PluginEventNotifier.tsx |
| 4.6 | developer | low | Create POST /api/plugin-lifecycle/scaffold route — generates minimal skill scaffold (dashboard.yaml, SKILL.md, starter page) |
src/dashboard/app/api/plugin-lifecycle/scaffold/route.ts |
Strategy: PARALLEL Agents:
| Step | Agent | Tier | Task | Files |
|---|---|---|---|---|
| 5.1 | developer | low | Add TODO_NEWSKILL file creation to plugin_watcher.py on skill_added events — file created inside the new skill folder |
plugins/observability/skills/daemon/scripts/plugin_watcher.py |
| 5.2 | developer | low | Add TODO_SKILL_REMOVED file creation to plugin_watcher.py on skill_removed events — file created in runtime/todos/ |
plugins/observability/skills/daemon/scripts/plugin_watcher.py |
| 5.3 | developer | medium | Create /skill-setup slash command — generates scaffold for a given {bundle}/{skill} path, removes TODO_NEWSKILL on completion |
plugins/ai/skills/ai_bridge/data/skills/skill-setup/SKILL.md |
| 5.4 | validator | low | Verify scan_code_markers.py picks up TODO_NEWSKILL and TODO_SKILL_REMOVED marker types |
.github/scripts/scan_code_markers.py |
Strategy: PIPELINE Agents:
| Step | Agent | Tier | Task | Files |
|---|---|---|---|---|
| 6.1 | developer | medium | Add bundle-level detection to plugin_watcher.py — detect new/removed directories under plugins/, distinguish from skill-level changes |
plugins/observability/skills/daemon/scripts/plugin_watcher.py |
| 6.2 | developer | medium | Auto-generate starter skill for new bundles — creates skills/overview/ with minimal dashboard.yaml (role: primary), SKILL.md, and page.tsx |
plugins/observability/skills/daemon/scripts/plugin_watcher.py |
| 6.3 | developer | medium | Implement dependency impact checker — on removal, scan all remaining skills' dashboard.yaml dependencies, flag broken required deps with TODO_BROKEN_DEP | plugins/observability/skills/daemon/scripts/plugin_watcher.py |
Strategy: PIPELINE Agents:
| Step | Agent | Tier | Task |
|---|---|---|---|
| V.1 | validator | low | Run full test suite (pytest tests/src/, npm run build), verify no regressions |
| V.2 | validator | low | Test mount-plugins with .disabled skills — verify they are skipped in nav and routes |
| V.3 | validator | low | Test archive/restore round-trip — uninstall a skill, verify removal, restore, verify re-mount |
| V.4 | devops | low | Run stale path scanner: python3 .github/scripts/scan_stale_paths.py --ci |
| V.5 | architect | low | Verify ADR intent matches implementation, update ADR status to Implemented |
This ADR involves directory structure changes (new .archive/ directory, .disabled files, migration away from plugin_state.json). The final verification MUST include:
python3 .github/scripts/scan_stale_paths.py --ciAfter all phases complete and before shutdown, the team lead MUST produce a Token Usage Summary saved to runtime/adr-122-token-report.md with this format:
# ADR-122 Token Usage Report
## Execution Summary
- **Total steps executed**: N
- **Team members spawned**: N (list names + models)
- **Total duration**: Xm Ys
## Per-Agent Token Usage
| Agent | Model | Steps Completed | Input Tokens | Output Tokens | Estimated Cost |
|-------|-------|-----------------|--------------|---------------|----------------|
| developer | sonnet | N | ... | ... | $X.XX |
| devops | haiku | N | ... | ... | $X.XX |
| validator | haiku | N | ... | ... | $X.XX |
| orchestrator | opus | 1 (coordination) | ... | ... | $X.XX |
## Cost Comparison
| Approach | Estimated Cost |
|----------|---------------|
| All Opus (projected) | $X.XX |
| Tiered (actual) | $X.XX |
| **Actual savings** | **X% ($X.XX saved)** |
## Per-Phase Breakdown
| Phase | Steps | Strategy | Models Used | Notes |
|-------|-------|----------|-------------|-------|
| 1. Filesystem Watcher | 3 | PIPELINE | sonnet, haiku | ... |
| ... | ... | ... | ... | ... |
## Quality Notes
- Any steps where haiku/sonnet quality was insufficient and required rework: [list or "none"]
- Any steps where a cheaper model could have been used: [list or "none"]How to collect: Each teammate reports token usage in their completion message to team lead. The team lead aggregates into the report. If exact token counts are unavailable, estimate based on conversation turns and average tokens per turn (~15K input + ~5K output per step).
This report will be used as real data for a LinkedIn post about tiered model cost savings. Make the numbers accurate.
- Plugin watcher detects new/removed skills and bundles within 10s
-
.disabledfile in skill folder prevents mount, MCP registration, and nav inclusion -
plugin_state.jsonmigrated to.disabledfiles, old config removed - Uninstall moves to
plugins/.archive/with metadata; restore works - GUI shows toast notifications and wizard modals for plugin events
- TODO_NEWSKILL and TODO_SKILL_REMOVED markers are created and scannable
- Bundle creation auto-generates starter skill
- Dependency impact shown on skill/bundle removal
- All tests pass
- Stale path scanner clean
- ADR status updated to Implemented
# Option 1: Use /implement-adr (handles team orchestration automatically)
/implement-adr docs/decisions/ADR-122-filesystem-driven-plugin-lifecycle.md
# Option 2: Paste this prompt into Claude Code
# The agent will create the team, spawn teammates, and coordinate