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.
Files changed (99) hide show
  1. package/dashboard/dist/assets/{_basePickBy-CHKX1r7P.js → _basePickBy-BhaCV7eH.js} +1 -1
  2. package/dashboard/dist/assets/{_baseUniq-CTxTc4MS.js → _baseUniq-CDPcqrs2.js} +1 -1
  3. package/dashboard/dist/assets/{arc-BUo5zftd.js → arc-BP0RxLwl.js} +1 -1
  4. package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-CrJLm-P0.js → architectureDiagram-2XIMDMQ5-BDzvaeJp.js} +1 -1
  5. package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-BK60lBBJ.js → blockDiagram-WCTKOSBZ-ZeL9mROo.js} +1 -1
  6. package/dashboard/dist/assets/{c4Diagram-IC4MRINW-C7oJEvA0.js → c4Diagram-IC4MRINW-7S5bvFLp.js} +1 -1
  7. package/dashboard/dist/assets/channel-CcB_wcgb.js +1 -0
  8. package/dashboard/dist/assets/{chunk-4BX2VUAB-CjUPlzHz.js → chunk-4BX2VUAB-Ca7R4nv5.js} +1 -1
  9. package/dashboard/dist/assets/{chunk-55IACEB6-6HmWguiO.js → chunk-55IACEB6-flEv13FB.js} +1 -1
  10. package/dashboard/dist/assets/{chunk-FMBD7UC4-CLuJnd1b.js → chunk-FMBD7UC4-CfcYWBM6.js} +1 -1
  11. package/dashboard/dist/assets/{chunk-JSJVCQXG-B4d62qWV.js → chunk-JSJVCQXG-Dw4yL0VS.js} +1 -1
  12. package/dashboard/dist/assets/{chunk-KX2RTZJC-AsEKRPq2.js → chunk-KX2RTZJC-B2cDe40G.js} +1 -1
  13. package/dashboard/dist/assets/{chunk-NQ4KR5QH-DQhHHvwY.js → chunk-NQ4KR5QH-LZVm0IWg.js} +1 -1
  14. package/dashboard/dist/assets/{chunk-QZHKN3VN-Ds1TtI3E.js → chunk-QZHKN3VN-Dg0EeHNI.js} +1 -1
  15. package/dashboard/dist/assets/{chunk-WL4C6EOR-C7jE3-cR.js → chunk-WL4C6EOR-v3rXNwXc.js} +1 -1
  16. package/dashboard/dist/assets/classDiagram-VBA2DB6C-BJr38z2g.js +1 -0
  17. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BJr38z2g.js +1 -0
  18. package/dashboard/dist/assets/clone-Cfs2GUGt.js +1 -0
  19. package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-C9ka5v1m.js → cose-bilkent-S5V4N54A-D-3JzLoS.js} +1 -1
  20. package/dashboard/dist/assets/{dagre-KLK3FWXG-BbgPQBKy.js → dagre-KLK3FWXG-d_mbczhU.js} +1 -1
  21. package/dashboard/dist/assets/{diagram-E7M64L7V-DpdeZFD4.js → diagram-E7M64L7V-BUyAp8pW.js} +1 -1
  22. package/dashboard/dist/assets/{diagram-IFDJBPK2-FlHLQzOV.js → diagram-IFDJBPK2-C8doXcyQ.js} +1 -1
  23. package/dashboard/dist/assets/{diagram-P4PSJMXO-B22NkEF_.js → diagram-P4PSJMXO-BUSmHa55.js} +1 -1
  24. package/dashboard/dist/assets/{erDiagram-INFDFZHY-zSqmtDid.js → erDiagram-INFDFZHY-Bn5_0LPU.js} +1 -1
  25. package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-BP_0XmVV.js → flowDiagram-PKNHOUZH-CnEjerQM.js} +1 -1
  26. package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-8uRyYgZV.js → ganttDiagram-A5KZAMGK-CL94fbyy.js} +1 -1
  27. package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-JFqg8sv4.js → gitGraphDiagram-K3NZZRJ6-4i_PeG8V.js} +1 -1
  28. package/dashboard/dist/assets/{graph-a-PAH599.js → graph-BtoFhoAd.js} +1 -1
  29. package/dashboard/dist/assets/index-DZUGYrvE.css +1 -0
  30. package/dashboard/dist/assets/index-Dv_-SxuL.js +481 -0
  31. package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-C3kq7Nbv.js → infoDiagram-LFFYTUFH-CdUsuNgZ.js} +1 -1
  32. package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-Kqi4EZ-n.js → ishikawaDiagram-PHBUUO56-BjggRlUx.js} +1 -1
  33. package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-CTfv0Wcr.js → journeyDiagram-4ABVD52K-V4AgexlR.js} +1 -1
  34. package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-Dmx0lgvR.js → kanban-definition-K7BYSVSG-ChlylQRf.js} +1 -1
  35. package/dashboard/dist/assets/{layout-KKRbT2Od.js → layout-DLcz9AmA.js} +1 -1
  36. package/dashboard/dist/assets/{linear-5egaBiw7.js → linear-l2xnSHze.js} +1 -1
  37. package/dashboard/dist/assets/{mermaid.core-C9pF_oFQ.js → mermaid.core-DKO1ytRW.js} +4 -4
  38. package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-C7HXYEXt.js → mindmap-definition-YRQLILUH-DTmTPHrT.js} +1 -1
  39. package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-DkdZm-YP.js → pieDiagram-SKSYHLDU-CwK80y8Y.js} +1 -1
  40. package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-DkcRJs5F.js → quadrantDiagram-337W2JSQ-Be1xqW_w.js} +1 -1
  41. package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-BaTDVYTl.js → requirementDiagram-Z7DCOOCP-JcspXCs0.js} +1 -1
  42. package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-DvPLbGV5.js → sankeyDiagram-WA2Y5GQK-nJb1BInq.js} +1 -1
  43. package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-DQoZ2xMK.js → sequenceDiagram-2WXFIKYE-DUrclEgA.js} +1 -1
  44. package/dashboard/dist/assets/{stateDiagram-RAJIS63D-CS4l0OjM.js → stateDiagram-RAJIS63D-CjinnNtF.js} +1 -1
  45. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-yfclw-nM.js +1 -0
  46. package/dashboard/dist/assets/{timeline-definition-YZTLITO2-aC0iCFCW.js → timeline-definition-YZTLITO2-kM-oVLNz.js} +1 -1
  47. package/dashboard/dist/assets/{treemap-KZPCXAKY-Ie-PFjgx.js → treemap-KZPCXAKY-CYziFlrQ.js} +1 -1
  48. package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-CJN3ExTQ.js → vennDiagram-LZ73GAT5-DX0DbxBN.js} +1 -1
  49. package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-DSiDu1CN.js → xychartDiagram-JWTSCODW-BGqM42ZM.js} +1 -1
  50. package/dashboard/dist/index.html +2 -2
  51. package/dist/dashboard/server.d.ts +5 -0
  52. package/dist/dashboard/server.js +2185 -609
  53. package/dist/dashboard/server.js.map +1 -1
  54. package/dist/index.js +2596 -959
  55. package/dist/index.js.map +1 -1
  56. package/examples/playbooks/keep-records-updated.md +14 -8
  57. package/examples/playbooks/read-before-plan.md +8 -5
  58. package/examples/sample-project/_status.md +1 -1
  59. package/examples/sample-project/assignments/design-auth-schema/assignment.md +4 -17
  60. package/examples/sample-project/assignments/design-auth-schema/comments.md +26 -0
  61. package/examples/sample-project/assignments/design-auth-schema/progress.md +20 -0
  62. package/examples/sample-project/assignments/implement-jwt-middleware/assignment.md +4 -17
  63. package/examples/sample-project/assignments/implement-jwt-middleware/comments.md +17 -0
  64. package/examples/sample-project/assignments/implement-jwt-middleware/progress.md +20 -0
  65. package/examples/sample-project/assignments/write-auth-tests/assignment.md +4 -8
  66. package/examples/sample-project/assignments/write-auth-tests/comments.md +10 -0
  67. package/examples/sample-project/assignments/write-auth-tests/progress.md +10 -0
  68. package/package.json +1 -1
  69. package/platforms/claude-code/.claude-plugin/plugin.json +5 -1
  70. package/platforms/claude-code/agents/syntaur-expert.md +46 -15
  71. package/platforms/claude-code/commands/track-session/track-session.md +43 -18
  72. package/platforms/claude-code/hooks/hooks.json +11 -0
  73. package/platforms/claude-code/hooks/session-cleanup.sh +13 -23
  74. package/platforms/claude-code/hooks/session-start.sh +80 -0
  75. package/platforms/claude-code/hooks/statusline.sh +110 -0
  76. package/platforms/claude-code/references/file-ownership.md +15 -3
  77. package/platforms/claude-code/references/protocol-summary.md +19 -5
  78. package/platforms/claude-code/skills/complete-assignment/SKILL.md +14 -0
  79. package/platforms/claude-code/skills/create-assignment/SKILL.md +12 -10
  80. package/platforms/claude-code/skills/grab-assignment/SKILL.md +30 -15
  81. package/platforms/claude-code/skills/plan-assignment/SKILL.md +16 -8
  82. package/platforms/claude-code/skills/syntaur-protocol/SKILL.md +21 -11
  83. package/platforms/codex/.codex-plugin/plugin.json +1 -1
  84. package/platforms/codex/agents/syntaur-operator.md +39 -25
  85. package/platforms/codex/references/file-ownership.md +14 -3
  86. package/platforms/codex/references/protocol-summary.md +19 -5
  87. package/platforms/codex/scripts/resolve-session.sh +49 -0
  88. package/platforms/codex/skills/complete-assignment/SKILL.md +1 -0
  89. package/platforms/codex/skills/create-assignment/SKILL.md +13 -8
  90. package/platforms/codex/skills/grab-assignment/SKILL.md +7 -5
  91. package/platforms/codex/skills/plan-assignment/SKILL.md +8 -4
  92. package/platforms/codex/skills/syntaur-protocol/SKILL.md +26 -13
  93. package/dashboard/dist/assets/channel-DdltvFFH.js +0 -1
  94. package/dashboard/dist/assets/classDiagram-VBA2DB6C-BHqdFE-8.js +0 -1
  95. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BHqdFE-8.js +0 -1
  96. package/dashboard/dist/assets/clone-CBJOOeOm.js +0 -1
  97. package/dashboard/dist/assets/index-CoVCLSh2.css +0 -1
  98. package/dashboard/dist/assets/index-yyAIuzrP.js +0 -471
  99. 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
- PORT=$(cat "$HOME/.syntaur/dashboard-port" 2>/dev/null || echo "4800")
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
- # Can only auto-register if we have project and assignment context
42
- if [ -z "$MISSION_SLUG" ] || [ -z "$ASSIGNMENT_SLUG" ]; then
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
- RESPONSE=$(curl -sf -X POST "http://localhost:${PORT}/api/agent-sessions" \
52
- -H "Content-Type: application/json" \
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
- # If registration succeeded, update the context file with the session ID
57
- if [ -n "$RESPONSE" ]; then
58
- jq --arg sid "$SESSION_ID" '. + {sessionId: $sid}' "$CONTEXT_FILE" > "${CONTEXT_FILE}.tmp" 2>/dev/null \
59
- && mv "${CONTEXT_FILE}.tmp" "$CONTEXT_FILE" 2>/dev/null || true
60
- fi
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 6: Mark session as stopped via dashboard API ---
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://localhost:${PORT}/api/agent-sessions/${SESSION_ID}/status" \
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. **One folder per project**, one subfolder per assignment.
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 project+assignment in one step
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
- - `--depends-on` (optional): comma-separated list of assignment slugs this depends on
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 (assignment.md, scratchpad.md, handoff.md, decision-record.md). Note that `plan.md` is NOT scaffolded — plan files are optional and created on demand by `/plan-assignment`.
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, 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?"
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
- Write `.syntaur/context.json` in the current working directory with the assignment context. First ensure the directory exists:
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
- Then write the JSON file with this structure:
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 creating the context file, register this session in the project's agent session log so it appears in the dashboard.
161
+ After merging context, register this session in the dashboard.
146
162
 
147
- 1. Find the current Claude Code session ID by reading from `~/.claude/sessions/`. These are JSON files keyed by PID containing `sessionId`, `cwd`, etc. Find the most recently modified file whose `cwd` matches the current working directory:
148
- ```bash
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
- If you cannot find a matching session file (e.g., no file matches the cwd, or the sessions directory is empty), ask the user to run `/rename <assignment-slug>` to name the current session after the assignment. Then store the assignment slug as the session name in context.json (`"sessionName": "<assignment-slug>"`) instead of `sessionId`. The user can later resume with `claude --resume <assignment-slug>`.
168
+ 2. **Merge `sessionId` and `transcriptPath` back into context.json** (safe even if already present jq merge is idempotent).
154
169
 
155
- 2. Run the track-session command (use `dangerouslyDisableSandbox: true` since it writes to `~/.syntaur/`):
156
- ```bash
157
- syntaur track-session --project <projectSlug> --assignment <assignmentSlug> --agent claude --session-id <claude-session-id> --path $(pwd)
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 any Q&A
50
- 2. Read `<projectDir>/agent.md` -- extract conventions and boundaries
51
- 3. Read `<projectDir>/claude.md` if it exists -- extract Claude-specific instructions
52
- 4. Read `<projectDir>/project.md` -- extract the project goal for broader context
53
-
54
- If the assignment has dependencies (`dependsOn` in frontmatter), read the handoff.md from each dependency's assignment folder for integration context:
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
- - Update the `## Progress` section in `assignment.md` after each meaningful milestone
148
- - The assignment file is a live document it should reflect current state at all times
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`, `agent.md`, `claude.md` -- human-authored, read-only
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. Available commands:
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 `agent.md` and `claude.md` at the project level before starting work
75
- - Add unanswered questions to the Q&A section of assignment.md (do not set status to blocked for questions)
76
- - Commit frequently with messages referencing the assignment slug
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.7",
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"