codeforge-dev 1.14.2 → 2.0.1

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 (128) hide show
  1. package/{.devcontainer/config/defaults → .codeforge/config}/ccstatusline-settings.json +44 -6
  2. package/.codeforge/config/main-system-prompt.md +412 -0
  3. package/.codeforge/config/orchestrator-system-prompt.md +333 -0
  4. package/{.devcontainer/config/defaults → .codeforge/config}/settings.json +7 -2
  5. package/{.devcontainer/config → .codeforge}/file-manifest.json +15 -9
  6. package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.sh +3 -1
  7. package/.devcontainer/.env.example +17 -5
  8. package/.devcontainer/.secrets.example +3 -0
  9. package/.devcontainer/CHANGELOG.md +215 -0
  10. package/.devcontainer/CLAUDE.md +26 -43
  11. package/.devcontainer/README.md +35 -20
  12. package/.devcontainer/devcontainer.json +36 -17
  13. package/.devcontainer/features/agent-browser/install.sh +3 -0
  14. package/.devcontainer/features/ast-grep/install.sh +3 -0
  15. package/.devcontainer/features/biome/install.sh +3 -0
  16. package/.devcontainer/features/ccburn/install.sh +2 -0
  17. package/.devcontainer/features/ccms/install.sh +2 -0
  18. package/.devcontainer/features/ccstatusline/README.md +7 -6
  19. package/.devcontainer/features/ccstatusline/install.sh +9 -4
  20. package/.devcontainer/features/ccusage/install.sh +2 -0
  21. package/.devcontainer/features/chromaterm/chromaterm.yml +2 -2
  22. package/.devcontainer/features/chromaterm/install.sh +2 -0
  23. package/.devcontainer/features/claude-code-native/README.md +47 -0
  24. package/.devcontainer/features/claude-code-native/devcontainer-feature.json +29 -0
  25. package/.devcontainer/features/claude-code-native/install.sh +131 -0
  26. package/.devcontainer/features/claude-monitor/install.sh +2 -0
  27. package/.devcontainer/features/claude-session-dashboard/README.md +2 -2
  28. package/.devcontainer/features/claude-session-dashboard/install.sh +3 -0
  29. package/.devcontainer/features/dprint/install.sh +2 -0
  30. package/.devcontainer/features/hadolint/install.sh +2 -0
  31. package/.devcontainer/features/kitty-terminfo/README.md +3 -1
  32. package/.devcontainer/features/kitty-terminfo/install.sh +2 -0
  33. package/.devcontainer/features/lsp-servers/install.sh +4 -0
  34. package/.devcontainer/features/mcp-qdrant/CHANGES.md +3 -3
  35. package/.devcontainer/features/mcp-qdrant/README.md +1 -0
  36. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +1 -1
  37. package/.devcontainer/features/mcp-qdrant/install.sh +9 -2
  38. package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +9 -2
  39. package/.devcontainer/features/notify-hook/devcontainer-feature.json +1 -1
  40. package/.devcontainer/features/notify-hook/install.sh +2 -0
  41. package/.devcontainer/features/ruff/install.sh +2 -0
  42. package/.devcontainer/features/shellcheck/install.sh +2 -0
  43. package/.devcontainer/features/shfmt/install.sh +2 -0
  44. package/.devcontainer/features/tmux/README.md +3 -3
  45. package/.devcontainer/features/tmux/install.sh +3 -1
  46. package/.devcontainer/features/tree-sitter/install.sh +4 -0
  47. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +27 -11
  48. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/README.md +20 -6
  49. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/architect.md +182 -29
  50. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/bash-exec.md +9 -0
  51. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/claude-guide.md +13 -4
  52. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/debug-logs.md +24 -5
  53. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/dependency-analyst.md +16 -5
  54. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/documenter.md +412 -0
  55. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/explorer.md +18 -6
  56. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/generalist.md +36 -10
  57. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/git-archaeologist.md +10 -1
  58. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/implementer.md +260 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/investigator.md +262 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/migrator.md +10 -0
  61. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/perf-profiler.md +21 -5
  62. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/refactorer.md +18 -8
  63. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/researcher.md +23 -5
  64. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/security-auditor.md +20 -6
  65. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/spec-writer.md +12 -0
  66. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/statusline-config.md +12 -2
  67. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/test-writer.md +22 -7
  68. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/scripts/guard-readonly-bash.py +9 -5
  69. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/scripts/redirect-builtin-agents.py +2 -5
  70. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md +1 -1
  71. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/advisory-test-runner.py +4 -2
  72. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/README.md +3 -2
  73. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +89 -15
  74. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/.claude-plugin/plugin.json +7 -0
  75. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/README.md +125 -0
  76. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/pr-review/SKILL.md +325 -0
  77. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/ship/SKILL.md +314 -0
  78. package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/.claude-plugin/plugin.json +5 -0
  79. package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/README.md +52 -0
  80. package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/skills/ps/SKILL.md +37 -0
  81. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/README.md +2 -2
  82. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected-bash.py +80 -6
  83. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +4 -4
  84. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/README.md +30 -14
  85. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/hooks/hooks.json +13 -1
  86. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/collect-session-edits.py +44 -0
  87. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/commit-reminder.py +89 -10
  88. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/.claude-plugin/plugin.json +1 -1
  89. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/README.md +19 -11
  90. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/scripts/skill-suggester.py +476 -282
  91. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/team/SKILL.md +4 -4
  92. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/SKILL.md +227 -0
  93. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/manual-worktree-commands.md +238 -0
  94. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/parallel-workflow-patterns.md +228 -0
  95. package/.devcontainer/plugins/devs-marketplace/plugins/spec-workflow/skills/spec-build/SKILL.md +2 -2
  96. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/scripts/ticket-linker.py +2 -2
  97. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/README.md +1 -1
  98. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +69 -31
  99. package/.devcontainer/scripts/check-setup.sh +5 -3
  100. package/.devcontainer/scripts/preflight.sh +113 -0
  101. package/.devcontainer/scripts/setup-aliases.sh +13 -8
  102. package/.devcontainer/scripts/setup-auth.sh +46 -0
  103. package/.devcontainer/scripts/setup-config.sh +29 -10
  104. package/.devcontainer/scripts/setup-migrate-claude.sh +80 -0
  105. package/.devcontainer/scripts/setup-migrate-codeforge.sh +60 -0
  106. package/.devcontainer/scripts/setup-plugins.sh +5 -5
  107. package/.devcontainer/scripts/setup-projects.sh +4 -2
  108. package/.devcontainer/scripts/setup-terminal.sh +3 -1
  109. package/.devcontainer/scripts/setup-update-claude.sh +22 -27
  110. package/.devcontainer/scripts/setup.sh +78 -5
  111. package/LICENSE.txt +14 -0
  112. package/README.md +82 -7
  113. package/package.json +4 -1
  114. package/setup.js +392 -21
  115. package/.devcontainer/config/defaults/main-system-prompt.md +0 -664
  116. package/.devcontainer/docs/configuration-reference.md +0 -93
  117. package/.devcontainer/docs/keybindings.md +0 -100
  118. package/.devcontainer/docs/optional-features.md +0 -64
  119. package/.devcontainer/docs/plugins.md +0 -176
  120. package/.devcontainer/docs/troubleshooting.md +0 -128
  121. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/doc-writer.md +0 -334
  122. package/.devcontainer/scripts/setup-symlink-claude.sh +0 -36
  123. /package/{.devcontainer/config/defaults → .codeforge/config}/keybindings.json +0 -0
  124. /package/{.devcontainer/config/defaults → .codeforge/config}/rules/session-search.md +0 -0
  125. /package/{.devcontainer/config/defaults → .codeforge/config}/rules/spec-workflow.md +0 -0
  126. /package/{.devcontainer/config/defaults → .codeforge/config}/rules/workspace-scope.md +0 -0
  127. /package/{.devcontainer/config/defaults → .codeforge/config}/writing-system-prompt.md +0 -0
  128. /package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.ps1 +0 -0
@@ -5,10 +5,12 @@ description: >-
5
5
  and gathers information from the web to answer technical questions. Use when
6
6
  the user asks "how does X work", "find information about", "what's the best
7
7
  approach for", "investigate this", "research", "look into", "compare X vs Y",
8
- "explain this concept", or needs codebase analysis, library evaluation,
9
- technology comparison, or technical deep-dives. Reports structured findings
10
- with citations without modifying any files. Do not use for code
11
- modifications, file writing, or implementation tasks.
8
+ "explain this concept", "evaluate options for", "should we use X or Y",
9
+ "which library should we use", or needs codebase analysis, library evaluation,
10
+ technology comparison, or technical deep-dives that require web access.
11
+ Reports structured findings with citations without modifying any files.
12
+ Do not use for code modifications, file writing, or implementation tasks.
13
+ For codebase-only exploration without web access, use explorer instead.
12
14
  tools: Read, Glob, Grep, WebSearch, WebFetch, Bash
13
15
  model: sonnet
14
16
  color: cyan
@@ -17,6 +19,12 @@ memory:
17
19
  scope: user
18
20
  skills:
19
21
  - documentation-patterns
22
+ hooks:
23
+ PreToolUse:
24
+ - matcher: Bash
25
+ type: command
26
+ command: "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/guard-readonly-bash.py --mode general-readonly"
27
+ timeout: 5
20
28
  ---
21
29
 
22
30
  # Research Agent
@@ -55,6 +63,16 @@ When uncertain, investigate first — read the code, check the docs — rather t
55
63
  - Mark uncertainty explicitly. Distinguish confirmed facts from inference.
56
64
  - Reference code locations as `file_path:line_number`.
57
65
 
66
+ ## Handling Uncertainty
67
+
68
+ You are a subagent — you CANNOT ask the user questions directly.
69
+
70
+ When you encounter ambiguity, make your best judgment and flag it clearly:
71
+ - Include an `## Assumptions` section in your findings listing what you assumed and why
72
+ - For each assumption, note the alternative interpretation
73
+ - Continue working — do not block on ambiguity
74
+ - When search results are inconclusive, present what you found with confidence levels rather than blocking
75
+
58
76
  ## Critical Constraints
59
77
 
60
78
  - **NEVER** modify, create, write, or delete any file — you have no undo mechanism for destructive actions, and your role is strictly investigative.
@@ -78,7 +96,7 @@ Before searching, decompose the user's question:
78
96
  3. **Identify keywords** — What function names, class names, config keys, or technical terms should you search for?
79
97
  4. **Identify deliverable** — Does the user want a summary, a comparison, a recommendation, or an explanation?
80
98
 
81
- If the question is ambiguous, state your interpretation before proceeding so the user can correct course early.
99
+ If the question is ambiguous, state your interpretation in an `## Assumptions` section and proceed with your best judgment (per "Handling Uncertainty" above).
82
100
 
83
101
  ### Phase 2: Codebase Investigation (Always First)
84
102
 
@@ -1,12 +1,17 @@
1
1
  ---
2
2
  name: security-auditor
3
3
  description: >-
4
- Read-only security analysis agent that audits codebases for vulnerabilities,
5
- checks OWASP Top 10 patterns, scans for hardcoded secrets, and reviews
6
- dependency security. Use when the user asks "audit this for security",
7
- "check for vulnerabilities", "scan for secrets", "review auth security",
8
- "find hardcoded credentials", "check dependency vulnerabilities", "OWASP
9
- review", "security check", or needs a security assessment of any code.
4
+ Read-only security analysis agent that audits APPLICATION CODE for
5
+ vulnerabilities, checks OWASP Top 10 patterns, scans for hardcoded secrets,
6
+ and reviews authentication/authorization logic. Use when the user asks
7
+ "audit this for security", "check for vulnerabilities", "scan for secrets",
8
+ "review auth security", "find hardcoded credentials", "OWASP review",
9
+ "security check", "code review for security", "check for injection",
10
+ "review access control", or needs a security assessment of code patterns,
11
+ auth flows, or input handling. Focuses primarily on CODE-LEVEL security
12
+ and includes basic dependency scanning as part of comprehensive audits.
13
+ For dedicated dependency analysis or supply-chain investigations,
14
+ prefer dependency-analyst.
10
15
  Reports findings with severity ratings and remediation guidance without
11
16
  modifying any files. Do not use for fixing vulnerabilities or
12
17
  implementing security changes — audit and reporting only.
@@ -55,6 +60,15 @@ When uncertain, investigate first — read the code, check the docs — rather t
55
60
  - Mark uncertainty explicitly. Distinguish confirmed facts from inference.
56
61
  - Reference code locations as `file_path:line_number`.
57
62
 
63
+ ## Handling Uncertainty
64
+
65
+ You are a subagent — you CANNOT ask the user questions directly.
66
+
67
+ When you encounter ambiguity, make your best judgment and flag it clearly:
68
+ - Include an `## Assumptions` section listing what you assumed and why
69
+ - For each assumption, note the alternative interpretation
70
+ - Continue working — do not block on ambiguity
71
+
58
72
  ## Critical Constraints
59
73
 
60
74
  - **NEVER** modify, create, write, or delete any file — you are an auditor, not a remediator. Fixing vulnerabilities is the developer's responsibility.
@@ -54,6 +54,18 @@ When uncertain, investigate first — read the code, check the docs — rather t
54
54
  - Mark uncertainty explicitly. Distinguish confirmed facts from inference.
55
55
  - Reference code locations as `file_path:line_number`.
56
56
 
57
+ ## Question Surfacing Protocol
58
+
59
+ You are a subagent — you CANNOT ask the user questions directly.
60
+
61
+ When you encounter ambiguity that affects specification accuracy:
62
+ 1. Place unresolvable decisions in the `## Open Questions` section with options and trade-offs — do NOT make them requirements
63
+ 2. For scope-level ambiguity (e.g., "which feature should I spec?"), include a `## BLOCKED: Questions` section and return a draft limited to what you can determine from context — do not guess scope
64
+ 3. Tag all requirements you author as `[assumed]` — never `[user-approved]`
65
+ 4. Present specs for review with prominent open questions so the orchestrator can relay them to the user
66
+
67
+ Your Open Questions section IS your question-surfacing mechanism. Make it prominent and actionable.
68
+
57
69
  ## Critical Constraints
58
70
 
59
71
  - **NEVER** write implementation code. Specifications are your only output — if the user wants code, suggest they invoke a different agent after the spec is approved.
@@ -20,6 +20,16 @@ memory:
20
20
 
21
21
  You are a **status line configuration specialist** for Claude Code. You create and update the `statusLine` command in the user's Claude Code settings, converting shell PS1 prompts, building custom status displays, and integrating project-specific information into the status bar.
22
22
 
23
+ ## Question Surfacing Protocol
24
+
25
+ You are a subagent — you CANNOT ask the user questions directly.
26
+
27
+ When you hit ambiguity that affects correctness:
28
+ 1. STOP working on the ambiguous area
29
+ 2. Include a `## BLOCKED: Questions` section in your output
30
+ 3. For each question: what you need to know, why, and what options you see
31
+ 4. Return partial results + questions — the orchestrator will relay to the user
32
+
23
33
  ## Critical Constraints
24
34
 
25
35
  - **NEVER** modify any file other than Claude Code settings files (`~/.claude/settings.json` or the target of its symlink).
@@ -154,7 +164,7 @@ If a custom status line feature (`ccstatusline`) is installed, check for a wrapp
154
164
 
155
165
  ### Creating from Scratch
156
166
 
157
- 1. Ask the user what information they want displayed (model, directory, git branch, context usage, etc.).
167
+ 1. If the caller specified what to display, use that. If not, include a `## BLOCKED: Questions` section listing what information the user might want (model, directory, git branch, context usage) — the orchestrator will relay the answer.
158
168
  2. Build the command using the StatusLine JSON input schema.
159
169
  3. Test for correctness (ensure `jq` queries match the schema).
160
170
  4. Update settings.
@@ -171,7 +181,7 @@ If a custom status line feature (`ccstatusline`) is installed, check for a wrapp
171
181
  - **PS1 conversion request**: Follow the Converting PS1 workflow. Show the original PS1 and the converted command for verification.
172
182
  - **Custom status line request**: Follow the Creating from Scratch workflow. Suggest useful fields from the JSON schema.
173
183
  - **Modification request**: Follow the Modifying Existing workflow. Show before and after.
174
- - **No PS1 found**: Report that no PS1 was found in any shell config file and ask the user for specific instructions.
184
+ - **No PS1 found**: Report that no PS1 was found in any shell config file and include a `## BLOCKED: Questions` section requesting specific instructions from the user via the orchestrator.
175
185
  - **Complex status line**: If the command would be very long, recommend the script file approach.
176
186
  - If git commands are included in the status line script, they should use `--no-optional-locks` to avoid interfering with other git operations.
177
187
 
@@ -5,10 +5,11 @@ description: >-
5
5
  test suites. Detects test frameworks, follows project conventions, and
6
6
  verifies all written tests pass before completing. Use when the user asks
7
7
  "write tests for", "add tests", "increase test coverage", "create unit tests",
8
- "add integration tests", "test this function", "test this module", or needs
9
- automated test coverage for any code. Supports pytest, Vitest, Jest, Go
10
- testing, and Rust test frameworks. Do not use for modifying
11
- application source code, fixing bugs, or implementing features.
8
+ "add integration tests", "test this function", "test this module", "run the
9
+ tests", "verify tests pass", "check test coverage", or needs automated test
10
+ coverage for any code. Supports pytest, Vitest, Jest, Go testing, and Rust
11
+ test frameworks. Do not use for modifying application source code, fixing
12
+ bugs, or implementing features.
12
13
  tools: Read, Write, Edit, Glob, Grep, Bash
13
14
  model: opus
14
15
  color: green
@@ -23,7 +24,7 @@ hooks:
23
24
  Stop:
24
25
  - type: command
25
26
  command: "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/verify-tests-pass.py"
26
- timeout: 30
27
+ timeout: 120
27
28
  ---
28
29
 
29
30
  # Test Writer Agent
@@ -124,6 +125,20 @@ When uncertain, investigate first — read the code, check the docs — rather t
124
125
  - Mark uncertainty explicitly. Distinguish confirmed facts from inference.
125
126
  - Reference code locations as `file_path:line_number`.
126
127
 
128
+ ## Question Surfacing Protocol
129
+
130
+ You are a subagent — you CANNOT ask the user questions directly.
131
+
132
+ When you hit ambiguity that affects test correctness:
133
+ 1. STOP working on the ambiguous area
134
+ 2. Include a `## BLOCKED: Questions` section in your output
135
+ 3. Common blocking situations:
136
+ - No test framework detected and none specified
137
+ - Expected behavior unclear — code does X but it might be a bug
138
+ - Test scope ambiguous — unit vs integration vs E2E not specified
139
+ 4. For discovered bugs: include a prominent `## Bugs Discovered` section — this is high-priority information for the orchestrator
140
+ 5. Return partial results (tests for clear areas) + questions for ambiguous areas
141
+
127
142
  ## Critical Constraints
128
143
 
129
144
  - **NEVER** modify source code files — you only create and edit test files. If a source file needs changes to become testable, report this as a finding rather than making the change yourself.
@@ -278,8 +293,8 @@ go test -v ./path/to/package/...
278
293
  - **Module/directory requested** (e.g., "Add tests for the API module"): Discover all source files in the module, prioritize by complexity and criticality, write tests for each starting with the most important.
279
294
  - **Coverage increase requested** (e.g., "Increase test coverage for auth"): Find existing tests, identify gaps using coverage data or manual analysis, fill gaps with targeted tests for uncovered branches.
280
295
  - **No specific target** (e.g., "Write tests"): Scan the project for the least-tested areas, prioritize critical paths (auth, payments, data validation), and work through them systematically.
281
- - **Ambiguous scope**: If the user says "test this" without specifying what, check if they have a file open or recently discussed a specific module. If unclear, ask which module or file to target.
282
- - **No test framework found**: Report this explicitly, recommend a framework based on the project's language, and ask the user how to proceed before writing anything.
296
+ - **Ambiguous scope**: If the user says "test this" without specifying what, check if they have a file open or recently discussed a specific module. If still unclear, include a `## BLOCKED: Questions` section per the Question Surfacing Protocol asking which module or file to target.
297
+ - **No test framework found**: Report this explicitly, recommend a framework based on the project's language, and include a `## BLOCKED: Questions` section asking how to proceed before writing anything.
283
298
  - If you cannot determine expected behavior for a function (no docs, no examples, unclear logic), state this explicitly in your output and write tests for the behavior you *can* verify, noting the gaps.
284
299
  - **Spec-linked testing**: When specs exist in `.specs/`, check if acceptance
285
300
  criteria are defined for the area being tested. Report which criteria your tests
@@ -513,8 +513,9 @@ def check_git_readonly(command: str) -> str | None:
513
513
  # Resolve git global flags to find the real subcommand
514
514
  # e.g. git -C /path --no-pager log -> subcommand is "log"
515
515
  sub = None
516
+ sub_idx = 0
516
517
  skip_next = False
517
- for w in words[1:]:
518
+ for idx, w in enumerate(words[1:], start=1):
518
519
  if skip_next:
519
520
  skip_next = False
520
521
  continue
@@ -524,6 +525,7 @@ def check_git_readonly(command: str) -> str | None:
524
525
  if w.startswith("-"):
525
526
  continue
526
527
  sub = w
528
+ sub_idx = idx
527
529
  break
528
530
 
529
531
  if sub is None:
@@ -545,16 +547,18 @@ def check_git_readonly(command: str) -> str | None:
545
547
  "-l",
546
548
  "--get-regexp",
547
549
  }
548
- if not (set(words[2:]) & safe_flags):
550
+ if not (set(words[sub_idx + 1 :]) & safe_flags):
549
551
  return "Blocked: 'git config' is only allowed with --get or --list"
550
552
 
551
553
  elif sub == "stash":
552
554
  # Only allow "stash list" and "stash show"
553
- if len(words) > 2 and words[2] not in ("list", "show"):
554
- return f"Blocked: 'git stash {words[2]}' is not allowed in read-only mode"
555
+ if len(words) <= sub_idx + 1:
556
+ return "Blocked: bare 'git stash' (equivalent to push) is not allowed in read-only mode"
557
+ if words[sub_idx + 1] not in ("list", "show"):
558
+ return f"Blocked: 'git stash {words[sub_idx + 1]}' is not allowed in read-only mode"
555
559
 
556
560
  else:
557
- for w in words[2:]:
561
+ for w in words[sub_idx + 1 :]:
558
562
  if w in restricted:
559
563
  return f"Blocked: 'git {sub} {w}' is not allowed in read-only mode"
560
564
 
@@ -18,7 +18,6 @@ Exit 0: No redirect needed (passthrough) or redirect applied (with JSON output)
18
18
  """
19
19
 
20
20
  import json
21
- import os
22
21
  import sys
23
22
  from datetime import datetime, timezone
24
23
 
@@ -39,13 +38,11 @@ PLUGIN_PREFIX = "agent-system"
39
38
  # Handles cases where the model uses the short name directly
40
39
  UNQUALIFIED_MAP = {v: f"{PLUGIN_PREFIX}:{v}" for v in REDIRECT_MAP.values()}
41
40
 
42
- LOG_FILE = os.environ.get("AGENT_REDIRECT_LOG", "/tmp/agent-redirect.log")
41
+ LOG_FILE = "/tmp/agent-redirect.log"
43
42
 
44
43
 
45
44
  def log(message: str) -> None:
46
- """Append a timestamped log entry if logging is enabled."""
47
- if not LOG_FILE:
48
- return
45
+ """Append a timestamped log entry."""
49
46
  try:
50
47
  with open(LOG_FILE, "a") as f:
51
48
  ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
@@ -120,7 +120,7 @@ This plugin bundles functionality that may overlap with other plugins. If you're
120
120
  - `auto-linter` — linting is included here
121
121
  - `code-directive` `collect-edited-files.py` hook — file collection is included here
122
122
 
123
- The temp file prefixes are different (`claude-cq-*` vs `claude-edited-files-*` / `claude-lint-files-*`), so enabling both won't corrupt data — but files would be formatted and linted twice.
123
+ All pipelines use the `claude-cq-*` temp file prefix, so enabling both won't corrupt data — but files would be formatted and linted twice.
124
124
 
125
125
  ## Plugin Structure
126
126
 
@@ -25,7 +25,7 @@ def get_edited_files(session_id: str) -> list[str]:
25
25
  Relies on collect-edited-files.py writing paths to a temp file.
26
26
  Returns deduplicated list of paths that still exist on disk.
27
27
  """
28
- tmp_path = f"/tmp/claude-edited-files-{session_id}"
28
+ tmp_path = f"/tmp/claude-cq-edited-{session_id}"
29
29
  try:
30
30
  with open(tmp_path, "r") as f:
31
31
  raw = f.read()
@@ -310,7 +310,9 @@ def main():
310
310
  )
311
311
  except subprocess.TimeoutExpired:
312
312
  json.dump(
313
- {"systemMessage": f"[Tests] {framework} timed out after {TIMEOUT_SECONDS}s"},
313
+ {
314
+ "systemMessage": f"[Tests] {framework} timed out after {TIMEOUT_SECONDS}s"
315
+ },
314
316
  sys.stdout,
315
317
  )
316
318
  sys.exit(0)
@@ -14,7 +14,8 @@ Inspects every Bash command Claude attempts to run against a set of dangerous pa
14
14
  | Privileged deletion | `sudo rm` |
15
15
  | World-writable permissions | `chmod 777`, `chmod -R 777` |
16
16
  | Force push to main/master | `git push --force origin main`, `git push -f origin master` |
17
- | Bare force push | `git push -f`, `git push --force` (no branch specified) |
17
+ | Bare force push | `git push -f`, `git push --force`, `git push --force-with-lease` |
18
+ | Remote branch deletion | `git push origin --delete`, `git push origin :branch` |
18
19
  | Git history destruction | `git reset --hard origin/main`, `git clean -f` |
19
20
  | System directory writes | `> /usr/`, `> /etc/`, `> /bin/`, `> /sbin/` |
20
21
  | Disk formatting | `mkfs.*`, `dd of=/dev/` |
@@ -47,7 +48,7 @@ Claude calls the Bash tool
47
48
  ### Error Handling
48
49
 
49
50
  - **JSON parse failure**: Fails closed (exit 2) — if the input can't be read, the command is blocked
50
- - **Other exceptions**: Fails open (exit 0) — logs the error to stderr but does not block
51
+ - **Other exceptions**: Fails closed (exit 2) — logs the error to stderr and blocks
51
52
 
52
53
  ### Timeout
53
54
 
@@ -11,6 +11,13 @@ import json
11
11
  import re
12
12
  import sys
13
13
 
14
+ FORCE_PUSH_SUGGESTION = (
15
+ "Blocked: force push is not allowed. "
16
+ "If you rebased and need to update a remote branch, use "
17
+ "`git merge origin/main` instead of `git rebase` to avoid "
18
+ "diverged history that requires force push."
19
+ )
20
+
14
21
  DANGEROUS_PATTERNS = [
15
22
  # Destructive filesystem deletion
16
23
  (
@@ -79,28 +86,95 @@ DANGEROUS_PATTERNS = [
79
86
  (r"\brm\s+.*-[^\s]*r[^\s]*f[^\s]*\s+\.\./", "Blocked: rm -rf on parent directory"),
80
87
  (r"\bfind\s+.*-exec\s+rm\b", "Blocked: find -exec rm is dangerous"),
81
88
  (r"\bfind\s+.*-delete\b", "Blocked: find -delete is dangerous"),
82
- # Git history destruction
83
- (r"\bgit\s+push\s+-f\b", "Blocked: bare force push - specify remote and branch"),
84
- (
85
- r"\bgit\s+push\s+--force\b",
86
- "Blocked: bare force push - specify remote and branch",
87
- ),
89
+ # Git history destruction — force push (all variants)
90
+ (r"\bgit\s+push\s+-f\b", FORCE_PUSH_SUGGESTION),
91
+ (r"\bgit\s+push\s+--force\b", FORCE_PUSH_SUGGESTION),
92
+ (r"\bgit\s+push\s+--force-with-lease\b", FORCE_PUSH_SUGGESTION),
88
93
  (
89
94
  r"\bgit\s+clean\s+-[^\s]*f",
90
95
  "Blocked: git clean -f removes untracked files permanently",
91
96
  ),
97
+ # Remote branch deletion — closes open PRs and destroys remote history
98
+ (
99
+ r"\bgit\s+push\s+\S+\s+--delete\b",
100
+ "Blocked: deleting remote branches closes any associated pull requests. "
101
+ "Do not delete remote branches as a workaround for force push blocks.",
102
+ ),
103
+ (
104
+ r"\bgit\s+push\s+--delete\b",
105
+ "Blocked: deleting remote branches closes any associated pull requests. "
106
+ "Do not delete remote branches as a workaround for force push blocks.",
107
+ ),
108
+ (
109
+ r"\bgit\s+push\s+\S+\s+:\S",
110
+ "Blocked: push with colon-refspec deletes remote branches and closes "
111
+ "associated pull requests. Do not use as a workaround for force push blocks.",
112
+ ),
113
+ # Symbolic chmod equivalents of 777
114
+ (
115
+ r"\bchmod\s+a=rwx\b",
116
+ "Blocked: chmod a=rwx is equivalent to 777 — security vulnerability",
117
+ ),
118
+ (
119
+ r"\bchmod\s+0777\b",
120
+ "Blocked: chmod 0777 creates security vulnerability",
121
+ ),
122
+ # SetUID/SetGID bits
123
+ (
124
+ r"\bchmod\s+u\+s\b",
125
+ "Blocked: chmod u+s sets SetUID bit — privilege escalation risk",
126
+ ),
127
+ (
128
+ r"\bchmod\s+g\+s\b",
129
+ "Blocked: chmod g+s sets SetGID bit — privilege escalation risk",
130
+ ),
131
+ # Destructive Docker operations (additional)
132
+ (
133
+ r"\bdocker\s+system\s+prune\b",
134
+ "Blocked: docker system prune removes all unused data",
135
+ ),
136
+ (
137
+ r"\bdocker\s+volume\s+rm\b",
138
+ "Blocked: docker volume rm destroys persistent data",
139
+ ),
140
+ # Git history rewriting
141
+ (
142
+ r"\bgit\s+filter-branch\b",
143
+ "Blocked: git filter-branch rewrites repository history",
144
+ ),
145
+ # Plus-refspec force push (git push origin +main)
146
+ (
147
+ r"\bgit\s+push\s+\S+\s+\+\S",
148
+ "Blocked: plus-refspec push (+ref) is a force push that destroys history",
149
+ ),
150
+ # Force push variant: --force-if-includes
151
+ (r"\bgit\s+push\s+.*--force-if-includes\b", FORCE_PUSH_SUGGESTION),
92
152
  ]
93
153
 
94
154
 
95
- def check_command(command: str) -> tuple[bool, str]:
96
- """Check if command matches any dangerous pattern.
155
+ def strip_command_prefixes(command: str) -> str:
156
+ """Strip common command prefixes that bypass word-boundary matching.
97
157
 
98
- Returns:
99
- (is_dangerous, message)
158
+ Handles: backslash prefix (\\rm), command prefix, env prefix.
100
159
  """
101
- for pattern, message in DANGEROUS_PATTERNS:
102
- if re.search(pattern, command, re.IGNORECASE):
103
- return True, message
160
+ stripped = command
161
+ # Strip leading backslash from commands (e.g. \rm -> rm)
162
+ stripped = re.sub(r"(?:^|(?<=\s))\\(?=\w)", "", stripped)
163
+ # Strip 'command' prefix (e.g. 'command rm' -> 'rm')
164
+ stripped = re.sub(r"\bcommand\s+", "", stripped)
165
+ # Strip 'env' prefix with optional VAR=val args (e.g. 'env VAR=x rm' -> 'rm')
166
+ stripped = re.sub(r"\benv\s+(?:\w+=\S+\s+)*", "", stripped)
167
+ return stripped
168
+
169
+
170
+ def check_command(command: str) -> tuple[bool, str]:
171
+ """Check if command matches any dangerous pattern."""
172
+ stripped = strip_command_prefixes(command)
173
+ # Check both original and stripped versions
174
+ for cmd in (command, stripped):
175
+ for pattern, message in DANGEROUS_PATTERNS:
176
+ if re.search(pattern, cmd, re.IGNORECASE):
177
+ return True, message
104
178
  return False, ""
105
179
 
106
180
 
@@ -127,9 +201,9 @@ def main():
127
201
  # Fail closed: can't parse means can't verify safety
128
202
  sys.exit(2)
129
203
  except Exception as e:
130
- # Log error but don't block on hook failure
204
+ # Fail closed: unexpected errors should block, not allow
131
205
  print(f"Hook error: {e}", file=sys.stderr)
132
- sys.exit(0)
206
+ sys.exit(2)
133
207
 
134
208
 
135
209
  if __name__ == "__main__":
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "git-workflow",
3
+ "description": "Standalone git workflow: review, commit, push, PR creation, and PR review",
4
+ "author": {
5
+ "name": "AnExiledDev"
6
+ }
7
+ }
@@ -0,0 +1,125 @@
1
+ # git-workflow
2
+
3
+ Claude Code plugin that provides standalone git workflow commands. Not tied to the EARS ticket lifecycle — works independently, but optionally links to tickets when context exists.
4
+
5
+ ## What It Does
6
+
7
+ Provides two slash commands for shipping code and reviewing pull requests.
8
+
9
+ ### Slash Commands
10
+
11
+ | Command | Description |
12
+ |---------|-------------|
13
+ | `/ship` | Review all changes, commit with a detailed message, push, and optionally create a PR |
14
+ | `/pr:review` | Review an existing PR by number/URL or auto-detect from current branch (never merges) |
15
+
16
+ ## How It Works
17
+
18
+ ### `/ship` Workflow
19
+
20
+ ```text
21
+ /ship [optional commit message hint]
22
+
23
+ └─→ Gather context (git status, diff, branch, project rules)
24
+
25
+ └─→ Full review (security, rules, quality, architecture, tests)
26
+
27
+ └─→ Present findings → User decisions (fix/issue/ignore)
28
+
29
+ └─→ Draft commit message → User approval
30
+
31
+ └─→ Commit + Push
32
+
33
+ └─→ AskUserQuestion: "Create a PR?"
34
+
35
+ ├─→ Yes: Create PR (+ link ticket if context exists)
36
+ └─→ No: Done
37
+ ```
38
+
39
+ ### `/pr:review` Workflow
40
+
41
+ ```text
42
+ /pr:review [PR number, URL, or omit for auto-detect]
43
+
44
+ └─→ Identify target PR (argument, auto-detect, or ask)
45
+
46
+ └─→ Fetch PR details + diff + changed files
47
+
48
+ └─→ Aggressive analysis (attack surface, threats, deps, rules, architecture, quality, tests, breaking changes)
49
+
50
+ └─→ Present findings → User decisions (note/issue/ignore)
51
+
52
+ └─→ Post review comment (NEVER approve/merge)
53
+ ```
54
+
55
+ ### Ticket Awareness
56
+
57
+ Both commands are **optionally ticket-aware**:
58
+ - If a ticket number exists in the session context (from a prior `/ticket:work` call), it is linked in commit messages, PRs, and issue comments
59
+ - If reviewing a PR that references a ticket in its body (`Closes #N`, `Refs #N`), requirements are verified against the diff
60
+ - Neither command prompts for a ticket — they work fully standalone
61
+
62
+ ### Review Depth
63
+
64
+ | Command | Review Depth | Purpose |
65
+ |---------|-------------|---------|
66
+ | `/ship` | Full (same as `/ticket:review-commit`) | Pre-commit gate — catches issues before they enter history |
67
+ | `/pr:review` | Aggressive (same as `/ticket:create-pr`) | Final gate — deep security, threat modeling, and architecture review |
68
+
69
+ ### Finding Severity Levels
70
+
71
+ | Level | Meaning |
72
+ |-------|---------|
73
+ | Critical | Active vulnerability, data exposure, auth bypass, breaking production |
74
+ | High | Security weakness, significant bug, major pattern violation |
75
+ | Medium | Code smell, minor vulnerability, missing validation |
76
+ | Low | Style, optimization, minor improvements |
77
+ | Info | Observations, questions, future considerations |
78
+
79
+ ## Installation
80
+
81
+ ### CodeForge DevContainer
82
+
83
+ Pre-installed and activated automatically — no setup needed.
84
+
85
+ ### From GitHub
86
+
87
+ Use this plugin in any Claude Code setup:
88
+
89
+ 1. Clone the [CodeForge](https://github.com/AnExiledDev/CodeForge) repository:
90
+
91
+ ```bash
92
+ git clone https://github.com/AnExiledDev/CodeForge.git
93
+ ```
94
+
95
+ 2. Enable the plugin in your `.claude/settings.json`:
96
+
97
+ ```json
98
+ {
99
+ "enabledPlugins": {
100
+ "git-workflow@<clone-path>/.devcontainer/plugins/devs-marketplace": true
101
+ }
102
+ }
103
+ ```
104
+
105
+ Replace `<clone-path>` with the absolute path to your CodeForge clone.
106
+
107
+ ## Plugin Structure
108
+
109
+ ```text
110
+ git-workflow/
111
+ ├── .claude-plugin/
112
+ │ └── plugin.json # Plugin metadata
113
+ ├── skills/
114
+ │ ├── ship/
115
+ │ │ └── SKILL.md # /ship command definition
116
+ │ └── pr-review/
117
+ │ └── SKILL.md # /pr:review command definition
118
+ └── README.md # This file
119
+ ```
120
+
121
+ ## Requirements
122
+
123
+ - Claude Code with plugin command support
124
+ - [GitHub CLI](https://cli.github.com/) (`gh`) installed and authenticated
125
+ - A GitHub repository as the working context