syntaur 0.2.0 → 0.3.3
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/dashboard/dist/assets/{_basePickBy-CHKX1r7P.js → _basePickBy-BhaCV7eH.js} +1 -1
- package/dashboard/dist/assets/{_baseUniq-CTxTc4MS.js → _baseUniq-CDPcqrs2.js} +1 -1
- package/dashboard/dist/assets/{arc-BUo5zftd.js → arc-BP0RxLwl.js} +1 -1
- package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-CrJLm-P0.js → architectureDiagram-2XIMDMQ5-BDzvaeJp.js} +1 -1
- package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-BK60lBBJ.js → blockDiagram-WCTKOSBZ-ZeL9mROo.js} +1 -1
- package/dashboard/dist/assets/{c4Diagram-IC4MRINW-C7oJEvA0.js → c4Diagram-IC4MRINW-7S5bvFLp.js} +1 -1
- package/dashboard/dist/assets/channel-CcB_wcgb.js +1 -0
- package/dashboard/dist/assets/{chunk-4BX2VUAB-CjUPlzHz.js → chunk-4BX2VUAB-Ca7R4nv5.js} +1 -1
- package/dashboard/dist/assets/{chunk-55IACEB6-6HmWguiO.js → chunk-55IACEB6-flEv13FB.js} +1 -1
- package/dashboard/dist/assets/{chunk-FMBD7UC4-CLuJnd1b.js → chunk-FMBD7UC4-CfcYWBM6.js} +1 -1
- package/dashboard/dist/assets/{chunk-JSJVCQXG-B4d62qWV.js → chunk-JSJVCQXG-Dw4yL0VS.js} +1 -1
- package/dashboard/dist/assets/{chunk-KX2RTZJC-AsEKRPq2.js → chunk-KX2RTZJC-B2cDe40G.js} +1 -1
- package/dashboard/dist/assets/{chunk-NQ4KR5QH-DQhHHvwY.js → chunk-NQ4KR5QH-LZVm0IWg.js} +1 -1
- package/dashboard/dist/assets/{chunk-QZHKN3VN-Ds1TtI3E.js → chunk-QZHKN3VN-Dg0EeHNI.js} +1 -1
- package/dashboard/dist/assets/{chunk-WL4C6EOR-C7jE3-cR.js → chunk-WL4C6EOR-v3rXNwXc.js} +1 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-BJr38z2g.js +1 -0
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BJr38z2g.js +1 -0
- package/dashboard/dist/assets/clone-Cfs2GUGt.js +1 -0
- package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-C9ka5v1m.js → cose-bilkent-S5V4N54A-D-3JzLoS.js} +1 -1
- package/dashboard/dist/assets/{dagre-KLK3FWXG-BbgPQBKy.js → dagre-KLK3FWXG-d_mbczhU.js} +1 -1
- package/dashboard/dist/assets/{diagram-E7M64L7V-DpdeZFD4.js → diagram-E7M64L7V-BUyAp8pW.js} +1 -1
- package/dashboard/dist/assets/{diagram-IFDJBPK2-FlHLQzOV.js → diagram-IFDJBPK2-C8doXcyQ.js} +1 -1
- package/dashboard/dist/assets/{diagram-P4PSJMXO-B22NkEF_.js → diagram-P4PSJMXO-BUSmHa55.js} +1 -1
- package/dashboard/dist/assets/{erDiagram-INFDFZHY-zSqmtDid.js → erDiagram-INFDFZHY-Bn5_0LPU.js} +1 -1
- package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-BP_0XmVV.js → flowDiagram-PKNHOUZH-CnEjerQM.js} +1 -1
- package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-8uRyYgZV.js → ganttDiagram-A5KZAMGK-CL94fbyy.js} +1 -1
- package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-JFqg8sv4.js → gitGraphDiagram-K3NZZRJ6-4i_PeG8V.js} +1 -1
- package/dashboard/dist/assets/{graph-a-PAH599.js → graph-BtoFhoAd.js} +1 -1
- package/dashboard/dist/assets/index-DZUGYrvE.css +1 -0
- package/dashboard/dist/assets/index-Dv_-SxuL.js +481 -0
- package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-C3kq7Nbv.js → infoDiagram-LFFYTUFH-CdUsuNgZ.js} +1 -1
- package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-Kqi4EZ-n.js → ishikawaDiagram-PHBUUO56-BjggRlUx.js} +1 -1
- package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-CTfv0Wcr.js → journeyDiagram-4ABVD52K-V4AgexlR.js} +1 -1
- package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-Dmx0lgvR.js → kanban-definition-K7BYSVSG-ChlylQRf.js} +1 -1
- package/dashboard/dist/assets/{layout-KKRbT2Od.js → layout-DLcz9AmA.js} +1 -1
- package/dashboard/dist/assets/{linear-5egaBiw7.js → linear-l2xnSHze.js} +1 -1
- package/dashboard/dist/assets/{mermaid.core-C9pF_oFQ.js → mermaid.core-DKO1ytRW.js} +4 -4
- package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-C7HXYEXt.js → mindmap-definition-YRQLILUH-DTmTPHrT.js} +1 -1
- package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-DkdZm-YP.js → pieDiagram-SKSYHLDU-CwK80y8Y.js} +1 -1
- package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-DkcRJs5F.js → quadrantDiagram-337W2JSQ-Be1xqW_w.js} +1 -1
- package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-BaTDVYTl.js → requirementDiagram-Z7DCOOCP-JcspXCs0.js} +1 -1
- package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-DvPLbGV5.js → sankeyDiagram-WA2Y5GQK-nJb1BInq.js} +1 -1
- package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-DQoZ2xMK.js → sequenceDiagram-2WXFIKYE-DUrclEgA.js} +1 -1
- package/dashboard/dist/assets/{stateDiagram-RAJIS63D-CS4l0OjM.js → stateDiagram-RAJIS63D-CjinnNtF.js} +1 -1
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-yfclw-nM.js +1 -0
- package/dashboard/dist/assets/{timeline-definition-YZTLITO2-aC0iCFCW.js → timeline-definition-YZTLITO2-kM-oVLNz.js} +1 -1
- package/dashboard/dist/assets/{treemap-KZPCXAKY-Ie-PFjgx.js → treemap-KZPCXAKY-CYziFlrQ.js} +1 -1
- package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-CJN3ExTQ.js → vennDiagram-LZ73GAT5-DX0DbxBN.js} +1 -1
- package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-DSiDu1CN.js → xychartDiagram-JWTSCODW-BGqM42ZM.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/dashboard/server.d.ts +5 -0
- package/dist/dashboard/server.js +2185 -609
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.js +2596 -959
- package/dist/index.js.map +1 -1
- package/examples/playbooks/keep-records-updated.md +14 -8
- package/examples/playbooks/read-before-plan.md +8 -5
- package/examples/sample-project/_status.md +1 -1
- package/examples/sample-project/assignments/design-auth-schema/assignment.md +4 -17
- package/examples/sample-project/assignments/design-auth-schema/comments.md +26 -0
- package/examples/sample-project/assignments/design-auth-schema/progress.md +20 -0
- package/examples/sample-project/assignments/implement-jwt-middleware/assignment.md +4 -17
- package/examples/sample-project/assignments/implement-jwt-middleware/comments.md +17 -0
- package/examples/sample-project/assignments/implement-jwt-middleware/progress.md +20 -0
- package/examples/sample-project/assignments/write-auth-tests/assignment.md +4 -8
- package/examples/sample-project/assignments/write-auth-tests/comments.md +10 -0
- package/examples/sample-project/assignments/write-auth-tests/progress.md +10 -0
- package/package.json +1 -1
- package/platforms/claude-code/.claude-plugin/plugin.json +5 -1
- package/platforms/claude-code/agents/syntaur-expert.md +46 -15
- package/platforms/claude-code/commands/track-session/track-session.md +43 -18
- package/platforms/claude-code/hooks/hooks.json +11 -0
- package/platforms/claude-code/hooks/session-cleanup.sh +13 -23
- package/platforms/claude-code/hooks/session-start.sh +80 -0
- package/platforms/claude-code/hooks/statusline.sh +110 -0
- package/platforms/claude-code/references/file-ownership.md +15 -3
- package/platforms/claude-code/references/protocol-summary.md +19 -5
- package/platforms/claude-code/skills/complete-assignment/SKILL.md +14 -0
- package/platforms/claude-code/skills/create-assignment/SKILL.md +12 -10
- package/platforms/claude-code/skills/grab-assignment/SKILL.md +30 -15
- package/platforms/claude-code/skills/plan-assignment/SKILL.md +16 -8
- package/platforms/claude-code/skills/syntaur-protocol/SKILL.md +21 -11
- package/platforms/codex/.codex-plugin/plugin.json +1 -1
- package/platforms/codex/agents/syntaur-operator.md +39 -25
- package/platforms/codex/references/file-ownership.md +14 -3
- package/platforms/codex/references/protocol-summary.md +19 -5
- package/platforms/codex/scripts/resolve-session.sh +49 -0
- package/platforms/codex/skills/complete-assignment/SKILL.md +1 -0
- package/platforms/codex/skills/create-assignment/SKILL.md +13 -8
- package/platforms/codex/skills/grab-assignment/SKILL.md +7 -5
- package/platforms/codex/skills/plan-assignment/SKILL.md +8 -4
- package/platforms/codex/skills/syntaur-protocol/SKILL.md +26 -13
- package/dashboard/dist/assets/channel-DdltvFFH.js +0 -1
- package/dashboard/dist/assets/classDiagram-VBA2DB6C-BHqdFE-8.js +0 -1
- package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BHqdFE-8.js +0 -1
- package/dashboard/dist/assets/clone-CBJOOeOm.js +0 -1
- package/dashboard/dist/assets/index-CoVCLSh2.css +0 -1
- package/dashboard/dist/assets/index-yyAIuzrP.js +0 -471
- package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-DkBtE1WJ.js +0 -1
|
@@ -34,39 +34,29 @@ SESSION_ID=$(jq -r '.sessionId // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
|
34
34
|
MISSION_SLUG=$(jq -r '.projectSlug // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
35
35
|
ASSIGNMENT_SLUG=$(jq -r '.assignmentSlug // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# --- Step 5: If no session was registered, try to auto-register (requires project+assignment) ---
|
|
37
|
+
# Fall back to the SessionEnd stdin payload if context.json didn't have the id.
|
|
38
|
+
# Claude Code passes session_id on stdin for SessionEnd.
|
|
40
39
|
if [ -z "$SESSION_ID" ]; then
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
exit 0
|
|
44
|
-
fi
|
|
45
|
-
|
|
46
|
-
# Generate a session ID for the log entry
|
|
47
|
-
SESSION_ID=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "ses-$(date +%s)")
|
|
48
|
-
# Lowercase the UUID (uuidgen on macOS outputs uppercase)
|
|
49
|
-
SESSION_ID=$(echo "$SESSION_ID" | tr '[:upper:]' '[:lower:]')
|
|
40
|
+
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
|
41
|
+
fi
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-d "{\"projectSlug\": \"${MISSION_SLUG}\", \"assignmentSlug\": \"${ASSIGNMENT_SLUG}\", \"agent\": \"claude\", \"sessionId\": \"${SESSION_ID}\", \"path\": \"${CWD}\"}" \
|
|
54
|
-
2>/dev/null) || true
|
|
43
|
+
# No real session id available — exit quietly. We never synthesize one.
|
|
44
|
+
[ -z "$SESSION_ID" ] && exit 0
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
# --- Dashboard endpoint resolution (mirror session-start.sh exactly so start
|
|
47
|
+
# and end hooks always target the same host:port) ---
|
|
48
|
+
PORT="${SYNTAUR_DASHBOARD_PORT:-}"
|
|
49
|
+
if [ -z "$PORT" ]; then
|
|
50
|
+
PORT=$(cat "$HOME/.syntaur/dashboard-port" 2>/dev/null || echo "4800")
|
|
61
51
|
fi
|
|
62
52
|
|
|
63
|
-
# --- Step
|
|
53
|
+
# --- Step 5: Mark session as stopped via dashboard API ---
|
|
64
54
|
BODY="{\"status\": \"stopped\"}"
|
|
65
55
|
if [ -n "$MISSION_SLUG" ]; then
|
|
66
56
|
BODY="{\"status\": \"stopped\", \"projectSlug\": \"${MISSION_SLUG}\"}"
|
|
67
57
|
fi
|
|
68
58
|
|
|
69
|
-
curl -sf -X PATCH "http://
|
|
59
|
+
curl -sf --max-time 3 -X PATCH "http://127.0.0.1:${PORT}/api/agent-sessions/${SESSION_ID}/status" \
|
|
70
60
|
-H "Content-Type: application/json" \
|
|
71
61
|
-d "$BODY" \
|
|
72
62
|
-o /dev/null 2>/dev/null || true
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Syntaur SessionStart Hook
|
|
3
|
+
# (1) Merges the real Claude Code session_id + transcript_path into an
|
|
4
|
+
# EXISTING .syntaur/context.json. Never creates context.json — that would
|
|
5
|
+
# break grab-assignment's "context.json implies active assignment" semantic.
|
|
6
|
+
# (2) Pre-registers a minimal row in the dashboard sessions table so
|
|
7
|
+
# SessionEnd's PATCH /status always has a row to target. Best-effort —
|
|
8
|
+
# silently ignores dashboard-unreachable.
|
|
9
|
+
#
|
|
10
|
+
# Reads JSON from stdin per Claude Code SessionStart contract:
|
|
11
|
+
# { "session_id": "...", "transcript_path": "...", "cwd": "...", ... }
|
|
12
|
+
#
|
|
13
|
+
# Always exits 0.
|
|
14
|
+
|
|
15
|
+
set -o pipefail 2>/dev/null || true
|
|
16
|
+
|
|
17
|
+
command -v jq >/dev/null 2>&1 || exit 0
|
|
18
|
+
|
|
19
|
+
INPUT=$(cat)
|
|
20
|
+
[ -z "$INPUT" ] && exit 0
|
|
21
|
+
|
|
22
|
+
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
|
23
|
+
TRANSCRIPT_PATH=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
24
|
+
CWD=$(printf '%s' "$INPUT" | jq -r '.cwd // empty' 2>/dev/null)
|
|
25
|
+
|
|
26
|
+
[ -z "$SESSION_ID" ] && exit 0
|
|
27
|
+
[ -z "$CWD" ] && exit 0
|
|
28
|
+
|
|
29
|
+
CONTEXT_FILE="$CWD/.syntaur/context.json"
|
|
30
|
+
|
|
31
|
+
# REQUIRED invariant: only operate on an EXISTING context file. If the current
|
|
32
|
+
# cwd has no active Syntaur assignment, leave the filesystem untouched.
|
|
33
|
+
[ ! -f "$CONTEXT_FILE" ] && exit 0
|
|
34
|
+
|
|
35
|
+
# --- (1) Merge session fields into context.json.
|
|
36
|
+
# Always replace both sessionId and transcriptPath together. If the incoming
|
|
37
|
+
# transcript_path is empty, explicitly null the stored transcriptPath so a new
|
|
38
|
+
# session never inherits a stale transcript path from the prior session.
|
|
39
|
+
TMP="${CONTEXT_FILE}.tmp.$$"
|
|
40
|
+
jq \
|
|
41
|
+
--arg sid "$SESSION_ID" \
|
|
42
|
+
--arg tp "$TRANSCRIPT_PATH" \
|
|
43
|
+
'. + {sessionId: $sid, transcriptPath: (if ($tp | length) > 0 then $tp else null end)}' \
|
|
44
|
+
"$CONTEXT_FILE" > "$TMP" 2>/dev/null \
|
|
45
|
+
&& mv "$TMP" "$CONTEXT_FILE" 2>/dev/null \
|
|
46
|
+
|| rm -f "$TMP"
|
|
47
|
+
|
|
48
|
+
# --- (2) Best-effort pre-registration in the dashboard.
|
|
49
|
+
# Read project/assignment context if present so the pre-registered row is
|
|
50
|
+
# already linked. Upsert semantics on the server mean this is idempotent with
|
|
51
|
+
# later /track-session or grab-assignment calls.
|
|
52
|
+
MISSION_SLUG=$(jq -r '.projectSlug // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
53
|
+
ASSIGNMENT_SLUG=$(jq -r '.assignmentSlug // empty' "$CONTEXT_FILE" 2>/dev/null)
|
|
54
|
+
|
|
55
|
+
PORT="${SYNTAUR_DASHBOARD_PORT:-}"
|
|
56
|
+
if [ -z "$PORT" ]; then
|
|
57
|
+
PORT=$(cat "$HOME/.syntaur/dashboard-port" 2>/dev/null || echo "4800")
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
BODY=$(jq -cn \
|
|
61
|
+
--arg sid "$SESSION_ID" \
|
|
62
|
+
--arg tp "$TRANSCRIPT_PATH" \
|
|
63
|
+
--arg proj "$MISSION_SLUG" \
|
|
64
|
+
--arg assn "$ASSIGNMENT_SLUG" \
|
|
65
|
+
--arg path "$CWD" \
|
|
66
|
+
'{ agent: "claude", sessionId: $sid, path: $path }
|
|
67
|
+
+ (if ($tp | length) > 0 then {transcriptPath: $tp} else {} end)
|
|
68
|
+
+ (if ($proj | length) > 0 then {projectSlug: $proj} else {} end)
|
|
69
|
+
+ (if ($assn | length) > 0 then {assignmentSlug: $assn} else {} end)' 2>/dev/null)
|
|
70
|
+
|
|
71
|
+
if [ -n "$BODY" ]; then
|
|
72
|
+
# --max-time bounds the hook's wall-clock cost if the dashboard socket
|
|
73
|
+
# accepts but then hangs. The hook itself is registered with timeout: 5.
|
|
74
|
+
curl -sf --max-time 3 -X POST "http://127.0.0.1:${PORT}/api/agent-sessions" \
|
|
75
|
+
-H "Content-Type: application/json" \
|
|
76
|
+
-d "$BODY" \
|
|
77
|
+
-o /dev/null 2>/dev/null || true
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
exit 0
|
|
@@ -0,0 +1,110 @@
|
|
|
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
|
|
@@ -7,8 +7,6 @@ Agents must NEVER modify these files:
|
|
|
7
7
|
| File | Location |
|
|
8
8
|
|------|----------|
|
|
9
9
|
| `project.md` | `<project>/project.md` |
|
|
10
|
-
| `agent.md` | `<project>/agent.md` |
|
|
11
|
-
| `claude.md` | `<project>/claude.md` |
|
|
12
10
|
|
|
13
11
|
## Agent-Writable (YOUR assignment folder ONLY)
|
|
14
12
|
|
|
@@ -18,11 +16,25 @@ You may ONLY write to files inside your assigned assignment folder:
|
|
|
18
16
|
|------|---------|
|
|
19
17
|
| `assignment.md` | Assignment record, source of truth for state (includes `## Todos` checklist) |
|
|
20
18
|
| `plan*.md` | Versioned implementation plans (optional, 0 or more: `plan.md`, `plan-v2.md`, ...) — each linked from a todo in `assignment.md` |
|
|
19
|
+
| `progress.md` | Append-only timestamped progress log (newest first). Replaces the old `## Progress` body section. |
|
|
21
20
|
| `scratchpad.md` | Working notes |
|
|
22
21
|
| `handoff.md` | Append-only handoff log |
|
|
23
22
|
| `decision-record.md` | Append-only decision log |
|
|
24
23
|
|
|
25
|
-
Path pattern: `~/.syntaur/projects/<project>/assignments/<your-assignment>/`
|
|
24
|
+
Path pattern (project-nested): `~/.syntaur/projects/<project>/assignments/<your-assignment>/`
|
|
25
|
+
Path pattern (standalone): `~/.syntaur/assignments/<your-assignment-uuid>/`
|
|
26
|
+
|
|
27
|
+
## CLI-Mediated Shared-Writable
|
|
28
|
+
|
|
29
|
+
Do NOT edit these files directly. Use the listed CLI commands:
|
|
30
|
+
|
|
31
|
+
| File | Mediator |
|
|
32
|
+
|------|----------|
|
|
33
|
+
| `comments.md` (any assignment) | `syntaur comment <slug-or-uuid> "body" [--type question\|note\|feedback] [--reply-to <id>]` |
|
|
34
|
+
| `## Todos` in another assignment's `assignment.md` (cross-assignment request) | `syntaur request <source> <target> "text"` |
|
|
35
|
+
| Question resolution | `PATCH /api/.../comments/:id/resolved` (dashboard) or toggle in dashboard UI |
|
|
36
|
+
|
|
37
|
+
These are bounded exceptions to the single-writer rule for assignment folders — the CLI serializes writes to avoid conflicts.
|
|
26
38
|
|
|
27
39
|
## Shared-Writable (any agent or human)
|
|
28
40
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Syntaur Protocol Summary
|
|
2
2
|
|
|
3
|
+
Protocol version: **2.0**
|
|
4
|
+
|
|
3
5
|
## Directory Structure
|
|
4
6
|
|
|
5
7
|
```
|
|
@@ -13,12 +15,12 @@
|
|
|
13
15
|
_index-plans.md # Derived (read-only)
|
|
14
16
|
_index-decisions.md # Derived (read-only)
|
|
15
17
|
_status.md # Derived (read-only)
|
|
16
|
-
claude.md # Human-authored: Claude-specific instructions (read-only)
|
|
17
|
-
agent.md # Human-authored: universal agent instructions (read-only)
|
|
18
18
|
assignments/
|
|
19
19
|
<assignment-slug>/
|
|
20
20
|
assignment.md # Agent-writable: source of truth for state (includes ## Todos checklist)
|
|
21
21
|
plan*.md # Agent-writable: versioned implementation plans (optional, 0 or more: plan.md, plan-v2.md, ...)
|
|
22
|
+
progress.md # Agent-writable, append-only: timestamped progress log
|
|
23
|
+
comments.md # CLI-mediated: threaded questions/notes/feedback (via `syntaur comment`)
|
|
22
24
|
scratchpad.md # Agent-writable: working notes
|
|
23
25
|
handoff.md # Agent-writable: append-only handoff log
|
|
24
26
|
decision-record.md # Agent-writable: append-only decision log
|
|
@@ -28,6 +30,15 @@
|
|
|
28
30
|
memories/
|
|
29
31
|
_index.md # Derived (read-only)
|
|
30
32
|
<memory-slug>.md # Shared-writable
|
|
33
|
+
assignments/
|
|
34
|
+
<assignment-id>/ # Standalone assignments — folder named by UUID, `project: null`
|
|
35
|
+
assignment.md # Same schema as project-nested, `slug` is display-only
|
|
36
|
+
plan*.md
|
|
37
|
+
progress.md
|
|
38
|
+
comments.md
|
|
39
|
+
scratchpad.md
|
|
40
|
+
handoff.md
|
|
41
|
+
decision-record.md
|
|
31
42
|
playbooks/
|
|
32
43
|
manifest.md # Derived: playbook listing (read-only)
|
|
33
44
|
<slug>.md # User-authored: behavioral rules for agents
|
|
@@ -62,10 +73,13 @@
|
|
|
62
73
|
## Key Rules
|
|
63
74
|
|
|
64
75
|
1. **Assignment frontmatter is the single source of truth** for all assignment state.
|
|
65
|
-
2. **
|
|
76
|
+
2. **Project-nested assignments** live at `projects/<slug>/assignments/<aslug>/` (folder name = slug). **Standalone assignments** live at `assignments/<uuid>/` (folder name = UUID, `project: null`, slug display-only).
|
|
66
77
|
3. **Derived files** (underscore-prefixed) are never edited manually.
|
|
67
78
|
4. **Slugs** are lowercase, hyphen-separated.
|
|
68
|
-
5. **Dependencies** are declared via `dependsOn` in assignment frontmatter.
|
|
79
|
+
5. **Dependencies** are declared via `dependsOn` in assignment frontmatter. Only valid within the same project — standalone assignments cannot declare `dependsOn`.
|
|
69
80
|
6. An assignment cannot transition from `pending` to `in_progress` while any dependency is not `completed`.
|
|
70
81
|
7. **Playbooks** in `~/.syntaur/playbooks/` define behavioral rules agents must follow. Read `manifest.md` for a summary, then read each referenced playbook before starting work.
|
|
71
|
-
8. **Todos** in the `## Todos` section of `assignment.md` are an informal markdown checklist. Items may be simple tasks or link to plan files. When a plan is superseded, mark the old todo: `- [x] ~~Execute [plan](./plan.md)~~ (superseded by plan-v2)` — never delete it.
|
|
82
|
+
8. **Todos** in the `## Todos` section of `assignment.md` are an informal markdown checklist. Items may be simple tasks or link to plan files. When a plan is superseded, mark the old todo: `- [x] ~~Execute [plan](./plan.md)~~ (superseded by plan-v2)` — never delete it. `## Todos` is also the landing spot for cross-assignment requests via `syntaur request`.
|
|
83
|
+
9. **Progress** is appended to `progress.md` as timestamped entries (newest first). Do not add a `## Progress` section to `assignment.md`.
|
|
84
|
+
10. **Comments** are appended to `comments.md` via `syntaur comment <slug> "body" [--type question|note|feedback] [--reply-to <id>]`. Never edit `comments.md` directly. Questions carry a `resolved` flag.
|
|
85
|
+
11. **Cross-assignment work** is requested via `syntaur request <source> <target> "text"` — appends to the target's `## Todos` annotated `(from: <source>)`.
|
|
@@ -51,6 +51,20 @@ If any acceptance criteria are unmet OR any todo is still `- [ ]` and not supers
|
|
|
51
51
|
|
|
52
52
|
If the user says no, stop.
|
|
53
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
|
+
|
|
54
68
|
## Step 3: Write Handoff Entry
|
|
55
69
|
|
|
56
70
|
Read `<assignmentDir>/handoff.md` to see its current content and frontmatter.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-assignment
|
|
3
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>] [--one-off]
|
|
4
|
+
argument-hint: <title> --project <slug> [--priority <level>] [--depends-on <slugs>] [--type <type>] [--one-off]
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Bash
|
|
7
7
|
- Read
|
|
@@ -18,10 +18,11 @@ The user provided: $ARGUMENTS
|
|
|
18
18
|
Parse the arguments:
|
|
19
19
|
- First argument (required): the assignment title (e.g., `"Add login endpoint"`)
|
|
20
20
|
- `--project <slug>` (required unless `--one-off`): the project to add the assignment to
|
|
21
|
-
- `--one-off` (optional): create a standalone
|
|
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
22
|
- `--slug` (optional): override the auto-generated assignment slug
|
|
23
23
|
- `--priority` (optional): `low`, `medium` (default), `high`, or `critical`
|
|
24
|
-
- `--
|
|
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
|
|
25
26
|
- `--dir` (optional): override the default project directory
|
|
26
27
|
|
|
27
28
|
If no title was provided, ask the user what the assignment should be called.
|
|
@@ -35,13 +36,13 @@ If there is no active context and no project flag, ask the user which project to
|
|
|
35
36
|
Build the command from the parsed arguments. Use `dangerouslyDisableSandbox: true` since the CLI writes to `~/.syntaur/` which is outside the project sandbox.
|
|
36
37
|
|
|
37
38
|
```bash
|
|
38
|
-
syntaur create-assignment "<title>" --project <slug> [--slug <slug>] [--priority <level>] [--depends-on <slugs>] [--dir <path>]
|
|
39
|
+
syntaur create-assignment "<title>" --project <slug> [--slug <slug>] [--priority <level>] [--depends-on <slugs>] [--type <type>] [--dir <path>]
|
|
39
40
|
```
|
|
40
41
|
|
|
41
|
-
Or for one-off:
|
|
42
|
+
Or for one-off (standalone at `~/.syntaur/assignments/<uuid>/`):
|
|
42
43
|
|
|
43
44
|
```bash
|
|
44
|
-
syntaur create-assignment "<title>" --one-off [--slug <slug>] [--priority <level>] [--dir <path>]
|
|
45
|
+
syntaur create-assignment "<title>" --one-off [--slug <slug>] [--priority <level>] [--type <type>] [--dir <path>]
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
If the command fails (e.g., project not found, slug collision), report the error and suggest fixes.
|
|
@@ -57,9 +58,10 @@ cat ~/.syntaur/projects/<project-slug>/assignments/<assignment-slug>/assignment.
|
|
|
57
58
|
## Step 3: Guide Next Steps
|
|
58
59
|
|
|
59
60
|
Tell the user:
|
|
60
|
-
- The assignment was created with its slug, priority, and location
|
|
61
|
-
- List the files created
|
|
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`.
|
|
62
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.
|
|
63
65
|
- Or suggest running `/plan-assignment` after grabbing — it creates a plan file and auto-appends a linked todo to `## Todos`.
|
|
64
|
-
- If dependencies were set, note them
|
|
65
|
-
- Suggest running `/grab-assignment <project-slug> <assignment-slug>` to claim and start working on it
|
|
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.
|
|
@@ -27,8 +27,9 @@ Parse the arguments:
|
|
|
27
27
|
## Pre-flight Check
|
|
28
28
|
|
|
29
29
|
1. Check if `.syntaur/context.json` already exists in the current working directory.
|
|
30
|
-
- If it exists
|
|
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
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.
|
|
32
33
|
|
|
33
34
|
## Step 1: Discover the Project
|
|
34
35
|
|
|
@@ -113,15 +114,17 @@ workspace:
|
|
|
113
114
|
worktreePath: /absolute/path/to/cwd
|
|
114
115
|
```
|
|
115
116
|
|
|
116
|
-
## Step 5: Create Context File
|
|
117
|
+
## Step 5: Create or Merge Context File
|
|
117
118
|
|
|
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:
|
|
119
122
|
|
|
120
123
|
```bash
|
|
121
124
|
mkdir -p .syntaur
|
|
122
125
|
```
|
|
123
126
|
|
|
124
|
-
|
|
127
|
+
Prepare the assignment payload:
|
|
125
128
|
|
|
126
129
|
```json
|
|
127
130
|
{
|
|
@@ -136,26 +139,38 @@ Then write the JSON file with this structure:
|
|
|
136
139
|
}
|
|
137
140
|
```
|
|
138
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
|
+
|
|
139
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.
|
|
140
156
|
|
|
141
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.
|
|
142
158
|
|
|
143
159
|
## Step 5.5: Register Agent Session
|
|
144
160
|
|
|
145
|
-
After
|
|
161
|
+
After merging context, register this session in the dashboard.
|
|
146
162
|
|
|
147
|
-
1.
|
|
148
|
-
|
|
149
|
-
ls -t ~/.claude/sessions/*.json | head -5
|
|
150
|
-
|
|
151
|
-
Read the most recent file(s) and find the one whose `cwd` matches `$(pwd)`. Extract the `sessionId` field — this is the real Claude Code session ID that can be used with `claude --resume <sessionId>` to resume this exact conversation.
|
|
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."
|
|
152
167
|
|
|
153
|
-
|
|
168
|
+
2. **Merge `sessionId` and `transcriptPath` back into context.json** (safe even if already present — jq merge is idempotent).
|
|
154
169
|
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
syntaur track-session --project <projectSlug> --assignment <assignmentSlug> --agent claude --session-id <
|
|
158
|
-
```
|
|
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
|
+
```
|
|
159
174
|
|
|
160
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.
|
|
161
176
|
|
|
@@ -46,13 +46,20 @@ For each file found, read it and follow its directives. Playbooks may contain ru
|
|
|
46
46
|
|
|
47
47
|
Read the following files to understand the assignment:
|
|
48
48
|
|
|
49
|
-
1. Read `<assignmentDir>/assignment.md` -- extract the objective, acceptance criteria, context section, and
|
|
50
|
-
2. Read `<
|
|
51
|
-
3. Read `<projectDir>/
|
|
52
|
-
4. Read `<projectDir>/
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
1. Read `<assignmentDir>/assignment.md` -- extract the objective, acceptance criteria, context section, and the `## Todos` list
|
|
50
|
+
2. Read `<assignmentDir>/comments.md` if it exists -- inherited questions, notes, and feedback
|
|
51
|
+
3. Read `<projectDir>/project.md` -- extract the project goal for broader context
|
|
52
|
+
4. Read `<projectDir>/manifest.md` -- navigation index for the project
|
|
53
|
+
|
|
54
|
+
Per-project `agent.md` and `claude.md` were removed in v0.2.0. The agent-level
|
|
55
|
+
conventions now live in the repo root `CLAUDE.md` / `AGENTS.md` and in
|
|
56
|
+
`~/.syntaur/playbooks/`, which Step 1.5 already loaded.
|
|
57
|
+
|
|
58
|
+
If the assignment has dependencies (`dependsOn` in frontmatter), read each
|
|
59
|
+
dependency's `handoff.md` and `decision-record.md` for integration context and
|
|
60
|
+
upstream decisions:
|
|
55
61
|
- `<projectDir>/assignments/<dep-slug>/handoff.md`
|
|
62
|
+
- `<projectDir>/assignments/<dep-slug>/decision-record.md`
|
|
56
63
|
|
|
57
64
|
## Step 3: Explore Workspace (if set)
|
|
58
65
|
|
|
@@ -144,5 +151,6 @@ After writing the plan:
|
|
|
144
151
|
|
|
145
152
|
**Remind the agent about recordkeeping during implementation:**
|
|
146
153
|
- Check off acceptance criteria in `assignment.md` as each one is completed, not in a batch at the end
|
|
147
|
-
-
|
|
148
|
-
-
|
|
154
|
+
- Append timestamped milestones to `progress.md` (separate append-only file) — not to `assignment.md`
|
|
155
|
+
- Use `syntaur comment <slug-or-uuid> "body" --type note|question|feedback` to add a comment to `comments.md`
|
|
156
|
+
- `assignment.md` is a live document — keep its status, todos, and acceptance checkboxes reflecting current state at all times
|
|
@@ -12,21 +12,26 @@ You are working within the Syntaur protocol. Follow these rules at all times.
|
|
|
12
12
|
|
|
13
13
|
You MUST respect file ownership boundaries. Violations will be blocked by the PreToolUse hook.
|
|
14
14
|
|
|
15
|
-
### Files you may WRITE:
|
|
15
|
+
### Files you may WRITE directly:
|
|
16
16
|
1. **Your assignment folder** -- only the assignment you are currently working on:
|
|
17
|
-
- `assignment.md`, `plan*.md` (0 or more versioned plan files), `scratchpad.md`, `handoff.md`, `decision-record.md`
|
|
18
|
-
- Path: `~/.syntaur/projects/<project>/assignments/<your-assignment>/`
|
|
17
|
+
- `assignment.md`, `plan*.md` (0 or more versioned plan files), `progress.md`, `scratchpad.md`, `handoff.md`, `decision-record.md`
|
|
18
|
+
- Path (project-nested): `~/.syntaur/projects/<project>/assignments/<your-assignment>/`
|
|
19
|
+
- Path (standalone): `~/.syntaur/assignments/<your-assignment-uuid>/` — folder named by UUID, `project: null`, `slug` display-only
|
|
19
20
|
2. **Shared resources and memories** at the project level:
|
|
20
21
|
- `~/.syntaur/projects/<project>/resources/<slug>.md`
|
|
21
22
|
- `~/.syntaur/projects/<project>/memories/<slug>.md`
|
|
22
23
|
3. **Your workspace** -- source code files within the workspace defined in your assignment's frontmatter (`workspace.worktreePath` or `workspace.repository`)
|
|
23
24
|
4. **Context file** -- `.syntaur/context.json` in the current working directory
|
|
24
25
|
|
|
26
|
+
### Files written only via CLI (never edit directly):
|
|
27
|
+
- `comments.md` (any assignment) — use `syntaur comment <slug-or-uuid> "body" --type question|note|feedback [--reply-to <id>]`. Never edit directly. Questions carry a `resolved` flag toggled in the dashboard.
|
|
28
|
+
- Another assignment's `## Todos` section — use `syntaur request <target> "text"` to append a todo annotated `(from: <source>)`.
|
|
29
|
+
|
|
25
30
|
### Files you must NEVER write:
|
|
26
|
-
1. `project.md
|
|
31
|
+
1. `project.md` -- human-authored, read-only
|
|
27
32
|
2. `manifest.md` -- derived, rebuilt by tooling
|
|
28
33
|
3. Any file prefixed with `_` (`_index-*.md`, `_status.md`) -- derived
|
|
29
|
-
4. Other agents' assignment folders
|
|
34
|
+
4. Other agents' assignment folders (except via the CLI-mediated channels above)
|
|
30
35
|
5. Any files outside your workspace boundary
|
|
31
36
|
|
|
32
37
|
## Current Assignment Context
|
|
@@ -46,7 +51,7 @@ For detailed protocol information, read these files:
|
|
|
46
51
|
|
|
47
52
|
## Lifecycle Commands
|
|
48
53
|
|
|
49
|
-
Use the `syntaur` CLI for state transitions
|
|
54
|
+
Use the `syntaur` CLI for state transitions and coordination:
|
|
50
55
|
- `syntaur assign <slug> --agent <name> --project <project>` -- set assignee
|
|
51
56
|
- `syntaur start <slug> --project <project>` -- pending -> in_progress
|
|
52
57
|
- `syntaur review <slug> --project <project>` -- in_progress -> review
|
|
@@ -54,6 +59,9 @@ Use the `syntaur` CLI for state transitions. Available commands:
|
|
|
54
59
|
- `syntaur block <slug> --project <project> --reason <text>` -- block an assignment
|
|
55
60
|
- `syntaur unblock <slug> --project <project>` -- unblock
|
|
56
61
|
- `syntaur fail <slug> --project <project>` -- mark as failed
|
|
62
|
+
- `syntaur create-assignment "<title>" [--type <type>] [--project <slug> | --one-off]` -- create project-nested or standalone assignment
|
|
63
|
+
- `syntaur comment <slug-or-uuid> "body" --type question|note|feedback [--reply-to <id>]` -- append to `comments.md`
|
|
64
|
+
- `syntaur request <target> "text" [--from <source>]` -- append a todo to another assignment's `## Todos`
|
|
57
65
|
|
|
58
66
|
## Troubleshooting
|
|
59
67
|
|
|
@@ -69,8 +77,10 @@ ls ~/.syntaur/playbooks/*.md 2>/dev/null
|
|
|
69
77
|
|
|
70
78
|
## Conventions
|
|
71
79
|
|
|
72
|
-
- Assignment frontmatter is the single source of truth for state
|
|
73
|
-
- Slugs are lowercase, hyphen-separated
|
|
74
|
-
- Always read `
|
|
75
|
-
-
|
|
76
|
-
-
|
|
80
|
+
- Assignment frontmatter is the single source of truth for state. `project` is the containing project slug (`null` for standalone); `type` is a classification validated against `config.md` `types.definitions` when present.
|
|
81
|
+
- Slugs are lowercase, hyphen-separated. For standalone assignments, the folder is named by UUID; `slug` is display-only.
|
|
82
|
+
- Always read `project.md` at the project level (when project-nested) before starting work.
|
|
83
|
+
- Append timestamped entries to `progress.md` as work lands — do NOT add a `## Progress` section to `assignment.md`.
|
|
84
|
+
- Record questions/notes/feedback via `syntaur comment` — never edit `comments.md` directly. Do NOT set status to blocked for questions.
|
|
85
|
+
- Use `syntaur request` to route work to another assignment.
|
|
86
|
+
- Commit frequently with messages referencing the assignment slug.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "syntaur",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Run Syntaur project and assignment workflows from Codex, including claiming work, planning, completing handoffs, session tracking, and write-boundary enforcement.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Brennen"
|