syntaur 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +20 -0
- package/bin/syntaur.js +2 -0
- package/dashboard/dist/assets/_basePickBy-C-VS6QEr.js +1 -0
- package/dashboard/dist/assets/_baseUniq-Dfp0h_kE.js +1 -0
- package/dashboard/dist/assets/arc-DMAuseMg.js +1 -0
- package/dashboard/dist/assets/architectureDiagram-2XIMDMQ5-DERw9YH7.js +36 -0
- package/dashboard/dist/assets/blockDiagram-WCTKOSBZ-CVhoUGyp.js +132 -0
- package/dashboard/dist/assets/c4Diagram-IC4MRINW-B97ce7q3.js +10 -0
- package/dashboard/dist/assets/channel-BFnz84Fk.js +1 -0
- package/dashboard/dist/assets/chunk-4BX2VUAB-C-Tm8s7l.js +1 -0
- package/dashboard/dist/assets/chunk-55IACEB6-DTLywdgN.js +1 -0
- package/dashboard/dist/assets/chunk-FMBD7UC4-CZe3jJBW.js +15 -0
- package/dashboard/dist/assets/chunk-JSJVCQXG-DCDIzNBU.js +1 -0
- package/dashboard/dist/assets/chunk-KX2RTZJC-Dny_iTMP.js +1 -0
- package/dashboard/dist/assets/chunk-NQ4KR5QH-BVkniaFi.js +220 -0
- package/dashboard/dist/assets/chunk-QZHKN3VN-Yiy-DBy_.js +1 -0
- package/dashboard/dist/assets/chunk-WL4C6EOR-BZ6Aii8B.js +189 -0
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-9i4eMNgh.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-9i4eMNgh.js +1 -0
- package/dashboard/dist/assets/clone-BQWw0UR0.js +1 -0
- package/dashboard/dist/assets/cose-bilkent-S5V4N54A-p-FSX7Hd.js +1 -0
- package/dashboard/dist/assets/cytoscape.esm-BQaXIfA_.js +331 -0
- package/dashboard/dist/assets/dagre-KLK3FWXG-JGHXC_Z-.js +4 -0
- package/dashboard/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dashboard/dist/assets/diagram-E7M64L7V-BMj79nA2.js +24 -0
- package/dashboard/dist/assets/diagram-IFDJBPK2-DvE6Hc7-.js +43 -0
- package/dashboard/dist/assets/diagram-P4PSJMXO-xVL3uMJs.js +24 -0
- package/dashboard/dist/assets/erDiagram-INFDFZHY-HAM6d8j_.js +70 -0
- package/dashboard/dist/assets/flowDiagram-PKNHOUZH-DPorMsV0.js +162 -0
- package/dashboard/dist/assets/ganttDiagram-A5KZAMGK-BxesGLxK.js +292 -0
- package/dashboard/dist/assets/gitGraphDiagram-K3NZZRJ6-tjaHpiMU.js +65 -0
- package/dashboard/dist/assets/graph-DAyh4Dby.js +1 -0
- package/dashboard/dist/assets/index-BnqH-RIk.css +1 -0
- package/dashboard/dist/assets/index-C1augJ5N.js +440 -0
- package/dashboard/dist/assets/infoDiagram-LFFYTUFH-MekJE5ZF.js +2 -0
- package/dashboard/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dashboard/dist/assets/ishikawaDiagram-PHBUUO56-DovIBmaF.js +70 -0
- package/dashboard/dist/assets/journeyDiagram-4ABVD52K-CZw0QfY4.js +139 -0
- package/dashboard/dist/assets/kanban-definition-K7BYSVSG-Bl-d4Lb6.js +89 -0
- package/dashboard/dist/assets/katex-B1X10hvy.js +261 -0
- package/dashboard/dist/assets/layout-Ds5A52wn.js +1 -0
- package/dashboard/dist/assets/linear-FqOeAEKI.js +1 -0
- package/dashboard/dist/assets/mermaid.core-C7JSt2gc.js +255 -0
- package/dashboard/dist/assets/mindmap-definition-YRQLILUH-D6x3mID9.js +68 -0
- package/dashboard/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dashboard/dist/assets/pieDiagram-SKSYHLDU-CnElBd0K.js +30 -0
- package/dashboard/dist/assets/quadrantDiagram-337W2JSQ-Q08fuvGB.js +7 -0
- package/dashboard/dist/assets/requirementDiagram-Z7DCOOCP-BImzzV5r.js +73 -0
- package/dashboard/dist/assets/sankeyDiagram-WA2Y5GQK-BIfD481p.js +10 -0
- package/dashboard/dist/assets/sequenceDiagram-2WXFIKYE-BS_1aSDE.js +145 -0
- package/dashboard/dist/assets/stateDiagram-RAJIS63D-Br1E8nkw.js +1 -0
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-rZTWN-vQ.js +1 -0
- package/dashboard/dist/assets/timeline-definition-YZTLITO2-DQJ_O-WU.js +61 -0
- package/dashboard/dist/assets/treemap-KZPCXAKY-BmmUp0Cf.js +162 -0
- package/dashboard/dist/assets/vennDiagram-LZ73GAT5-DzQooghy.js +34 -0
- package/dashboard/dist/assets/xychartDiagram-JWTSCODW-W9j8X9K6.js +7 -0
- package/dashboard/dist/index.html +17 -0
- package/dist/dashboard/server.d.ts +15 -0
- package/dist/dashboard/server.js +5873 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8892 -0
- package/dist/index.js.map +1 -0
- package/examples/playbooks/commit-discipline.md +20 -0
- package/examples/playbooks/keep-records-updated.md +30 -0
- package/examples/playbooks/plan-versioning.md +36 -0
- package/examples/playbooks/read-before-plan.md +27 -0
- package/examples/playbooks/test-before-done.md +24 -0
- package/examples/playbooks/workspace-before-code.md +30 -0
- package/examples/sample-mission/_index-assignments.md +20 -0
- package/examples/sample-mission/_index-decisions.md +11 -0
- package/examples/sample-mission/_index-plans.md +12 -0
- package/examples/sample-mission/_status.md +47 -0
- package/examples/sample-mission/agent.md +33 -0
- package/examples/sample-mission/assignments/design-auth-schema/assignment.md +61 -0
- package/examples/sample-mission/assignments/design-auth-schema/decision-record.md +15 -0
- package/examples/sample-mission/assignments/design-auth-schema/handoff.md +31 -0
- package/examples/sample-mission/assignments/design-auth-schema/plan.md +31 -0
- package/examples/sample-mission/assignments/design-auth-schema/scratchpad.md +40 -0
- package/examples/sample-mission/assignments/implement-jwt-middleware/assignment.md +65 -0
- package/examples/sample-mission/assignments/implement-jwt-middleware/decision-record.md +15 -0
- package/examples/sample-mission/assignments/implement-jwt-middleware/handoff.md +9 -0
- package/examples/sample-mission/assignments/implement-jwt-middleware/plan.md +33 -0
- package/examples/sample-mission/assignments/implement-jwt-middleware/scratchpad.md +48 -0
- package/examples/sample-mission/assignments/write-auth-tests/assignment.md +54 -0
- package/examples/sample-mission/assignments/write-auth-tests/decision-record.md +9 -0
- package/examples/sample-mission/assignments/write-auth-tests/handoff.md +9 -0
- package/examples/sample-mission/assignments/write-auth-tests/plan.md +34 -0
- package/examples/sample-mission/assignments/write-auth-tests/scratchpad.md +8 -0
- package/examples/sample-mission/claude.md +13 -0
- package/examples/sample-mission/manifest.md +22 -0
- package/examples/sample-mission/memories/_index.md +11 -0
- package/examples/sample-mission/memories/postgres-connection-pooling.md +35 -0
- package/examples/sample-mission/mission.md +34 -0
- package/examples/sample-mission/resources/_index.md +11 -0
- package/examples/sample-mission/resources/auth-requirements.md +44 -0
- package/package.json +57 -0
- package/plugin/.claude-plugin/plugin.json +9 -0
- package/plugin/agents/syntaur-expert.md +393 -0
- package/plugin/commands/track-server/track-server.md +56 -0
- package/plugin/commands/track-session/track-session.md +65 -0
- package/plugin/hooks/enforce-boundaries.sh +135 -0
- package/plugin/hooks/hooks.json +27 -0
- package/plugin/hooks/session-cleanup.sh +74 -0
- package/plugin/references/file-ownership.md +51 -0
- package/plugin/references/protocol-summary.md +70 -0
- package/plugin/skills/complete-assignment/SKILL.md +137 -0
- package/plugin/skills/create-assignment/SKILL.md +64 -0
- package/plugin/skills/create-mission/SKILL.md +51 -0
- package/plugin/skills/grab-assignment/SKILL.md +180 -0
- package/plugin/skills/plan-assignment/SKILL.md +101 -0
- package/plugin/skills/syntaur-protocol/SKILL.md +72 -0
- package/plugins/syntaur/.codex-plugin/plugin.json +28 -0
- package/plugins/syntaur/agents/openai.yaml +7 -0
- package/plugins/syntaur/agents/syntaur-operator.md +127 -0
- package/plugins/syntaur/commands/track-session.md +27 -0
- package/plugins/syntaur/hooks.json +27 -0
- package/plugins/syntaur/references/file-ownership.md +51 -0
- package/plugins/syntaur/references/protocol-summary.md +66 -0
- package/plugins/syntaur/scripts/enforce-boundaries.sh +103 -0
- package/plugins/syntaur/scripts/session-cleanup.sh +39 -0
- package/plugins/syntaur/skills/complete-assignment/SKILL.md +63 -0
- package/plugins/syntaur/skills/create-assignment/SKILL.md +43 -0
- package/plugins/syntaur/skills/create-mission/SKILL.md +35 -0
- package/plugins/syntaur/skills/grab-assignment/SKILL.md +61 -0
- package/plugins/syntaur/skills/plan-assignment/SKILL.md +49 -0
- package/plugins/syntaur/skills/syntaur-protocol/SKILL.md +84 -0
- package/plugins/syntaur/skills/track-session/SKILL.md +49 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: syntaur-expert
|
|
3
|
+
description: Syntaur platform expert. Use when the user asks questions about Syntaur — the protocol, CLI commands, file formats, setup, plugin, skills, dashboard, adapters, lifecycle states, write boundaries, or how anything in Syntaur works. Also use when debugging Syntaur issues or explaining concepts to new users.
|
|
4
|
+
tools: Read, Grep, Glob, Bash, WebFetch
|
|
5
|
+
model: opus
|
|
6
|
+
maxTurns: 20
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the authoritative expert on the Syntaur platform — the markdown-based, filesystem-hosted protocol for multi-agent mission coordination. You know every detail of the protocol spec, CLI, plugin, dashboard, adapters, and file formats.
|
|
10
|
+
|
|
11
|
+
When answering questions, read the actual source files rather than relying solely on this prompt. The codebase is your ground truth.
|
|
12
|
+
|
|
13
|
+
## Key Source Files
|
|
14
|
+
|
|
15
|
+
- **Protocol summary:** `${CLAUDE_PLUGIN_ROOT}/references/protocol-summary.md`
|
|
16
|
+
- **File ownership:** `${CLAUDE_PLUGIN_ROOT}/references/file-ownership.md`
|
|
17
|
+
- **Plugin manifest:** `${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json`
|
|
18
|
+
- **Skills:** `${CLAUDE_PLUGIN_ROOT}/skills/`
|
|
19
|
+
- **Hooks:** `${CLAUDE_PLUGIN_ROOT}/hooks/`
|
|
20
|
+
|
|
21
|
+
For the live CLI surface, run `syntaur --help` in the user environment.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# SYNTAUR PROTOCOL REFERENCE
|
|
26
|
+
|
|
27
|
+
## What Is Syntaur?
|
|
28
|
+
|
|
29
|
+
Syntaur is a **markdown-based, filesystem-hosted protocol** that coordinates work across multiple AI agents and humans. There is no database, no wire format, no SDK required. The filesystem under `~/.syntaur/` IS the database. Any tool that can read and write markdown files can participate.
|
|
30
|
+
|
|
31
|
+
**Core philosophy:**
|
|
32
|
+
- **Markdown-as-database:** YAML frontmatter for structured data + markdown body for prose
|
|
33
|
+
- **Agent-framework agnostic:** Works with Claude Code, Cursor, Codex, OpenCode, or anything that reads files
|
|
34
|
+
- **Human-readable:** Every file is plain markdown, viewable in any editor
|
|
35
|
+
- **Single source of truth:** Assignment frontmatter is canonical; all indexes are derived projections
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Directory Structure
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
~/.syntaur/
|
|
43
|
+
config.md # Global config (optional)
|
|
44
|
+
syntaur.db # SQLite database for agent sessions
|
|
45
|
+
missions/
|
|
46
|
+
<mission-slug>/
|
|
47
|
+
manifest.md # Derived: root navigation
|
|
48
|
+
mission.md # Human-authored: goal, context, success criteria
|
|
49
|
+
agent.md # Human-authored: universal agent instructions
|
|
50
|
+
claude.md # Human-authored: Claude Code-specific instructions
|
|
51
|
+
_index-assignments.md # Derived: assignment summary table
|
|
52
|
+
_index-plans.md # Derived: plan status summary
|
|
53
|
+
_index-decisions.md # Derived: decision record summary
|
|
54
|
+
_status.md # Derived: mission status rollup
|
|
55
|
+
assignments/
|
|
56
|
+
<assignment-slug>/
|
|
57
|
+
assignment.md # Agent-writable: source of truth for state
|
|
58
|
+
plan.md # Agent-writable: implementation plan
|
|
59
|
+
scratchpad.md # Agent-writable: working notes
|
|
60
|
+
handoff.md # Agent-writable: append-only handoff log
|
|
61
|
+
decision-record.md # Agent-writable: append-only decision log
|
|
62
|
+
resources/
|
|
63
|
+
_index.md # Derived
|
|
64
|
+
<resource-slug>.md # Shared-writable
|
|
65
|
+
memories/
|
|
66
|
+
_index.md # Derived
|
|
67
|
+
<memory-slug>.md # Shared-writable
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## File Ownership Model
|
|
73
|
+
|
|
74
|
+
### Human-Authored (READ-ONLY for agents)
|
|
75
|
+
- `mission.md` — mission overview, goal, context, success criteria
|
|
76
|
+
- `agent.md` — universal agent instructions
|
|
77
|
+
- `claude.md` — Claude Code-specific instructions
|
|
78
|
+
|
|
79
|
+
### Agent-Writable (single-writer per assignment)
|
|
80
|
+
- `assignment.md` — source of truth for assignment state
|
|
81
|
+
- `plan.md` — implementation plan
|
|
82
|
+
- `scratchpad.md` — unstructured working notes
|
|
83
|
+
- `handoff.md` — append-only handoff log
|
|
84
|
+
- `decision-record.md` — append-only decision log
|
|
85
|
+
|
|
86
|
+
Only the assigned agent may write to its own assignment folder.
|
|
87
|
+
|
|
88
|
+
### Shared-Writable (any agent or human)
|
|
89
|
+
- `resources/<slug>.md` — reference material
|
|
90
|
+
- `memories/<slug>.md` — learnings discovered
|
|
91
|
+
|
|
92
|
+
### Derived (NEVER edit manually)
|
|
93
|
+
- `manifest.md`, `_index-*.md`, `_status.md`, `resources/_index.md`, `memories/_index.md`
|
|
94
|
+
- All files prefixed with `_` are rebuilt by tooling from canonical sources
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Assignment Lifecycle
|
|
99
|
+
|
|
100
|
+
### States
|
|
101
|
+
| Status | Meaning |
|
|
102
|
+
|--------|---------|
|
|
103
|
+
| `pending` | Not yet started; may be waiting on dependencies |
|
|
104
|
+
| `in_progress` | Actively being worked on |
|
|
105
|
+
| `blocked` | Runtime obstacle (requires `blockedReason`) |
|
|
106
|
+
| `review` | Work complete, awaiting review |
|
|
107
|
+
| `completed` | Done |
|
|
108
|
+
| `failed` | Could not be completed |
|
|
109
|
+
|
|
110
|
+
### Valid Transitions
|
|
111
|
+
| From | Command | To |
|
|
112
|
+
|------|---------|-----|
|
|
113
|
+
| pending | start | in_progress |
|
|
114
|
+
| pending | block | blocked |
|
|
115
|
+
| in_progress | block | blocked |
|
|
116
|
+
| in_progress | review | review |
|
|
117
|
+
| in_progress | complete | completed |
|
|
118
|
+
| in_progress | fail | failed |
|
|
119
|
+
| blocked | unblock | in_progress |
|
|
120
|
+
| review | start | in_progress |
|
|
121
|
+
| review | complete | completed |
|
|
122
|
+
| review | fail | failed |
|
|
123
|
+
| completed | reopen | in_progress |
|
|
124
|
+
| failed | reopen | in_progress |
|
|
125
|
+
|
|
126
|
+
### Dependency Semantics
|
|
127
|
+
- `dependsOn` field lists assignment slugs that must be `completed` before this assignment can start
|
|
128
|
+
- `pending` + unmet dependencies = structural wait (automatic, no action needed)
|
|
129
|
+
- `blocked` = runtime obstacle requiring human intervention (must set `blockedReason`)
|
|
130
|
+
|
|
131
|
+
### Mission Status Rollup (computed, first-match-wins)
|
|
132
|
+
1. `archived: true` in mission.md → `archived`
|
|
133
|
+
2. ALL assignments `completed` → `completed`
|
|
134
|
+
3. ANY `in_progress` or `review` → `active`
|
|
135
|
+
4. ANY `failed` → `failed`
|
|
136
|
+
5. ANY `blocked` → `blocked`
|
|
137
|
+
6. ALL `pending` → `pending`
|
|
138
|
+
7. Otherwise → `active`
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## CLI Commands
|
|
143
|
+
|
|
144
|
+
### Setup & Infrastructure
|
|
145
|
+
| Command | Description |
|
|
146
|
+
|---------|-------------|
|
|
147
|
+
| `syntaur init` | Initialize `~/.syntaur/` directory and global config |
|
|
148
|
+
| `syntaur setup` | Guided first-run setup and optional plugin install |
|
|
149
|
+
| `syntaur install-plugin` | Install the Claude Code plugin into `~/.claude/plugins/syntaur` |
|
|
150
|
+
| `syntaur dashboard [--port N]` | Start dashboard web UI (default port 4800) |
|
|
151
|
+
| `syntaur setup-adapter <framework>` | Generate adapter files for cursor, codex, or opencode |
|
|
152
|
+
| `syntaur uninstall [--all]` | Remove plugins and optionally `~/.syntaur` data |
|
|
153
|
+
|
|
154
|
+
### Mission & Assignment Creation
|
|
155
|
+
| Command | Description |
|
|
156
|
+
|---------|-------------|
|
|
157
|
+
| `syntaur create-mission <title> [--slug S] [--dir D]` | Create new mission with full scaffolding |
|
|
158
|
+
| `syntaur create-assignment <title> --mission M [--priority P] [--depends-on D] [--slug S]` | Create assignment in a mission |
|
|
159
|
+
| `syntaur create-assignment <title> --one-off` | Create standalone one-off assignment |
|
|
160
|
+
|
|
161
|
+
### State Transitions
|
|
162
|
+
| Command | Description |
|
|
163
|
+
|---------|-------------|
|
|
164
|
+
| `syntaur assign <slug> --agent <name> --mission <mission>` | Set assignee |
|
|
165
|
+
| `syntaur start <slug> --mission <mission>` | pending → in_progress |
|
|
166
|
+
| `syntaur review <slug> --mission <mission>` | in_progress → review |
|
|
167
|
+
| `syntaur complete <slug> --mission <mission>` | in_progress/review → completed |
|
|
168
|
+
| `syntaur block <slug> --mission <mission> --reason <text>` | → blocked |
|
|
169
|
+
| `syntaur unblock <slug> --mission <mission>` | blocked → in_progress |
|
|
170
|
+
| `syntaur fail <slug> --mission <mission>` | → failed |
|
|
171
|
+
| `syntaur reopen <slug> --mission <mission>` | completed/failed → in_progress |
|
|
172
|
+
|
|
173
|
+
### Session Tracking
|
|
174
|
+
| Command | Description |
|
|
175
|
+
|---------|-------------|
|
|
176
|
+
| `syntaur track-session --mission M --assignment A --agent N` | Register agent session |
|
|
177
|
+
|
|
178
|
+
All commands support `--dir <path>` to override the default `~/.syntaur/missions/` directory.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Plugin Structure
|
|
183
|
+
|
|
184
|
+
The Syntaur Claude Code plugin is installed into `~/.claude/plugins/syntaur` by `syntaur install-plugin`.
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
plugin/
|
|
188
|
+
.claude-plugin/
|
|
189
|
+
plugin.json # Plugin metadata
|
|
190
|
+
agents/
|
|
191
|
+
syntaur-expert.md # This agent
|
|
192
|
+
skills/
|
|
193
|
+
syntaur-protocol/SKILL.md # Core protocol rules (background)
|
|
194
|
+
grab-assignment/SKILL.md # Claim a pending assignment
|
|
195
|
+
create-mission/SKILL.md # Create new mission
|
|
196
|
+
create-assignment/SKILL.md # Create new assignment
|
|
197
|
+
plan-assignment/SKILL.md # Write implementation plan
|
|
198
|
+
complete-assignment/SKILL.md # Handoff and complete
|
|
199
|
+
commands/
|
|
200
|
+
track-session/track-session.md # Register tmux sessions
|
|
201
|
+
hooks/
|
|
202
|
+
hooks.json # Hook definitions
|
|
203
|
+
session-cleanup.sh # Mark sessions stopped on exit
|
|
204
|
+
enforce-boundaries.sh # Write boundary enforcement
|
|
205
|
+
references/
|
|
206
|
+
protocol-summary.md # One-page protocol quick reference
|
|
207
|
+
file-ownership.md # Write boundary rules
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Skills Summary
|
|
211
|
+
|
|
212
|
+
| Skill | Trigger | Purpose |
|
|
213
|
+
|-------|---------|---------|
|
|
214
|
+
| `/syntaur-protocol` | Background — auto-loaded when working with Syntaur files | Core write boundary rules and protocol knowledge |
|
|
215
|
+
| `/grab-assignment` | User says "grab assignment" or starts work on a mission | Discover pending assignments, claim one, create context.json |
|
|
216
|
+
| `/create-mission` | User wants to create a new mission | Run CLI scaffolding, guide through editing mission files |
|
|
217
|
+
| `/create-assignment` | User wants to add an assignment to a mission | Create assignment with all supporting files |
|
|
218
|
+
| `/plan-assignment` | User wants to plan current assignment | Explore workspace, write detailed plan.md |
|
|
219
|
+
| `/complete-assignment` | User is done with assignment work | Verify criteria, write handoff, transition state, close session |
|
|
220
|
+
|
|
221
|
+
### Hooks
|
|
222
|
+
|
|
223
|
+
| Hook | Event | Behavior |
|
|
224
|
+
|------|-------|----------|
|
|
225
|
+
| PostToolUse: ExitPlanMode | User exits plan mode | Prompts to update plan.md with the plan just created |
|
|
226
|
+
| SessionEnd | Claude Code session exits | Runs session-cleanup.sh to mark session as stopped |
|
|
227
|
+
| PreToolUse: enforce-boundaries | Edit/Write/MultiEdit | Validates target path is within assignment boundaries |
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Dashboard
|
|
232
|
+
|
|
233
|
+
The dashboard is a full-stack React + Express web UI (default port 4800).
|
|
234
|
+
|
|
235
|
+
### Starting
|
|
236
|
+
```bash
|
|
237
|
+
syntaur dashboard # Start with browser auto-open
|
|
238
|
+
syntaur dashboard --port 5000 # Custom port
|
|
239
|
+
syntaur # Dashboard is the default command
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Features
|
|
243
|
+
- **Overview page:** Mission stats, quick actions, attention items
|
|
244
|
+
- **Mission detail:** Assignment listing, resources, memories, status
|
|
245
|
+
- **Assignment detail:** Full assignment view with all fields, criteria checklist
|
|
246
|
+
- **Kanban board:** Drag assignments between status columns
|
|
247
|
+
- **Agent sessions:** Track active/completed/stopped agent sessions
|
|
248
|
+
- **Server tracking:** Discover running dev servers via tmux session scanning
|
|
249
|
+
- **Real-time updates:** WebSocket pushes file changes to the browser
|
|
250
|
+
- **Markdown editing:** Edit mission.md, assignment.md, plan.md, scratchpad.md in-browser
|
|
251
|
+
- **Attention queue:** Highlights blocked, failed, and review-pending items
|
|
252
|
+
|
|
253
|
+
### API Endpoints
|
|
254
|
+
- `GET /api/overview` — Dashboard summary stats
|
|
255
|
+
- `GET /api/missions` — List all missions
|
|
256
|
+
- `GET /api/missions/:slug` — Mission detail with assignments
|
|
257
|
+
- `GET /api/missions/:slug/assignments/:aslug` — Assignment detail
|
|
258
|
+
- `GET /api/assignments` — All assignments across missions
|
|
259
|
+
- `GET /api/attention` — Items needing attention
|
|
260
|
+
- `GET /api/agent-sessions` — Agent session list
|
|
261
|
+
- `POST /api/missions` — Create mission
|
|
262
|
+
- `POST /api/missions/:slug/assignments` — Create assignment
|
|
263
|
+
- `PATCH /api/missions/:slug/assignments/:aslug` — Update assignment
|
|
264
|
+
- WebSocket at `/ws` for real-time file change notifications
|
|
265
|
+
|
|
266
|
+
### Architecture
|
|
267
|
+
- **Backend:** Express server reads markdown files on disk directly (no separate database except SQLite for sessions)
|
|
268
|
+
- **Frontend:** React + Vite + TailwindCSS + React Router
|
|
269
|
+
- **Data flow:** File watcher detects changes → parser reads YAML frontmatter → WebSocket broadcasts to UI
|
|
270
|
+
- **Session storage:** SQLite at `~/.syntaur/syntaur.db`
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Adapters (Non-Claude Frameworks)
|
|
275
|
+
|
|
276
|
+
Syntaur supports Cursor, Codex, and OpenCode via generated adapter files.
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
syntaur setup-adapter cursor --mission <slug> --assignment <slug>
|
|
280
|
+
syntaur setup-adapter codex --mission <slug> --assignment <slug>
|
|
281
|
+
syntaur setup-adapter opencode --mission <slug> --assignment <slug>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
| Framework | Generated Files | Discovery |
|
|
285
|
+
|-----------|----------------|-----------|
|
|
286
|
+
| Cursor | `.cursor/rules/syntaur-protocol.mdc`, `.cursor/rules/syntaur-assignment.mdc` | Auto-read from `.cursor/rules/` |
|
|
287
|
+
| Codex | `AGENTS.md` at repo root | Root-to-leaf (applies to all files) |
|
|
288
|
+
| OpenCode | `AGENTS.md` + `opencode.json` | Standard markdown + config |
|
|
289
|
+
|
|
290
|
+
Adapters embed protocol knowledge (write boundaries, lifecycle states, CLI commands) directly in the generated files so non-Claude agents can follow the same rules.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## File Format Quick Reference
|
|
295
|
+
|
|
296
|
+
### Frontmatter Fields by File Type
|
|
297
|
+
|
|
298
|
+
**assignment.md:** id, slug, title, status, priority, created, updated, assignee, externalIds, dependsOn, blockedReason, workspace (repository, worktreePath, branch, parentBranch), tags
|
|
299
|
+
|
|
300
|
+
**plan.md:** assignment, status (draft/approved/in_progress/completed), created, updated
|
|
301
|
+
|
|
302
|
+
**handoff.md:** assignment, updated, handoffCount
|
|
303
|
+
|
|
304
|
+
**decision-record.md:** assignment, updated, decisionCount
|
|
305
|
+
|
|
306
|
+
**mission.md:** id, slug, title, archived, archivedAt, archivedReason, created, updated, externalIds, tags
|
|
307
|
+
|
|
308
|
+
**manifest.md:** version, mission, generated
|
|
309
|
+
|
|
310
|
+
**_status.md:** mission, generated, status, progress (total/completed/in_progress/blocked/pending/review/failed), needsAttention (blockedCount/failedCount/unansweredQuestions)
|
|
311
|
+
|
|
312
|
+
### Conventions
|
|
313
|
+
- **Timestamps:** RFC 3339 / ISO 8601 with UTC: `2026-03-18T14:30:00Z`
|
|
314
|
+
- **Paths:** Absolute expanded form in YAML (never `~`), relative in markdown links
|
|
315
|
+
- **Slugs:** Lowercase, hyphen-separated, match folder names
|
|
316
|
+
- **Protocol version:** `"1.0"` (string, not number)
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Setup Walkthrough
|
|
321
|
+
|
|
322
|
+
### First-Time Setup
|
|
323
|
+
```bash
|
|
324
|
+
# 1. Run guided setup
|
|
325
|
+
npx syntaur@latest setup
|
|
326
|
+
|
|
327
|
+
# 2. Create your first mission
|
|
328
|
+
syntaur create-mission "My First Mission"
|
|
329
|
+
|
|
330
|
+
# 3. Create assignments
|
|
331
|
+
syntaur create-assignment "Design the schema" --mission my-first-mission --priority high
|
|
332
|
+
syntaur create-assignment "Implement the API" --mission my-first-mission --depends-on design-the-schema
|
|
333
|
+
|
|
334
|
+
# 4. Start the dashboard
|
|
335
|
+
syntaur dashboard
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Agent Workflow
|
|
339
|
+
```bash
|
|
340
|
+
# In Claude Code, use skills:
|
|
341
|
+
/grab-assignment my-first-mission # Claim a pending assignment
|
|
342
|
+
/plan-assignment # Write implementation plan
|
|
343
|
+
# ... do the work ...
|
|
344
|
+
/complete-assignment # Handoff and complete
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Context File (.syntaur/context.json)
|
|
350
|
+
|
|
351
|
+
Created by `/grab-assignment` in the current working directory. Contains:
|
|
352
|
+
```json
|
|
353
|
+
{
|
|
354
|
+
"missionSlug": "my-first-mission",
|
|
355
|
+
"assignmentSlug": "design-the-schema",
|
|
356
|
+
"missionDir": "/Users/you/.syntaur/missions/my-first-mission",
|
|
357
|
+
"assignmentDir": "/Users/you/.syntaur/missions/my-first-mission/assignments/design-the-schema",
|
|
358
|
+
"workspaceRoot": "/Users/you/projects/my-app",
|
|
359
|
+
"title": "Design the schema",
|
|
360
|
+
"branch": "feature/design-the-schema",
|
|
361
|
+
"grabbedAt": "2026-03-18T14:30:00Z",
|
|
362
|
+
"sessionId": "uuid-v4"
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Read by `/plan-assignment`, `/complete-assignment`, and the write boundary hook to determine what the current agent is allowed to do.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Common Questions
|
|
371
|
+
|
|
372
|
+
**Q: How do I see what assignments are available?**
|
|
373
|
+
A: Use `/grab-assignment <mission-slug>` — it lists pending assignments. Or check the dashboard, or read `_index-assignments.md`.
|
|
374
|
+
|
|
375
|
+
**Q: Can two agents work on the same assignment?**
|
|
376
|
+
A: No. Single-writer guarantee — one agent per assignment folder. Use separate assignments for parallel work.
|
|
377
|
+
|
|
378
|
+
**Q: What if I need to ask the human a question?**
|
|
379
|
+
A: Add it to the Q&A section of assignment.md. Do NOT set status to `blocked` for questions — `blocked` is for runtime obstacles only.
|
|
380
|
+
|
|
381
|
+
**Q: How do indexes get updated?**
|
|
382
|
+
A: Derived files are rebuilt by tooling. They are projections of assignment frontmatter. When divergence occurs, re-run rebuild.
|
|
383
|
+
|
|
384
|
+
**Q: Can I use Syntaur without Claude Code?**
|
|
385
|
+
A: Yes. Run `syntaur setup-adapter <framework>` for Cursor, Codex, or OpenCode. Any tool that reads/writes markdown can participate.
|
|
386
|
+
|
|
387
|
+
**Q: Where is state stored?**
|
|
388
|
+
A: Assignment frontmatter YAML is the single source of truth. Agent sessions are in SQLite at `~/.syntaur/syntaur.db`. Everything else is markdown files.
|
|
389
|
+
|
|
390
|
+
**Q: How do dependencies work?**
|
|
391
|
+
A: `dependsOn` lists assignment slugs. An assignment with pending status and unmet dependencies cannot transition to `in_progress` until all dependencies are `completed`.
|
|
392
|
+
|
|
393
|
+
When in doubt about any detail, read the source files listed at the top of this prompt. The codebase is always the ground truth.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: track-server
|
|
3
|
+
description: Register, refresh, or remove a tmux session for server tracking in the Syntaur dashboard
|
|
4
|
+
arguments:
|
|
5
|
+
- name: session
|
|
6
|
+
description: "Tmux session name to track (or --refresh/--remove/--list flags)"
|
|
7
|
+
required: false
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /track-server
|
|
11
|
+
|
|
12
|
+
Track a tmux session so its dev servers appear in the Syntaur dashboard.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
- `/track-server <session-name>` — Register a session and scan it
|
|
17
|
+
- `/track-server --refresh [session-name]` — Refresh one or all sessions
|
|
18
|
+
- `/track-server --remove <session-name>` — Stop tracking a session
|
|
19
|
+
- `/track-server --list` — List all tracked sessions
|
|
20
|
+
|
|
21
|
+
## Instructions
|
|
22
|
+
|
|
23
|
+
When the user runs this command, follow these steps based on the argument:
|
|
24
|
+
|
|
25
|
+
### Register (default — argument is a session name)
|
|
26
|
+
|
|
27
|
+
1. Verify the tmux session exists: run `tmux has-session -t <name>` via Bash
|
|
28
|
+
2. If it doesn't exist, tell the user and list available sessions with `tmux list-sessions -F '#{session_name}'`
|
|
29
|
+
3. Create the registration file at `~/.syntaur/servers/<sanitized-name>.md`:
|
|
30
|
+
- Sanitize the name: replace any character that isn't alphanumeric, hyphen, or underscore with a hyphen
|
|
31
|
+
- Write this content:
|
|
32
|
+
```
|
|
33
|
+
---
|
|
34
|
+
session: <original-name>
|
|
35
|
+
registered: <ISO timestamp>
|
|
36
|
+
last_refreshed: <ISO timestamp>
|
|
37
|
+
---
|
|
38
|
+
```
|
|
39
|
+
4. Tell the user the session is now tracked and they can view it at the `/servers` page in the dashboard
|
|
40
|
+
|
|
41
|
+
### --refresh [session-name]
|
|
42
|
+
|
|
43
|
+
1. If a session name is given, update its `last_refreshed` timestamp in `~/.syntaur/servers/<name>.md`
|
|
44
|
+
2. If no session name, update all `.md` files in `~/.syntaur/servers/`
|
|
45
|
+
3. Tell the user to check the dashboard for updated scan data
|
|
46
|
+
|
|
47
|
+
### --remove <session-name>
|
|
48
|
+
|
|
49
|
+
1. Delete the file `~/.syntaur/servers/<sanitized-name>.md`
|
|
50
|
+
2. Confirm removal to the user
|
|
51
|
+
|
|
52
|
+
### --list
|
|
53
|
+
|
|
54
|
+
1. List all `.md` files in `~/.syntaur/servers/`
|
|
55
|
+
2. For each, read the `session` field from frontmatter and display it
|
|
56
|
+
3. If none exist, tell the user no sessions are being tracked
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: track-session
|
|
3
|
+
description: Register this Claude Code session as an agent session in the Syntaur dashboard
|
|
4
|
+
arguments:
|
|
5
|
+
- name: args
|
|
6
|
+
description: "Optional flags: --description, --mission, --assignment"
|
|
7
|
+
required: false
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /track-session
|
|
11
|
+
|
|
12
|
+
Register the current Claude Code session as an agent session in the Syntaur dashboard. Works standalone or linked to a mission/assignment.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
- `/track-session` — register a standalone session
|
|
17
|
+
- `/track-session --description "exploring auth patterns"` — with a description
|
|
18
|
+
- `/track-session --mission <slug> --assignment <slug>` — linked to a mission
|
|
19
|
+
- `/track-session --description "auth work" --mission <slug> --assignment <slug>` — both
|
|
20
|
+
|
|
21
|
+
## Instructions
|
|
22
|
+
|
|
23
|
+
When the user runs this command:
|
|
24
|
+
|
|
25
|
+
### Step 1: Parse arguments
|
|
26
|
+
|
|
27
|
+
Extract optional flags from the argument string:
|
|
28
|
+
- `--description "<text>"` or `--description <text>` — session description
|
|
29
|
+
- `--mission <slug>` — mission to link to
|
|
30
|
+
- `--assignment <slug>` — assignment to link to
|
|
31
|
+
|
|
32
|
+
### Step 2: Run the CLI command
|
|
33
|
+
|
|
34
|
+
Run the track-session CLI command via Bash (use `dangerouslyDisableSandbox: true` since it writes to `~/.syntaur/`):
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
syntaur track-session --agent claude --path $(pwd) [--description "<text>"] [--mission <slug>] [--assignment <slug>]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Step 3: Parse the session ID
|
|
41
|
+
|
|
42
|
+
The CLI output will be one of:
|
|
43
|
+
- `Registered standalone agent session <sessionId>.`
|
|
44
|
+
- `Registered agent session <sessionId> for <assignment> in <mission>.`
|
|
45
|
+
|
|
46
|
+
Extract the session ID from the output.
|
|
47
|
+
|
|
48
|
+
### Step 4: Write context file
|
|
49
|
+
|
|
50
|
+
Write the session ID to `.syntaur/context.json` so the SessionEnd hook can mark it stopped when this conversation ends:
|
|
51
|
+
|
|
52
|
+
- If `.syntaur/context.json` already exists, read it and add `"sessionId": "<id>"` to the existing JSON
|
|
53
|
+
- If it doesn't exist, create the `.syntaur/` directory and write:
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"sessionId": "<id>"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Step 5: Confirm
|
|
61
|
+
|
|
62
|
+
Tell the user:
|
|
63
|
+
- The session was registered (include the short session ID)
|
|
64
|
+
- It will be auto-stopped when this conversation ends
|
|
65
|
+
- If linked to a mission, mention which mission/assignment
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Syntaur Write Boundary Enforcement Hook
|
|
3
|
+
# PreToolUse hook that validates Edit/Write/MultiEdit targets against assignment boundaries.
|
|
4
|
+
# Reads JSON from stdin, outputs JSON to stdout. Always exits 0.
|
|
5
|
+
|
|
6
|
+
# --- Safety: never fail due to hook errors ---
|
|
7
|
+
allow_and_exit() {
|
|
8
|
+
echo '{}'
|
|
9
|
+
exit 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# --- Step 1: Check for jq ---
|
|
13
|
+
if ! command -v jq &>/dev/null; then
|
|
14
|
+
# Cannot parse JSON without jq; allow all operations
|
|
15
|
+
echo '{"systemMessage": "Syntaur boundary hook: jq not found, skipping enforcement"}'
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# --- Step 2: Read stdin ---
|
|
20
|
+
INPUT=$(cat)
|
|
21
|
+
if [ -z "$INPUT" ]; then
|
|
22
|
+
allow_and_exit
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# --- Step 3: Extract tool name ---
|
|
26
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
27
|
+
if [ -z "$TOOL_NAME" ]; then
|
|
28
|
+
allow_and_exit
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# --- Step 4: Only check file-writing tools ---
|
|
32
|
+
case "$TOOL_NAME" in
|
|
33
|
+
Edit|Write|MultiEdit)
|
|
34
|
+
;;
|
|
35
|
+
*)
|
|
36
|
+
allow_and_exit
|
|
37
|
+
;;
|
|
38
|
+
esac
|
|
39
|
+
|
|
40
|
+
# --- Step 5: Extract file path from tool input ---
|
|
41
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
42
|
+
if [ -z "$FILE_PATH" ]; then
|
|
43
|
+
# Cannot determine file path; allow (defensive)
|
|
44
|
+
allow_and_exit
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# --- Step 6: Resolve to absolute path ---
|
|
48
|
+
# If path is relative, make it absolute relative to cwd
|
|
49
|
+
if [[ "$FILE_PATH" != /* ]]; then
|
|
50
|
+
FILE_PATH="$(pwd)/$FILE_PATH"
|
|
51
|
+
fi
|
|
52
|
+
# Normalize path (resolve .. and . components)
|
|
53
|
+
FILE_PATH=$(cd "$(dirname "$FILE_PATH")" 2>/dev/null && echo "$(pwd)/$(basename "$FILE_PATH")") || FILE_PATH=""
|
|
54
|
+
if [ -z "$FILE_PATH" ]; then
|
|
55
|
+
allow_and_exit
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# --- Step 7: Check for context file ---
|
|
59
|
+
CONTEXT_FILE=".syntaur/context.json"
|
|
60
|
+
if [ ! -f "$CONTEXT_FILE" ]; then
|
|
61
|
+
# No active assignment; allow all writes
|
|
62
|
+
allow_and_exit
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# --- Step 8: Read context ---
|
|
66
|
+
ASSIGNMENT_DIR=$(jq -r '.assignmentDir // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
67
|
+
MISSION_DIR=$(jq -r '.missionDir // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
68
|
+
WORKSPACE_ROOT=$(jq -r '.workspaceRoot // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
69
|
+
|
|
70
|
+
if [ -z "$ASSIGNMENT_DIR" ] || [ -z "$MISSION_DIR" ]; then
|
|
71
|
+
# Malformed context file; allow (defensive)
|
|
72
|
+
allow_and_exit
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# --- Step 9: Expand ~ in paths ---
|
|
76
|
+
ASSIGNMENT_DIR="${ASSIGNMENT_DIR/#\~/$HOME}"
|
|
77
|
+
MISSION_DIR="${MISSION_DIR/#\~/$HOME}"
|
|
78
|
+
if [ -n "$WORKSPACE_ROOT" ] && [ "$WORKSPACE_ROOT" != "null" ]; then
|
|
79
|
+
WORKSPACE_ROOT="${WORKSPACE_ROOT/#\~/$HOME}"
|
|
80
|
+
else
|
|
81
|
+
WORKSPACE_ROOT=""
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# --- Step 10: Check allowed paths ---
|
|
85
|
+
|
|
86
|
+
# Allow: files inside the assignment directory
|
|
87
|
+
if [[ "$FILE_PATH" == "$ASSIGNMENT_DIR"/* ]]; then
|
|
88
|
+
allow_and_exit
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Allow: files in mission resources/ directory (but NOT derived _index.md)
|
|
92
|
+
if [[ "$FILE_PATH" == "$MISSION_DIR/resources/"* ]]; then
|
|
93
|
+
BASENAME=$(basename "$FILE_PATH")
|
|
94
|
+
if [[ "$BASENAME" == _* ]]; then
|
|
95
|
+
# Derived file (e.g., _index.md) -- fall through to block
|
|
96
|
+
:
|
|
97
|
+
else
|
|
98
|
+
allow_and_exit
|
|
99
|
+
fi
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Allow: files in mission memories/ directory (but NOT derived _index.md)
|
|
103
|
+
if [[ "$FILE_PATH" == "$MISSION_DIR/memories/"* ]]; then
|
|
104
|
+
BASENAME=$(basename "$FILE_PATH")
|
|
105
|
+
if [[ "$BASENAME" == _* ]]; then
|
|
106
|
+
# Derived file (e.g., _index.md) -- fall through to block
|
|
107
|
+
:
|
|
108
|
+
else
|
|
109
|
+
allow_and_exit
|
|
110
|
+
fi
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Allow: the context file itself
|
|
114
|
+
CONTEXT_ABS="$(cd "$(dirname "$CONTEXT_FILE")" 2>/dev/null && echo "$(pwd)/$(basename "$CONTEXT_FILE")")"
|
|
115
|
+
if [ "$FILE_PATH" = "$CONTEXT_ABS" ]; then
|
|
116
|
+
allow_and_exit
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Allow: files inside workspace root (if set)
|
|
120
|
+
if [ -n "$WORKSPACE_ROOT" ] && [[ "$FILE_PATH" == "$WORKSPACE_ROOT"/* ]]; then
|
|
121
|
+
allow_and_exit
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# --- Step 11: Block the write ---
|
|
125
|
+
REASON="Syntaur write boundary violation: Cannot write to '$FILE_PATH'. Allowed paths: assignment dir ($ASSIGNMENT_DIR), mission resources/memories, workspace ($WORKSPACE_ROOT)."
|
|
126
|
+
|
|
127
|
+
# Escape for JSON
|
|
128
|
+
REASON_ESCAPED=$(echo "$REASON" | jq -Rs '.' 2>/dev/null)
|
|
129
|
+
if [ -z "$REASON_ESCAPED" ]; then
|
|
130
|
+
REASON_ESCAPED="\"Syntaur write boundary violation\""
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
echo "{\"decision\": \"block\", \"reason\": ${REASON_ESCAPED}}"
|
|
134
|
+
|
|
135
|
+
exit 0
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Syntaur protocol hooks",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PostToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "ExitPlanMode",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "prompt",
|
|
10
|
+
"prompt": "You just exited plan mode. If there is an active Syntaur assignment (check for a workspace field in assignment.md), update the assignment's plan.md with the plan you just created and update assignment.md to reflect that planning is complete."
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"SessionEnd": [
|
|
16
|
+
{
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/session-cleanup.sh",
|
|
21
|
+
"timeout": 5
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|