@scriptgun/workerc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: workerc:handoff
3
+ description: Pause work and write handoff notes for the next session
4
+ allowed-tools:
5
+ - Read
6
+ - Edit
7
+ - Glob
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Pause the current session with structured handoff notes so the next session can resume effectively.
13
+ Different from /workerc:done — this is "paused", not "finished".
14
+ </objective>
15
+
16
+ <process>
17
+
18
+ **Step 1: Find session progress file**
19
+
20
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
21
+
22
+ If none found: print "No active progress file for this session." and STOP.
23
+
24
+ **Step 2: Suggest commit if uncommitted changes**
25
+
26
+ If no `(commit)` log entry and tracked files have uncommitted changes:
27
+ - Print: "Tip: run /workerc:commit first to commit your work-in-progress."
28
+ - Continue anyway — this is a suggestion, not a block.
29
+
30
+ **Step 3: Gather handoff info**
31
+
32
+ Ask user:
33
+ ```
34
+ AskUserQuestion(
35
+ header: "Handoff",
36
+ question: "Any notes for the next session? (blockers, gotchas, what's next)",
37
+ options: [
38
+ { label: "Auto-generate", description: "Summarize from progress log and files" },
39
+ { label: "I'll write notes", description: "I'll describe what to hand off" }
40
+ ],
41
+ multiSelect: false
42
+ )
43
+ ```
44
+
45
+ **If "Auto-generate":**
46
+ - Read the progress file's ## Log and ## Files
47
+ - Read the spec if one exists (line 3)
48
+ - Summarize: what was done (from log), what's left (from spec scope minus done items), any blockers apparent from log
49
+
50
+ **If "I'll write notes":**
51
+ - Wait for user input, use that as the handoff content
52
+
53
+ **Step 4: Write handoff to progress file**
54
+
55
+ Append to the progress file (before ## Files):
56
+ ```
57
+ ## Handoff
58
+ **Status:** Paused on {YYYY-MM-DD HH:MM}
59
+ **Done so far:** {1-2 sentence summary of completed work}
60
+ **Next steps:** {what to do next}
61
+ **Blockers:** {any blockers, or "None"}
62
+ **Notes:** {user notes or auto-generated context}
63
+ ```
64
+
65
+ Add log entry: `- [ ] ({YYYY-MM-DD HH:MM}) (handoff) Session paused`
66
+
67
+ **Step 5: Unclaim session**
68
+
69
+ Update line 2: change session ID to empty `<!-- session: -->`
70
+
71
+ **Step 6: Confirm**
72
+
73
+ Print:
74
+ ```
75
+ Paused: {filename}
76
+ Session unclaimed. Run /workerc:resume to pick this back up.
77
+ ```
78
+
79
+ STOP.
80
+
81
+ </process>
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: workerc:list
3
+ description: List all progress files with status
4
+ allowed-tools:
5
+ - Read
6
+ - Glob
7
+ ---
8
+
9
+ <objective>
10
+ List all progress files with their status.
11
+ </objective>
12
+
13
+ <process>
14
+
15
+ **Step 1: Read all progress files**
16
+
17
+ Read all `.claude/progress/*.md` files.
18
+
19
+ **Step 2: Display**
20
+
21
+ For each file, print one line (check in this order):
22
+ - `[DONE] {filename}: {line 1}` — if line 1 contains "[DONE]"
23
+ - `[ABORTED] {filename}: {line 1}` — if line 1 contains "[ABORTED]"
24
+ - `[ACTIVE] {filename}: {line 1}` — if line 2 has a non-empty session ID (not "pending")
25
+ - `[PAUSED] {filename}: {line 1}` — if file has a `## Handoff` section
26
+ - `[FREE] {filename}: {line 1}` — if line 2 has empty session, "pending", or no session tag
27
+
28
+ Print summary: "X active, Y paused, Z free, W done, V aborted"
29
+
30
+ STOP.
31
+
32
+ </process>
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: workerc:new
3
+ description: Start a new work session with progress file and optional spec
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Edit
8
+ - Glob
9
+ - Bash
10
+ - AskUserQuestion
11
+ ---
12
+
13
+ <objective>
14
+ Start a NEW work session. Always creates a fresh progress file.
15
+ The hook auto-claims "pending" progress files on first source file edit.
16
+ </objective>
17
+
18
+ <process>
19
+
20
+ **Step 1: Spec question**
21
+
22
+ Ask user:
23
+ ```
24
+ AskUserQuestion(
25
+ header: "Spec",
26
+ question: "Do you have a written spec for this work?",
27
+ options: [
28
+ { label: "Yes, I'll give the path", description: "Link existing spec file" },
29
+ { label: "No, create one", description: "I'll describe what I'm building" },
30
+ { label: "No spec needed", description: "Skip straight to work" }
31
+ ],
32
+ multiSelect: false
33
+ )
34
+ ```
35
+
36
+ **If "Yes, I'll give the path":**
37
+ - Ask for the path
38
+ - Validate file exists
39
+ - Store path as SPEC_PATH
40
+
41
+ **If "No, create one":**
42
+ - Ask: "What are you building?" and "What's in scope? What's out?" in a single AskUserQuestion with 2 questions
43
+ - Write spec to `.claude/specs/{slug}.md`:
44
+ ```
45
+ # {Title}
46
+ ## Goal
47
+ {user's description}
48
+ ## Scope
49
+ - In: {in scope items}
50
+ - Out: {out of scope items}
51
+ ## Decisions
52
+ ## Discovered
53
+ ## Rejected
54
+ ```
55
+ - Store path as SPEC_PATH
56
+
57
+ **If "No spec needed":**
58
+ - SPEC_PATH = "None"
59
+
60
+ **Step 2: Create progress file**
61
+
62
+ Ask user:
63
+ ```
64
+ AskUserQuestion(
65
+ header: "Name",
66
+ question: "Short name for this work? (used for filename, e.g. 'auth-refactor')",
67
+ options: [
68
+ { label: "Suggest from spec", description: "Auto-generate from spec/description" }
69
+ ],
70
+ multiSelect: false
71
+ )
72
+ ```
73
+
74
+ Generate slug from name (lowercase, hyphens, max 40 chars).
75
+
76
+ If `.claude/progress/{slug}.md` already exists, append `-2` (or `-3`, etc.) to make it unique.
77
+
78
+ Write `.claude/progress/{slug}.md`:
79
+ ```
80
+ Progress for {name} created on {YYYY-MM-DD}
81
+ <!-- session: pending -->
82
+ <!-- spec: {SPEC_PATH or None} -->
83
+
84
+ ## Log
85
+
86
+ ## Files
87
+ ```
88
+
89
+ The hook will auto-claim this with the real session ID on the first source file edit.
90
+
91
+ **Step 3: Confirm and start**
92
+
93
+ Print:
94
+ ```
95
+ Session started: {name}
96
+ Progress: .claude/progress/{slug}.md
97
+ Spec: {SPEC_PATH or None}
98
+ ```
99
+
100
+ **If a spec exists (SPEC_PATH is not "None"):**
101
+ - Read the spec file
102
+ - Start implementing immediately — the spec IS the instructions
103
+ - Do NOT ask "what do you want to do?"
104
+
105
+ **If no spec:**
106
+ - STOP and wait for user's next message with instructions
107
+
108
+ </process>
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: workerc:resume
3
+ description: Resume an existing work session by claiming an unclaimed progress file
4
+ allowed-tools:
5
+ - Read
6
+ - Edit
7
+ - Glob
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Resume an existing work session. Finds unclaimed/pending progress files and lets the user pick one.
13
+ If none found, tells user to run /workerc:new instead.
14
+ </objective>
15
+
16
+ <process>
17
+
18
+ **Step 1: Find resumable progress files**
19
+
20
+ Read all `.claude/progress/*.md` files. Collect ones where:
21
+ - Line 1 does NOT contain "[DONE]" or "[ABORTED]"
22
+ - Line 2 has `<!-- session: pending -->` or `<!-- session: -->` or no session tag
23
+
24
+ If none found:
25
+ - Print: "No unclaimed progress files found. Run /workerc:new to start fresh."
26
+ - STOP
27
+
28
+ **Step 2: Let user pick**
29
+
30
+ If only 1 unclaimed: skip the question, pick it automatically.
31
+
32
+ If multiple:
33
+ ```
34
+ AskUserQuestion(
35
+ header: "Resume",
36
+ question: "Which one do you want to resume?",
37
+ options: [list names from line 1],
38
+ multiSelect: false
39
+ )
40
+ ```
41
+
42
+ **Step 3: Claim and resume**
43
+
44
+ Set line 2 of chosen file to `<!-- session: pending -->` (hook auto-claims on first edit).
45
+
46
+ Print:
47
+ ```
48
+ Resuming: {line 1}
49
+ Progress: .claude/progress/{filename}
50
+ ```
51
+
52
+ Print the last 5 log entries.
53
+
54
+ If the file has a `## Handoff` section, print it in full — this is the previous session's context.
55
+
56
+ If it has a spec (line 3, not "None"):
57
+ - Read the spec file
58
+ - Re-read files listed in ## Files section
59
+ - Resume implementing — do NOT ask what to do
60
+
61
+ If no spec:
62
+ - STOP and wait for user's next message with instructions
63
+
64
+ </process>
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: workerc:review
3
+ description: Review work against spec before marking done
4
+ allowed-tools:
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ ---
9
+
10
+ <objective>
11
+ Self-check: compare what was built against the spec. Reports coverage, does NOT auto-fix.
12
+ Run this before /workerc:done to catch gaps.
13
+ </objective>
14
+
15
+ <process>
16
+
17
+ **Step 1: Find session progress file**
18
+
19
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
20
+
21
+ If none found: print "No active progress file for this session." and STOP.
22
+
23
+ **Step 2: Check for spec**
24
+
25
+ Read line 3 for spec path.
26
+
27
+ If spec is "None" or missing:
28
+ - Print: "No spec linked. Showing work summary instead."
29
+ - Read all files listed in ## Files section
30
+ - Print a summary of what was built (1 line per file: filename + what changed)
31
+ - STOP
32
+
33
+ **Step 3: Read spec and progress**
34
+
35
+ Read the spec file fully.
36
+ Read the progress file fully.
37
+
38
+ **Step 4: Extract scope items**
39
+
40
+ From the spec's `## Scope` section (or `## Goal` if no Scope), extract each item.
41
+ Items with ~~strikethrough~~ = done in spec.
42
+
43
+ **Step 5: Verify each scope item**
44
+
45
+ For each scope item:
46
+ - Check if it appears done in the spec (strikethrough)
47
+ - Check if related work appears in the progress ## Log
48
+ - Read relevant files from ## Files to verify implementation exists
49
+
50
+ **Step 6: Print checklist**
51
+
52
+ Print:
53
+ ```
54
+ ## Review: {progress filename}
55
+ Spec: {spec path}
56
+
57
+ | Status | Scope Item |
58
+ |--------|-----------|
59
+ | done | {item that's verified} |
60
+ | missing | {item with no evidence of implementation} |
61
+ | partial | {item with some but incomplete evidence} |
62
+
63
+ Summary: X/Y scope items done, Z missing, W partial
64
+ ```
65
+
66
+ If any items are "missing" or "partial":
67
+ - Print: "Run /workerc:done only after addressing gaps — or update spec to descope."
68
+
69
+ If all done:
70
+ - Print: "All scope items covered. Safe to run /workerc:done."
71
+
72
+ **Step 7: Check spec completeness**
73
+
74
+ Check if the spec has content in these sections:
75
+ - `## Decisions` — empty?
76
+ - `## Discovered` — empty?
77
+ - `## Rejected` — empty?
78
+
79
+ If ALL three are empty:
80
+ - Print: "Spec hygiene: Decisions, Discovered, and Rejected are all empty. Consider documenting any choices made or things learned during this work."
81
+
82
+ If only some are empty, skip — not every session has rejections or discoveries.
83
+
84
+ STOP.
85
+
86
+ </process>
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: workerc:scope
3
+ description: Update spec scope — add, remove, or mark items done
4
+ allowed-tools:
5
+ - Read
6
+ - Edit
7
+ - Glob
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Structured way to update the spec's scope mid-session. Keeps scope changes logged in progress.
13
+ </objective>
14
+
15
+ <process>
16
+
17
+ **Step 1: Find session progress file**
18
+
19
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
20
+
21
+ If none found: print "No active progress file for this session." and STOP.
22
+
23
+ **Step 2: Check for spec**
24
+
25
+ Read line 3 for spec path.
26
+
27
+ If spec is "None" or missing:
28
+ - Print: "No spec linked to this session. Nothing to update."
29
+ - STOP
30
+
31
+ **Step 3: Read and show current scope**
32
+
33
+ Read the spec file. Print the current `## Scope` section.
34
+
35
+ **Step 4: Ask what to do**
36
+
37
+ ```
38
+ AskUserQuestion(
39
+ header: "Scope",
40
+ question: "What do you want to change?",
41
+ options: [
42
+ { label: "Add item", description: "Add something new to scope" },
43
+ { label: "Remove item", description: "Descope something" },
44
+ { label: "Mark done", description: "Strikethrough a completed item" }
45
+ ],
46
+ multiSelect: false
47
+ )
48
+ ```
49
+
50
+ **If "Add item":**
51
+ - Ask: "What should be added to scope?"
52
+ - Wait for user input
53
+ - Append `- In: {user input}` to the `## Scope` section in the spec
54
+ - Log: `- [x] ({YYYY-MM-DD HH:MM}) (scope) Added to scope: {item}`
55
+
56
+ **If "Remove item":**
57
+ - Collect current "In:" items from spec
58
+ - Use AskUserQuestion with those items as options (label = item text, description = "Remove this from scope")
59
+ - Remove the chosen line from spec
60
+ - Log: `- [x] ({YYYY-MM-DD HH:MM}) (scope) Descoped: {item}`
61
+
62
+ **If "Mark done":**
63
+ - Collect current "In:" items that aren't struck through
64
+ - Use AskUserQuestion with those items as options (label = item text, description = "Mark as completed")
65
+ - Wrap chosen item text in ~~strikethrough~~
66
+ - Log: `- [x] ({YYYY-MM-DD HH:MM}) (scope) Completed: {item}`
67
+
68
+ **Step 5: Confirm**
69
+
70
+ Print updated `## Scope` section.
71
+
72
+ STOP.
73
+
74
+ </process>
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: workerc:status
3
+ description: Show current session progress
4
+ allowed-tools:
5
+ - Read
6
+ - Glob
7
+ ---
8
+
9
+ <objective>
10
+ Show the current session's progress file. No analysis, no suggestions.
11
+ </objective>
12
+
13
+ <process>
14
+
15
+ **Step 1: Find session progress file**
16
+
17
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
18
+
19
+ If none found: print "No active progress file for this session. Run /workerc:new to start." and STOP.
20
+
21
+ **Step 2: Display**
22
+
23
+ Print the full progress file contents.
24
+
25
+ If there's a spec link (line 3, not "None"):
26
+ - Print "Spec: {path}"
27
+
28
+ STOP.
29
+
30
+ </process>
@@ -0,0 +1,27 @@
1
+ #!/bin/bash
2
+ # Post-edit hook: Lint check
3
+ # Always exit 0, use JSON {"decision":"block","reason":"..."} to report errors
4
+
5
+ INPUT=$(cat)
6
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
7
+
8
+ [ -z "$FILE" ] && exit 0
9
+ [ ! -f "$FILE" ] && exit 0
10
+
11
+ # Only check files the linter cares about
12
+ echo "$FILE" | grep -qE '\.({{{EXTENSIONS}}})$' || exit 0
13
+
14
+ # Skip .claude directory entirely
15
+ echo "$FILE" | grep -qE '/\.claude/' && exit 0
16
+
17
+ LINT_OUTPUT=$({{{LINT_COMMAND}}} "$FILE" 2>&1)
18
+ if [ $? -ne 0 ]; then
19
+ jq -n --arg reason "Lint issues in $FILE:
20
+ $LINT_OUTPUT
21
+
22
+ FIX THESE BEFORE RESPONDING." '{"decision":"block","reason":$reason}'
23
+ exit 0
24
+ fi
25
+
26
+ echo '{}'
27
+ exit 0
@@ -0,0 +1,121 @@
1
+ #!/bin/bash
2
+ # Post-edit hook: Tracker enforcement (session-scoped)
3
+ # Always exit 0, use JSON {"decision":"block","reason":"..."} to report errors
4
+ #
5
+ # Logic:
6
+ # 1. Find tracker claimed by this session → check 15s freshness
7
+ # 2. Find "pending" tracker (from /workerc:new) → auto-claim it with real session ID
8
+ # 3. No tracker found → block, tell agent to create/claim one
9
+ #
10
+ # Subagents share parent session_id — parent's tracker covers them
11
+
12
+ INPUT=$(cat)
13
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
14
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
15
+
16
+ [ -z "$FILE" ] && exit 0
17
+ [ ! -f "$FILE" ] && exit 0
18
+ [ -z "$SESSION_ID" ] && exit 0
19
+
20
+ # Skip entire .claude directory
21
+ echo "$FILE" | grep -qE '/\.claude/' && exit 0
22
+
23
+ TRACKER_DIR="$(cd "$(dirname "$0")/../progress" 2>/dev/null && pwd)"
24
+
25
+ # No progress dir = block
26
+ if [ -z "$TRACKER_DIR" ] || [ ! -d "$TRACKER_DIR" ]; then
27
+ jq -n --arg reason "No .claude/progress/ directory found. Run /workerc:new to create one." '{"decision":"block","reason":$reason}'
28
+ exit 0
29
+ fi
30
+
31
+ # Scan all trackers
32
+ NOW=$(date +%s)
33
+ MY_TRACKER=""
34
+ MY_TRACKER_AGE=""
35
+ PENDING_TRACKER=""
36
+ UNCLAIMED=""
37
+
38
+ for t in "$TRACKER_DIR"/*.md; do
39
+ [ -f "$t" ] || continue
40
+ LINE1=$(head -1 "$t")
41
+
42
+ # Skip done/aborted trackers
43
+ echo "$LINE1" | grep -q "\[DONE\]" && continue
44
+ echo "$LINE1" | grep -q "\[ABORTED\]" && continue
45
+
46
+ LINE2=$(sed -n '2p' "$t")
47
+
48
+ # Already claimed by this session
49
+ if echo "$LINE2" | grep -q "<!-- session: $SESSION_ID -->"; then
50
+ MY_TRACKER="$t"
51
+ MOD=$(stat -f %m "$t" 2>/dev/null || stat -c %Y "$t" 2>/dev/null)
52
+ MY_TRACKER_AGE=$((NOW - MOD))
53
+ break
54
+ fi
55
+
56
+ # Pending tracker (from /workerc:new)
57
+ if echo "$LINE2" | grep -q "<!-- session: pending -->"; then
58
+ if [ -z "$PENDING_TRACKER" ]; then
59
+ PENDING_TRACKER="$t"
60
+ else
61
+ # Multiple pending — can't auto-claim safely
62
+ PENDING_TRACKER="AMBIGUOUS"
63
+ fi
64
+ continue
65
+ fi
66
+
67
+ # Unclaimed (empty session or no session tag)
68
+ if echo "$LINE2" | grep -q "<!-- session: -->" || ! echo "$LINE2" | grep -q "<!-- session:"; then
69
+ UNCLAIMED="$UNCLAIMED
70
+ $(basename "$t"): $LINE1"
71
+ fi
72
+ done
73
+
74
+ # Case 1: Already claimed by this session — check freshness + auto-track files
75
+ if [ -n "$MY_TRACKER" ]; then
76
+ # Auto-append edited file to ## Files if not already listed
77
+ PROJECT_DIR="$(cd "$(dirname "$0")/../.." 2>/dev/null && pwd)"
78
+ REL_FILE="${FILE#$PROJECT_DIR/}"
79
+ if ! grep -qF "$REL_FILE" "$MY_TRACKER" 2>/dev/null; then
80
+ echo "- $REL_FILE" >> "$MY_TRACKER"
81
+ fi
82
+
83
+ if [ "$MY_TRACKER_AGE" -le 15 ]; then
84
+ echo '{}'
85
+ exit 0
86
+ fi
87
+ jq -n --arg reason "Tracker $(basename "$MY_TRACKER") not updated in ${MY_TRACKER_AGE}s. UPDATE your tracker before continuing." '{"decision":"block","reason":$reason}'
88
+ exit 0
89
+ fi
90
+
91
+ # Case 2: Pending tracker exists — auto-claim it + track first file
92
+ if [ "$PENDING_TRACKER" = "AMBIGUOUS" ]; then
93
+ jq -n --arg reason "Multiple pending progress files found. Claim one manually: set line 2 to <!-- session: $SESSION_ID -->" '{"decision":"block","reason":$reason}'
94
+ exit 0
95
+ fi
96
+ if [ -n "$PENDING_TRACKER" ]; then
97
+ # Replace "pending" with real session ID using sed
98
+ sed -i '' "s/<!-- session: pending -->/<!-- session: $SESSION_ID -->/" "$PENDING_TRACKER" 2>/dev/null || \
99
+ sed -i "s/<!-- session: pending -->/<!-- session: $SESSION_ID -->/" "$PENDING_TRACKER" 2>/dev/null
100
+ # Track the first edited file
101
+ PROJECT_DIR="$(cd "$(dirname "$0")/../.." 2>/dev/null && pwd)"
102
+ REL_FILE="${FILE#$PROJECT_DIR/}"
103
+ if ! grep -qF "$REL_FILE" "$PENDING_TRACKER" 2>/dev/null; then
104
+ echo "- $REL_FILE" >> "$PENDING_TRACKER"
105
+ fi
106
+ # Touch it so freshness check passes
107
+ touch "$PENDING_TRACKER"
108
+ echo '{}'
109
+ exit 0
110
+ fi
111
+
112
+ # Case 3: No tracker — block
113
+ REASON="No progress file for this session. Run /workerc:new to set up."
114
+ if [ -n "$UNCLAIMED" ]; then
115
+ REASON="$REASON
116
+ Unclaimed trackers you could claim:$UNCLAIMED
117
+
118
+ To claim: set line 2 to <!-- session: $SESSION_ID -->"
119
+ fi
120
+ jq -n --arg reason "$REASON" '{"decision":"block","reason":$reason}'
121
+ exit 0
@@ -0,0 +1,25 @@
1
+ #!/bin/bash
2
+ # Post-edit hook: Type check
3
+ # Always exit 0, use JSON {"decision":"block","reason":"..."} to report errors
4
+
5
+ INPUT=$(cat)
6
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
7
+
8
+ [ -z "$FILE" ] && exit 0
9
+ [ ! -f "$FILE" ] && exit 0
10
+ echo "$FILE" | grep -qE '\.({{{EXTENSIONS}}})$' || exit 0
11
+
12
+ # Skip .claude directory entirely
13
+ echo "$FILE" | grep -qE '/\.claude/' && exit 0
14
+
15
+ TSC_OUTPUT=$({{{TYPE_COMMAND}}} 2>&1 | head -20)
16
+ if [ -n "$TSC_OUTPUT" ]; then
17
+ jq -n --arg reason "TypeScript errors:
18
+ $TSC_OUTPUT
19
+
20
+ FIX THESE BEFORE RESPONDING." '{"decision":"block","reason":$reason}'
21
+ exit 0
22
+ fi
23
+
24
+ echo '{}'
25
+ exit 0