syntaur 0.3.3 → 0.4.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/README.md +26 -3
- package/dist/index.js +650 -155
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/platforms/claude-code/.claude-plugin/plugin.json +1 -5
- package/platforms/claude-code/agents/syntaur-expert.md +30 -18
- package/platforms/claude-code/commands/complete-assignment/complete-assignment.md +20 -0
- package/platforms/claude-code/commands/create-assignment/create-assignment.md +20 -0
- package/platforms/claude-code/commands/create-project/create-project.md +20 -0
- package/platforms/claude-code/commands/grab-assignment/grab-assignment.md +20 -0
- package/platforms/claude-code/commands/plan-assignment/plan-assignment.md +20 -0
- package/statusline/statusline.sh +133 -0
- package/vendor/syntaur-skills/LICENSE +21 -0
- package/vendor/syntaur-skills/README.md +43 -0
- package/vendor/syntaur-skills/skills/complete-assignment/SKILL.md +146 -0
- package/vendor/syntaur-skills/skills/create-assignment/SKILL.md +72 -0
- package/vendor/syntaur-skills/skills/create-project/SKILL.md +56 -0
- package/vendor/syntaur-skills/skills/grab-assignment/SKILL.md +158 -0
- package/vendor/syntaur-skills/skills/plan-assignment/SKILL.md +137 -0
- package/vendor/syntaur-skills/skills/syntaur-protocol/SKILL.md +119 -0
- package/vendor/syntaur-skills/skills/syntaur-protocol/references/file-ownership.md +67 -0
- package/vendor/syntaur-skills/skills/syntaur-protocol/references/protocol-summary.md +82 -0
- package/platforms/claude-code/hooks/statusline.sh +0 -110
- package/platforms/claude-code/skills/complete-assignment/SKILL.md +0 -155
- package/platforms/claude-code/skills/create-assignment/SKILL.md +0 -67
- package/platforms/claude-code/skills/grab-assignment/SKILL.md +0 -202
- package/platforms/claude-code/skills/plan-assignment/SKILL.md +0 -156
- package/platforms/claude-code/skills/syntaur-protocol/SKILL.md +0 -86
- package/platforms/codex/skills/complete-assignment/SKILL.md +0 -64
- package/platforms/codex/skills/create-assignment/SKILL.md +0 -49
- package/platforms/codex/skills/grab-assignment/SKILL.md +0 -73
- package/platforms/codex/skills/plan-assignment/SKILL.md +0 -61
- package/platforms/codex/skills/syntaur-protocol/SKILL.md +0 -102
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Syntaur Claude Code statusLine.
|
|
3
|
-
#
|
|
4
|
-
# Renders a single line with:
|
|
5
|
-
# <branch> · <worktree-basename> · <assignment> · <sessionId-suffix>
|
|
6
|
-
#
|
|
7
|
-
# Reads JSON from stdin per Claude Code statusLine contract:
|
|
8
|
-
# { "session_id": "...", "cwd": "...", "workspace": { "current_dir": "..." }, ... }
|
|
9
|
-
#
|
|
10
|
-
# Empty segments are omitted. Never fails the terminal — always exits 0.
|
|
11
|
-
|
|
12
|
-
set -o pipefail 2>/dev/null || true
|
|
13
|
-
|
|
14
|
-
INPUT=$(cat)
|
|
15
|
-
|
|
16
|
-
# Degrade cleanly if jq is unavailable.
|
|
17
|
-
if ! command -v jq >/dev/null 2>&1; then
|
|
18
|
-
printf '%s' '(syntaur: jq missing)'
|
|
19
|
-
exit 0
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
SESSION_ID=""
|
|
23
|
-
CWD=""
|
|
24
|
-
|
|
25
|
-
if [ -n "$INPUT" ]; then
|
|
26
|
-
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
|
27
|
-
CWD=$(printf '%s' "$INPUT" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null)
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Fall back to the shell's CWD if the payload omits it.
|
|
31
|
-
[ -z "$CWD" ] && CWD="$PWD"
|
|
32
|
-
|
|
33
|
-
# --- Segment 1: branch ---
|
|
34
|
-
BRANCH=""
|
|
35
|
-
if [ -n "$CWD" ] && [ -d "$CWD" ]; then
|
|
36
|
-
BRANCH=$(git -C "$CWD" rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
37
|
-
if [ "$BRANCH" = "HEAD" ] || [ -z "$BRANCH" ]; then
|
|
38
|
-
SHORT=$(git -C "$CWD" rev-parse --short HEAD 2>/dev/null)
|
|
39
|
-
if [ -n "$SHORT" ]; then
|
|
40
|
-
BRANCH="detached@$SHORT"
|
|
41
|
-
else
|
|
42
|
-
BRANCH=""
|
|
43
|
-
fi
|
|
44
|
-
fi
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
# --- Segment 2: worktree basename ---
|
|
48
|
-
WORKTREE=""
|
|
49
|
-
if [ -n "$CWD" ] && [ -d "$CWD" ]; then
|
|
50
|
-
WT_PATH=$(git -C "$CWD" rev-parse --show-toplevel 2>/dev/null)
|
|
51
|
-
if [ -n "$WT_PATH" ]; then
|
|
52
|
-
WORKTREE=$(basename "$WT_PATH")
|
|
53
|
-
fi
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
# --- Segment 3: active syntaur assignment ---
|
|
57
|
-
ASSIGNMENT=""
|
|
58
|
-
CONTEXT_FILE="$CWD/.syntaur/context.json"
|
|
59
|
-
if [ -f "$CONTEXT_FILE" ]; then
|
|
60
|
-
PROJECT_SLUG=$(jq -r '.projectSlug // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
61
|
-
ASSIGNMENT_SLUG=$(jq -r '.assignmentSlug // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
62
|
-
ASSIGNMENT_DIR=$(jq -r '.assignmentDir // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
63
|
-
|
|
64
|
-
TITLE=""
|
|
65
|
-
if [ -n "$ASSIGNMENT_DIR" ] && [ -f "$ASSIGNMENT_DIR/assignment.md" ]; then
|
|
66
|
-
TITLE=$(awk '/^title:/{sub(/^title:[[:space:]]*"?/,""); sub(/"?[[:space:]]*$/,""); print; exit}' "$ASSIGNMENT_DIR/assignment.md" 2>/dev/null)
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
LABEL=""
|
|
70
|
-
if [ -n "$PROJECT_SLUG" ] && [ -n "$ASSIGNMENT_SLUG" ]; then
|
|
71
|
-
LABEL="$PROJECT_SLUG/$ASSIGNMENT_SLUG"
|
|
72
|
-
elif [ -n "$ASSIGNMENT_SLUG" ]; then
|
|
73
|
-
# Standalone assignment — assignmentSlug is the UUID folder name. Take the
|
|
74
|
-
# first 8 chars for terseness.
|
|
75
|
-
UUID_PREFIX="${ASSIGNMENT_SLUG:0:8}"
|
|
76
|
-
LABEL="standalone/$UUID_PREFIX"
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
|
-
if [ -n "$LABEL" ] && [ -n "$TITLE" ]; then
|
|
80
|
-
ASSIGNMENT="$LABEL — $TITLE"
|
|
81
|
-
elif [ -n "$LABEL" ]; then
|
|
82
|
-
ASSIGNMENT="$LABEL"
|
|
83
|
-
fi
|
|
84
|
-
fi
|
|
85
|
-
|
|
86
|
-
# --- Segment 4: session id suffix ---
|
|
87
|
-
SESSION_SUFFIX=""
|
|
88
|
-
if [ -n "$SESSION_ID" ]; then
|
|
89
|
-
LEN=${#SESSION_ID}
|
|
90
|
-
if [ "$LEN" -gt 8 ]; then
|
|
91
|
-
SESSION_SUFFIX="…${SESSION_ID: -8}"
|
|
92
|
-
else
|
|
93
|
-
SESSION_SUFFIX="$SESSION_ID"
|
|
94
|
-
fi
|
|
95
|
-
fi
|
|
96
|
-
|
|
97
|
-
# --- Join segments with ' · ', suppressing empties. ---
|
|
98
|
-
OUT=""
|
|
99
|
-
for seg in "$BRANCH" "$WORKTREE" "$ASSIGNMENT" "$SESSION_SUFFIX"; do
|
|
100
|
-
if [ -n "$seg" ]; then
|
|
101
|
-
if [ -z "$OUT" ]; then
|
|
102
|
-
OUT="$seg"
|
|
103
|
-
else
|
|
104
|
-
OUT="$OUT · $seg"
|
|
105
|
-
fi
|
|
106
|
-
fi
|
|
107
|
-
done
|
|
108
|
-
|
|
109
|
-
printf '%s' "$OUT"
|
|
110
|
-
exit 0
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: complete-assignment
|
|
3
|
-
description: Write a handoff and transition the current Syntaur assignment to review or completed
|
|
4
|
-
argument-hint: "[--complete]"
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Bash
|
|
7
|
-
- Read
|
|
8
|
-
- Write
|
|
9
|
-
- Edit
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Complete Assignment
|
|
13
|
-
|
|
14
|
-
Write a handoff for your current assignment and transition it to review (or completed).
|
|
15
|
-
|
|
16
|
-
## Arguments
|
|
17
|
-
|
|
18
|
-
User provided: $ARGUMENTS
|
|
19
|
-
|
|
20
|
-
If the user passed `--complete`, transition directly to `completed` instead of `review`. However, `--complete` is ONLY allowed if ALL acceptance criteria are met AND every `## Todos` item is either checked or marked superseded. If any criterion or todo is unresolved, always transition to `review` regardless of the `--complete` flag, and inform the user why.
|
|
21
|
-
|
|
22
|
-
## Step 1: Load Context
|
|
23
|
-
|
|
24
|
-
Read `.syntaur/context.json` from the current working directory.
|
|
25
|
-
|
|
26
|
-
If the file does not exist, tell the user: "No active assignment found. Run `/grab-assignment <project-slug>` first."
|
|
27
|
-
|
|
28
|
-
Extract: `projectSlug`, `assignmentSlug`, `assignmentDir`, `projectDir`.
|
|
29
|
-
|
|
30
|
-
## Step 1.5: Load Playbooks
|
|
31
|
-
|
|
32
|
-
Read all playbook files from `~/.syntaur/playbooks/` — verify your work complies with their rules:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
ls ~/.syntaur/playbooks/*.md 2>/dev/null
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
For each file found, read it and check that your work follows its directives. If any playbook has completion-related rules (e.g., "run tests before done"), follow them before proceeding.
|
|
39
|
-
|
|
40
|
-
## Step 2: Verify Acceptance Criteria and Todos
|
|
41
|
-
|
|
42
|
-
Read `<assignmentDir>/assignment.md` and find the `## Acceptance Criteria` and `## Todos` sections.
|
|
43
|
-
|
|
44
|
-
Review each acceptance criterion (checkbox item) and each todo. For each:
|
|
45
|
-
- If you believe it is met/done, note why (what was implemented, where)
|
|
46
|
-
- If it is NOT met/done, flag it clearly
|
|
47
|
-
|
|
48
|
-
Superseded todos (marked `- [x] ~~...~~ (superseded by ...)`) count as resolved — they do not need to be done again.
|
|
49
|
-
|
|
50
|
-
If any acceptance criteria are unmet OR any todo is still `- [ ]` and not superseded, warn the user: "The following are not yet done: [list]. Do you want to proceed with the handoff anyway?"
|
|
51
|
-
|
|
52
|
-
If the user says no, stop.
|
|
53
|
-
|
|
54
|
-
## Step 2.5: Append a Final Progress Entry
|
|
55
|
-
|
|
56
|
-
Before writing the handoff, append a final entry to `<assignmentDir>/progress.md` summarizing what was completed. The entry goes at the **top** of the body (reverse-chron order) under a new `## <RFC 3339 timestamp>` heading:
|
|
57
|
-
|
|
58
|
-
```markdown
|
|
59
|
-
## <ISO 8601 timestamp>
|
|
60
|
-
|
|
61
|
-
<One paragraph summarizing the final state of work: what was implemented, what verifications passed, and any deliberate scope exclusions.>
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Update `progress.md`'s frontmatter: bump `entryCount` and set `updated` to the current timestamp.
|
|
65
|
-
|
|
66
|
-
Do NOT add a `## Progress` section to `assignment.md` — progress entries live exclusively in `progress.md` as of protocol v2.0.
|
|
67
|
-
|
|
68
|
-
## Step 3: Write Handoff Entry
|
|
69
|
-
|
|
70
|
-
Read `<assignmentDir>/handoff.md` to see its current content and frontmatter.
|
|
71
|
-
|
|
72
|
-
Append a new handoff entry to the markdown body. Read the current `handoffCount` from the frontmatter and use `handoffCount + 1` as the entry number. The entry MUST follow the protocol-specified format from `docs/protocol/file-formats.md`:
|
|
73
|
-
|
|
74
|
-
```markdown
|
|
75
|
-
---
|
|
76
|
-
## Handoff <N>: <ISO 8601 timestamp>
|
|
77
|
-
|
|
78
|
-
**From:** claude
|
|
79
|
-
**To:** human
|
|
80
|
-
**Reason:** <Why this handoff is happening, e.g., "Assignment complete, handing off for review.">
|
|
81
|
-
|
|
82
|
-
### Summary
|
|
83
|
-
<One paragraph summarizing what was accomplished and what remains>
|
|
84
|
-
|
|
85
|
-
### Current State
|
|
86
|
-
- <What is working>
|
|
87
|
-
- <What is not working or partially done>
|
|
88
|
-
- <Acceptance criteria status: N of M met>
|
|
89
|
-
|
|
90
|
-
### Next Steps
|
|
91
|
-
- <Recommended next actions for the reviewer or next agent>
|
|
92
|
-
|
|
93
|
-
### Important Context
|
|
94
|
-
- <Anything the next agent/human needs that is not in the assignment or plan>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Use the Edit tool to append this entry to handoff.md (do not overwrite existing content).
|
|
98
|
-
|
|
99
|
-
Also update the handoff.md frontmatter: set `updated` to the current timestamp and increment the `handoffCount` by 1.
|
|
100
|
-
|
|
101
|
-
## Step 4: Update Checkboxes (Criteria + Todos)
|
|
102
|
-
|
|
103
|
-
In `<assignmentDir>/assignment.md`, update checkboxes in both the `## Acceptance Criteria` and `## Todos` sections to reflect the current state. Use the Edit tool to check off items that were completed (change `- [ ]` to `- [x]`).
|
|
104
|
-
|
|
105
|
-
**Note:** Ideally, these should have been checked off incrementally during implementation. If they are already checked, verify they are still accurate. If some were missed, check them off now with a note in the handoff about which were verified at completion time vs. during development.
|
|
106
|
-
|
|
107
|
-
Do NOT uncheck or rewrite superseded todo lines (those matching `- [x] ~~...~~ (superseded by ...)`) — leave that history intact.
|
|
108
|
-
|
|
109
|
-
## Step 4.5: Close Session
|
|
110
|
-
|
|
111
|
-
Read the context file (`.syntaur/context.json`) to get the `sessionId` and `projectSlug`. Then mark the session as completed via the dashboard API:
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
curl -s -X PATCH "http://localhost:$(cat ~/.syntaur/dashboard-port 2>/dev/null || echo 4800)/api/agent-sessions/<session-id>/status" \
|
|
115
|
-
-H "Content-Type: application/json" \
|
|
116
|
-
-d '{"status": "completed", "projectSlug": "<project-slug>"}'
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
If the API call fails (e.g., dashboard not running), this is non-critical — the session will be reconciled automatically on the next dashboard load.
|
|
120
|
-
|
|
121
|
-
## Step 5: Transition Assignment State
|
|
122
|
-
|
|
123
|
-
If the user passed `--complete`:
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
syntaur complete <assignment-slug> --project <project-slug>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Otherwise, transition to review:
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
syntaur review <assignment-slug> --project <project-slug>
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Use `dangerouslyDisableSandbox: true` since the CLI writes to `~/.syntaur/`.
|
|
136
|
-
|
|
137
|
-
If the command fails, report the error. Common failures:
|
|
138
|
-
- Assignment is not in `in_progress` status (cannot transition)
|
|
139
|
-
- Project not found
|
|
140
|
-
|
|
141
|
-
## Step 6: Clean Up Context
|
|
142
|
-
|
|
143
|
-
Delete the context file:
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
rm .syntaur/context.json
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Step 7: Report to User
|
|
150
|
-
|
|
151
|
-
Summarize:
|
|
152
|
-
- Assignment slug and title
|
|
153
|
-
- New status (review or completed)
|
|
154
|
-
- Number of acceptance criteria met vs total
|
|
155
|
-
- Remind: if transitioned to `review`, a human reviewer will check the work. If any criteria were unmet, they may send it back to `in_progress` via `syntaur start`.
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: create-assignment
|
|
3
|
-
description: Create a new Syntaur assignment within a project (or as a one-off)
|
|
4
|
-
argument-hint: <title> --project <slug> [--priority <level>] [--depends-on <slugs>] [--type <type>] [--one-off]
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Bash
|
|
7
|
-
- Read
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Create Assignment
|
|
11
|
-
|
|
12
|
-
Create a new assignment within a Syntaur project from Claude Code.
|
|
13
|
-
|
|
14
|
-
## Arguments
|
|
15
|
-
|
|
16
|
-
The user provided: $ARGUMENTS
|
|
17
|
-
|
|
18
|
-
Parse the arguments:
|
|
19
|
-
- First argument (required): the assignment title (e.g., `"Add login endpoint"`)
|
|
20
|
-
- `--project <slug>` (required unless `--one-off`): the project to add the assignment to
|
|
21
|
-
- `--one-off` (optional): create a **standalone** assignment at `~/.syntaur/assignments/<uuid>/` with `project: null`. Folder is named by UUID; `slug` is display-only. `--depends-on` is not permitted for standalone assignments.
|
|
22
|
-
- `--slug` (optional): override the auto-generated assignment slug
|
|
23
|
-
- `--priority` (optional): `low`, `medium` (default), `high`, or `critical`
|
|
24
|
-
- `--type` (optional): classification such as `feature`, `bug`, `refactor`, `research`, `chore`. Defaults to `feature`. When `~/.syntaur/config.md` defines `types.definitions`, the CLI validates against that list.
|
|
25
|
-
- `--depends-on` (optional, project-nested only): comma-separated list of assignment slugs this depends on
|
|
26
|
-
- `--dir` (optional): override the default project directory
|
|
27
|
-
|
|
28
|
-
If no title was provided, ask the user what the assignment should be called.
|
|
29
|
-
|
|
30
|
-
If neither `--project` nor `--one-off` was provided, check if there is an active assignment context in `.syntaur/context.json`. If so, default `--project` to that context's `projectSlug` and confirm with the user: "Add this assignment to project `<projectSlug>`?"
|
|
31
|
-
|
|
32
|
-
If there is no active context and no project flag, ask the user which project to add it to, or whether it should be a one-off.
|
|
33
|
-
|
|
34
|
-
## Step 1: Run the CLI
|
|
35
|
-
|
|
36
|
-
Build the command from the parsed arguments. Use `dangerouslyDisableSandbox: true` since the CLI writes to `~/.syntaur/` which is outside the project sandbox.
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
syntaur create-assignment "<title>" --project <slug> [--slug <slug>] [--priority <level>] [--depends-on <slugs>] [--type <type>] [--dir <path>]
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Or for one-off (standalone at `~/.syntaur/assignments/<uuid>/`):
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
syntaur create-assignment "<title>" --one-off [--slug <slug>] [--priority <level>] [--type <type>] [--dir <path>]
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
If the command fails (e.g., project not found, slug collision), report the error and suggest fixes.
|
|
49
|
-
|
|
50
|
-
## Step 2: Read the Created Assignment
|
|
51
|
-
|
|
52
|
-
After successful creation, extract the assignment slug and directory from the CLI output. Read the generated `assignment.md`:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
cat ~/.syntaur/projects/<project-slug>/assignments/<assignment-slug>/assignment.md
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Step 3: Guide Next Steps
|
|
59
|
-
|
|
60
|
-
Tell the user:
|
|
61
|
-
- The assignment was created with its slug, priority, type, and location. For standalone assignments, the location is `~/.syntaur/assignments/<uuid>/` — note the UUID (not slug) is the folder name.
|
|
62
|
-
- List the files created: `assignment.md`, `progress.md`, `comments.md`, `scratchpad.md`, `handoff.md`, `decision-record.md`. `plan.md` is NOT scaffolded — plan files are optional and created on demand by `/plan-assignment`.
|
|
63
|
-
- Remind the user: `progress.md` is where timestamped progress entries go (not `assignment.md`), and `comments.md` is written only via `syntaur comment <slug-or-uuid> "body" --type question|note|feedback`.
|
|
64
|
-
- Suggest they edit `assignment.md` to fill in the objective, acceptance criteria, context, and any initial todos. The `## Todos` section accepts simple tasks or markdown links to plan files.
|
|
65
|
-
- Or suggest running `/plan-assignment` after grabbing — it creates a plan file and auto-appends a linked todo to `## Todos`.
|
|
66
|
-
- If dependencies were set, note them. (Standalone assignments cannot declare dependencies.)
|
|
67
|
-
- Suggest running `/grab-assignment <project-slug> <assignment-slug>` (or `/grab-assignment --id <uuid>` for standalone) to claim and start working on it.
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: grab-assignment
|
|
3
|
-
description: Load a Syntaur assignment into the current working context
|
|
4
|
-
argument-hint: <project-slug> [assignment-slug]
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Bash
|
|
7
|
-
- Read
|
|
8
|
-
- Write
|
|
9
|
-
- Glob
|
|
10
|
-
- Grep
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Grab Assignment
|
|
14
|
-
|
|
15
|
-
Load a Syntaur assignment into the current working context so you can work on it.
|
|
16
|
-
|
|
17
|
-
**Grabbing is non-destructive.** It never fails because of status. An assignment in `pending`, `in_progress`, `blocked`, `review`, `completed`, or `failed` can all be grabbed — grabbing just sets up context (`.syntaur/context.json`), registers the session, and reads the assignment. Only a `pending` assignment will additionally be transitioned to `in_progress`; any other status is left untouched.
|
|
18
|
-
|
|
19
|
-
## Arguments
|
|
20
|
-
|
|
21
|
-
The user provided: $ARGUMENTS
|
|
22
|
-
|
|
23
|
-
Parse the arguments:
|
|
24
|
-
- First argument (required): the project slug (e.g., `build-auth-system`)
|
|
25
|
-
- Second argument (optional): a specific assignment slug to grab. If omitted, you will list the project's assignments and pick one (preferring `pending` when multiple exist).
|
|
26
|
-
|
|
27
|
-
## Pre-flight Check
|
|
28
|
-
|
|
29
|
-
1. Check if `.syntaur/context.json` already exists in the current working directory.
|
|
30
|
-
- If it exists AND contains BOTH `projectSlug` and `assignmentSlug`, read it and warn the user: "You already have an active assignment: `<assignmentSlug>` in project `<projectSlug>`. Grabbing a new assignment will replace this context. Proceed?"
|
|
31
|
-
- If the user says no, stop.
|
|
32
|
-
- If the file exists but only has session fields (`sessionId`, `transcriptPath`) and no project/assignment, do NOT warn — that context was populated by the SessionStart hook and is not an "active assignment" marker. Proceed silently and merge new assignment fields in Step 5.
|
|
33
|
-
|
|
34
|
-
## Step 1: Discover the Project
|
|
35
|
-
|
|
36
|
-
Read the project directory to understand what is available:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
ls ~/.syntaur/projects/<project-slug>/
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Read the project files, starting with the manifest (the protocol-defined entry point):
|
|
43
|
-
- Read `~/.syntaur/projects/<project-slug>/manifest.md` first (root navigation file per protocol spec)
|
|
44
|
-
- Read `~/.syntaur/projects/<project-slug>/project.md` for goal and context
|
|
45
|
-
- Read `~/.syntaur/projects/<project-slug>/agent.md` for agent instructions
|
|
46
|
-
- Read `~/.syntaur/projects/<project-slug>/claude.md` if it exists for Claude-specific instructions
|
|
47
|
-
|
|
48
|
-
Note the `workspace` field in `project.md` frontmatter if present. This indicates which project/codebase grouping the project belongs to. When writing context to `.syntaur/context.json` (Step 5), include `"workspace": "<value>"` if the project has a workspace.
|
|
49
|
-
|
|
50
|
-
## Step 2: Find Assignments
|
|
51
|
-
|
|
52
|
-
List assignment directories:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
ls ~/.syntaur/projects/<project-slug>/assignments/
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
If the user specified an assignment slug as the second argument, verify that directory exists. Its status does **not** matter — grab it regardless. If it doesn't exist, report that and stop.
|
|
59
|
-
|
|
60
|
-
If no specific assignment was requested, read each `assignment.md` frontmatter and present the list with title, priority, and current status. Prefer `pending` assignments when presenting options (they're the most likely default), but show non-terminal assignments too so the user can pick one to resume. Ask the user which to grab unless there is exactly one obvious candidate (single `pending` assignment).
|
|
61
|
-
|
|
62
|
-
## Step 3: Claim the Assignment
|
|
63
|
-
|
|
64
|
-
Read the assignment frontmatter first to learn its current `status`:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
cat ~/.syntaur/projects/<project-slug>/assignments/<assignment-slug>/assignment.md
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Then run the Syntaur CLI to set the assignee. This is safe at any status and does not transition state. Use `dangerouslyDisableSandbox: true` for these bash commands since the CLI writes to `~/.syntaur/` which is outside the project sandbox.
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
syntaur assign <assignment-slug> --agent claude --project <project-slug>
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**Only if the current status is `pending`**, also run `syntaur start` to transition it to `in_progress`:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
syntaur start <assignment-slug> --project <project-slug>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
For any other status (`in_progress`, `blocked`, `review`, `completed`, `failed`), **skip `syntaur start`** — the assignment has already been advanced past pending and grabbing should not rewind it. Tell the user which status the assignment is in and continue with context setup.
|
|
83
|
-
|
|
84
|
-
If `syntaur assign` fails (e.g., project not found, invalid slug), report the error and stop. Do not treat a non-pending status as a failure.
|
|
85
|
-
|
|
86
|
-
## Step 4: Read Assignment Context and Set Workspace
|
|
87
|
-
|
|
88
|
-
You have already read the assignment file in Step 3. Extract from the frontmatter:
|
|
89
|
-
- `title` -- the assignment title
|
|
90
|
-
- `workspace.repository` -- the code repository path (may be null)
|
|
91
|
-
- `workspace.worktreePath` -- the worktree path (may be null)
|
|
92
|
-
- `workspace.branch` -- the branch name (may be null)
|
|
93
|
-
- `dependsOn` -- list of dependency slugs
|
|
94
|
-
- `priority` -- priority level
|
|
95
|
-
|
|
96
|
-
Read the objective, acceptance criteria, and the `## Todos` section (if present) from the markdown body. Active (unchecked) todos indicate outstanding work and may link to plan files to execute.
|
|
97
|
-
|
|
98
|
-
### Auto-load upstream decision records
|
|
99
|
-
|
|
100
|
-
If `dependsOn` is non-empty, for each dependency slug `<dep>`, read:
|
|
101
|
-
- `<projectDir>/assignments/<dep>/handoff.md` (if it exists) for integration context
|
|
102
|
-
- `<projectDir>/assignments/<dep>/decision-record.md` (if it exists) for upstream decisions
|
|
103
|
-
|
|
104
|
-
Surface those upstream decisions in the Step 6 report — downstream work should inherit prior decisions without the user having to ask.
|
|
105
|
-
|
|
106
|
-
### Set workspace if not configured
|
|
107
|
-
|
|
108
|
-
If `workspace.repository` and `workspace.worktreePath` are both null, set them to the current working directory (`$(pwd)`). This is critical because the write boundary hook uses the workspace path to determine which files the agent is allowed to edit. Without it, all code edits outside the assignment directory will be blocked.
|
|
109
|
-
|
|
110
|
-
Use the Edit tool to update the assignment.md frontmatter:
|
|
111
|
-
```yaml
|
|
112
|
-
workspace:
|
|
113
|
-
repository: /absolute/path/to/cwd
|
|
114
|
-
worktreePath: /absolute/path/to/cwd
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Step 5: Create or Merge Context File
|
|
118
|
-
|
|
119
|
-
Merge assignment context into `.syntaur/context.json`. Do NOT overwrite: if the file already exists (e.g., the SessionStart hook populated `sessionId` + `transcriptPath`), preserve those fields.
|
|
120
|
-
|
|
121
|
-
First ensure the directory exists:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
mkdir -p .syntaur
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Prepare the assignment payload:
|
|
128
|
-
|
|
129
|
-
```json
|
|
130
|
-
{
|
|
131
|
-
"projectSlug": "<project-slug>",
|
|
132
|
-
"assignmentSlug": "<assignment-slug>",
|
|
133
|
-
"projectDir": "/Users/<username>/.syntaur/projects/<project-slug>",
|
|
134
|
-
"assignmentDir": "/Users/<username>/.syntaur/projects/<project-slug>/assignments/<assignment-slug>",
|
|
135
|
-
"workspaceRoot": "<workspace.worktreePath if set, else workspace.repository if it is a local path, else current working directory>",
|
|
136
|
-
"title": "<assignment title>",
|
|
137
|
-
"branch": "<workspace.branch or null>",
|
|
138
|
-
"grabbedAt": "<ISO 8601 timestamp>"
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Merge it on top of whatever context.json already contains:
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
if [ -f .syntaur/context.json ]; then
|
|
146
|
-
jq --slurpfile new <(echo "$NEW_CONTEXT_JSON") '. + $new[0]' .syntaur/context.json > .syntaur/context.json.tmp \
|
|
147
|
-
&& mv .syntaur/context.json.tmp .syntaur/context.json
|
|
148
|
-
else
|
|
149
|
-
echo "$NEW_CONTEXT_JSON" > .syntaur/context.json
|
|
150
|
-
fi
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
This preserves any `sessionId` / `transcriptPath` the SessionStart hook wrote, while layering assignment fields on top.
|
|
154
|
-
|
|
155
|
-
Use absolute paths (expand `~` to the actual home directory). Note: `workspace.repository` may be a remote URL (e.g., `https://github.com/...`) -- only use it as `workspaceRoot` if it starts with `/` (local path). If it is a URL, set `workspaceRoot` to the current working directory.
|
|
156
|
-
|
|
157
|
-
**IMPORTANT:** The `workspaceRoot` must NEVER be null when the agent will be writing code. If no workspace was configured, default to the current working directory.
|
|
158
|
-
|
|
159
|
-
## Step 5.5: Register Agent Session
|
|
160
|
-
|
|
161
|
-
After merging context, register this session in the dashboard.
|
|
162
|
-
|
|
163
|
-
1. **Source the real Claude session_id + transcript_path.** In priority order:
|
|
164
|
-
1. If `.syntaur/context.json` already has `sessionId` (SessionStart hook populated it), use that ID and read `transcriptPath` from the same file.
|
|
165
|
-
2. Otherwise, fall back to `~/.claude/sessions/*.json`: `ls -t ~/.claude/sessions/*.json | head -5`, read each, and pick the most recently modified entry whose `cwd` matches `$(pwd)`. Extract `sessionId`. The transcript path for Claude Code lives at `~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl` — construct that path if you need it.
|
|
166
|
-
3. If neither source yields a real ID, DO NOT synthesize one. Abort with: "Could not resolve a real Claude Code session id. Restart the Claude session so the SessionStart hook can populate `.syntaur/context.json`, or run `/rename <assignment-slug>` and retry."
|
|
167
|
-
|
|
168
|
-
2. **Merge `sessionId` and `transcriptPath` back into context.json** (safe even if already present — jq merge is idempotent).
|
|
169
|
-
|
|
170
|
-
3. **Run the track-session CLI** (use `dangerouslyDisableSandbox: true` since it writes to `~/.syntaur/`). Both `--session-id` and real path are required:
|
|
171
|
-
```bash
|
|
172
|
-
syntaur track-session --project <projectSlug> --assignment <assignmentSlug> --agent claude --session-id <real-session-id> --transcript-path <transcript-path> --path $(pwd)
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
3. Update the `.syntaur/context.json` context file to include the session ID. Add `"sessionId": "<claude-session-id>"` to the JSON object you wrote in Step 5.
|
|
176
|
-
|
|
177
|
-
## Step 5.6: Load Playbooks
|
|
178
|
-
|
|
179
|
-
Read all playbook files from `~/.syntaur/playbooks/` and treat their content as active behavioral rules for this assignment:
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
ls ~/.syntaur/playbooks/*.md 2>/dev/null
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
For each `.md` file found, read it and internalize the rules in its body section. These are user-defined behavioral policies that you must follow throughout your work on this assignment. Playbooks take precedence over default conventions when they conflict.
|
|
186
|
-
|
|
187
|
-
If no playbook files exist, skip this step.
|
|
188
|
-
|
|
189
|
-
## Step 6: Report to User
|
|
190
|
-
|
|
191
|
-
Summarize what was done:
|
|
192
|
-
- Which assignment was grabbed
|
|
193
|
-
- Its current status (note if it was already past `pending` — e.g., "already in `review`, status unchanged")
|
|
194
|
-
- The objective (first paragraph from assignment.md body)
|
|
195
|
-
- The acceptance criteria (the checkbox list)
|
|
196
|
-
- Active todos from the `## Todos` section (if any), with links to any referenced plan files
|
|
197
|
-
- The workspace path (if set)
|
|
198
|
-
- Suggest an appropriate next step based on status:
|
|
199
|
-
- `pending` / `in_progress`: `/plan-assignment` to plan implementation
|
|
200
|
-
- `blocked`: investigate the blocker recorded in `blockedReason`
|
|
201
|
-
- `review`: inspect the implementation and help verify acceptance criteria
|
|
202
|
-
- `completed` / `failed`: read the handoff; grab is probably for reference or reopen
|