codeforge-dev 1.9.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/.env +3 -0
- package/.devcontainer/CHANGELOG.md +125 -0
- package/.devcontainer/CLAUDE.md +41 -11
- package/.devcontainer/README.md +73 -3
- package/.devcontainer/config/defaults/main-system-prompt.md +187 -201
- package/.devcontainer/config/defaults/rules/session-search.md +66 -0
- package/.devcontainer/config/defaults/rules/spec-workflow.md +48 -13
- package/.devcontainer/config/defaults/settings.json +2 -1
- package/.devcontainer/config/defaults/writing-system-prompt.md +143 -0
- package/.devcontainer/config/file-manifest.json +12 -0
- package/.devcontainer/connect-external-terminal.sh +17 -17
- package/.devcontainer/devcontainer.json +150 -144
- package/.devcontainer/features/ccms/README.md +50 -0
- package/.devcontainer/features/ccms/devcontainer-feature.json +21 -0
- package/.devcontainer/features/ccms/install.sh +105 -0
- package/.devcontainer/features/ccstatusline/install.sh +24 -2
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +8 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +5 -3
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +7 -7
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +1 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +22 -12
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +11 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/skill-suggester.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/advisory-test-runner.py +186 -13
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/git-state-injector.py +15 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/inject-cwd.py +37 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +24 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/spec-reminder.py +4 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/SKILL.md +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-build/SKILL.md +353 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-build/references/review-checklist.md +175 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-check/SKILL.md +28 -15
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/SKILL.md +16 -13
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/backlog-template.md +19 -3
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/milestones-template.md +32 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/SKILL.md +28 -20
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/references/template.md +35 -6
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-refine/SKILL.md +194 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-review/SKILL.md +229 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-update/SKILL.md +24 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +20 -13
- package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +38 -5
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/__pycache__/guard-workspace-scope.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +132 -0
- package/.devcontainer/scripts/check-setup.sh +24 -25
- package/.devcontainer/scripts/setup-aliases.sh +95 -90
- package/.devcontainer/scripts/setup-projects.sh +172 -131
- package/.devcontainer/scripts/setup-terminal.sh +48 -0
- package/.devcontainer/scripts/setup-update-claude.sh +49 -107
- package/.devcontainer/scripts/setup.sh +4 -17
- package/README.md +2 -2
- package/package.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/roadmap-template.md +0 -13
package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-review/SKILL.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-review
|
|
3
|
+
description: >-
|
|
4
|
+
This skill should be used when the user asks to "review the spec",
|
|
5
|
+
"check spec adherence", "verify implementation", "spec-review",
|
|
6
|
+
"does code match spec", "audit implementation", or needs a standalone
|
|
7
|
+
deep implementation review that reads the code and confirms full
|
|
8
|
+
adherence to a specification.
|
|
9
|
+
version: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Spec Implementation Review
|
|
13
|
+
|
|
14
|
+
## Mental Model
|
|
15
|
+
|
|
16
|
+
A spec is a contract — but contracts only matter if someone verifies them. `/spec-review` is the verification step: given a spec and the code that claims to implement it, does the code actually do what the spec says?
|
|
17
|
+
|
|
18
|
+
This is a standalone, single-spec, deep implementation review. Unlike `/spec-check` (which audits metadata health across all specs without reading code) and unlike `/spec-build` Phase 4 (which is locked inside the build workflow), `/spec-review` can be invoked independently at any time after implementation exists.
|
|
19
|
+
|
|
20
|
+
Use cases:
|
|
21
|
+
|
|
22
|
+
- **Manual implementation** — you built a feature without `/spec-build` and want to verify the work before running `/spec-update`
|
|
23
|
+
- **Post-change regression check** — re-verify after modifying an already-implemented feature
|
|
24
|
+
- **Pre-release audit** — confirm a feature still matches its spec before shipping
|
|
25
|
+
- **Onboarding verification** — check if what's in the code matches what the spec says
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Lifecycle positioning:
|
|
29
|
+
|
|
30
|
+
/spec-new → /spec-refine → implement (manually or via /spec-build) → /spec-review → /spec-update
|
|
31
|
+
|
|
32
|
+
Or with /spec-build (which has its own Phase 4):
|
|
33
|
+
/spec-new → /spec-refine → /spec-build (includes review) → done
|
|
34
|
+
|
|
35
|
+
/spec-review is independent — usable at any time after implementation exists.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Relationship to Other Skills
|
|
41
|
+
|
|
42
|
+
| Skill | What it does | How `/spec-review` differs |
|
|
43
|
+
|-------|-------------|---------------------------|
|
|
44
|
+
| `/spec-check` | Batch metadata audit (all specs, no code reading) | Single-spec deep code audit |
|
|
45
|
+
| `/spec-build` Phase 4 | Same depth, but embedded in the build workflow | Standalone, invokable independently |
|
|
46
|
+
| `/spec-update` | Updates spec metadata after implementation | `/spec-review` audits first, then recommends `/spec-update` |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Spec Edits During Review
|
|
51
|
+
|
|
52
|
+
`/spec-review` makes limited spec edits — just enough to record what it verified:
|
|
53
|
+
|
|
54
|
+
- Upgrade `[ ]` or `[~]` → `[x]` for criteria verified by passing tests
|
|
55
|
+
- Downgrade `[x]` → `[ ]` if a previously-verified criterion now fails (regression)
|
|
56
|
+
- Add entries to `## Discrepancies` for gaps found
|
|
57
|
+
- Update `## Key Files` if paths are stale (files moved/deleted/added)
|
|
58
|
+
- Update `**Last Updated:**` date
|
|
59
|
+
|
|
60
|
+
It does NOT change `**Status:**` or add `## Implementation Notes` — that's `/spec-update`'s job. Clear boundary: `/spec-review` verifies and records findings; `/spec-update` closes the loop.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Workflow
|
|
65
|
+
|
|
66
|
+
### Step 1: Discovery
|
|
67
|
+
|
|
68
|
+
**Find the spec.** Match `$ARGUMENTS` (feature name or path) against:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Glob: .specs/**/*.md
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If ambiguous, list matching specs and ask which one to review.
|
|
75
|
+
|
|
76
|
+
**Read the full spec.** Extract:
|
|
77
|
+
|
|
78
|
+
- All FR-* and NFR-* requirements with their EARS-format text
|
|
79
|
+
- All acceptance criteria with current markers (`[ ]`, `[~]`, `[x]`)
|
|
80
|
+
- Key Files — every file path listed
|
|
81
|
+
- Out of Scope — boundaries to respect
|
|
82
|
+
- Discrepancies — any existing entries
|
|
83
|
+
|
|
84
|
+
**Gate check.** `/spec-review` works on any spec with implementation to review:
|
|
85
|
+
|
|
86
|
+
| Approval | Status | Action |
|
|
87
|
+
|----------|--------|--------|
|
|
88
|
+
| `user-approved` | `planned` | Proceed (reviewing work done against approved spec) |
|
|
89
|
+
| `user-approved` | `partial` or `implemented` | Proceed (re-reviewing) |
|
|
90
|
+
| `draft` | any | **Warn**: "This spec is `draft`. Requirements may not be validated. Consider running `/spec-refine` first. Proceed anyway?" |
|
|
91
|
+
|
|
92
|
+
Unlike `/spec-build` which hard-blocks on `draft` (because it's about to write code), `/spec-review` is read-heavy — reviewing existing code against a draft spec is still useful, even if the spec itself isn't finalized.
|
|
93
|
+
|
|
94
|
+
**Read every Key File.** Read all files listed in the spec's `## Key Files` section. These are the files the spec author identified as implementing the feature. Understanding them is prerequisite to the audit.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### Step 2: Requirement Coverage Audit
|
|
99
|
+
|
|
100
|
+
Walk every FR-* and NFR-* requirement from the spec. Use the Spec Implementation Review Checklist at `spec-build/references/review-checklist.md` sections 4A and 4D as the authoritative guide.
|
|
101
|
+
|
|
102
|
+
**For each FR-* requirement:**
|
|
103
|
+
|
|
104
|
+
1. Identify the file(s) and function(s) that implement it
|
|
105
|
+
2. Verify the implementation matches the EARS-format requirement text
|
|
106
|
+
3. Confirm the requirement is fully addressed (not partially)
|
|
107
|
+
4. Note if the requirement was met through a different approach than planned
|
|
108
|
+
|
|
109
|
+
**For each NFR-* requirement:**
|
|
110
|
+
|
|
111
|
+
1. Identify how the non-functional requirement is enforced
|
|
112
|
+
2. Verify measurable NFRs have been tested or measured
|
|
113
|
+
3. Confirm the NFR is met under expected conditions, not just ideal conditions
|
|
114
|
+
|
|
115
|
+
**Cross-checks:**
|
|
116
|
+
|
|
117
|
+
- Every FR-* has corresponding code — no requirements were skipped
|
|
118
|
+
- Every NFR-* has corresponding enforcement — no hand-waving
|
|
119
|
+
- No code was written that doesn't map to a requirement (scope creep check)
|
|
120
|
+
- Out of Scope items from the spec were NOT implemented
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Step 3: Acceptance Criteria Verification
|
|
125
|
+
|
|
126
|
+
For each acceptance criterion, locate or write the corresponding test. Use the Spec Implementation Review Checklist at `spec-build/references/review-checklist.md` sections 4B and 4C as the authoritative guide.
|
|
127
|
+
|
|
128
|
+
**For each criterion:**
|
|
129
|
+
|
|
130
|
+
1. Locate the corresponding test (unit, integration, or manual verification)
|
|
131
|
+
2. If no test exists: **write one** — verification requires evidence, "no test exists" is not a valid review outcome
|
|
132
|
+
3. Run the test
|
|
133
|
+
4. If test passes → upgrade marker to `[x]` in the spec
|
|
134
|
+
5. If test fails → note the failure, set marker to `[ ]`, document the issue
|
|
135
|
+
|
|
136
|
+
**Summary checks:**
|
|
137
|
+
|
|
138
|
+
- Count total criteria vs. verified `[x]` — report the ratio
|
|
139
|
+
- Flag any criteria still `[ ]` (not started or regressed)
|
|
140
|
+
- Flag any criteria that cannot be tested — document why and note as discrepancy
|
|
141
|
+
- Verify tests actually test the criterion, not just exercise the code path
|
|
142
|
+
|
|
143
|
+
**Code quality spot-check** per checklist section 4C:
|
|
144
|
+
|
|
145
|
+
- Error handling at appropriate boundaries
|
|
146
|
+
- No hardcoded values that should be configurable
|
|
147
|
+
- Functions short and single-purpose
|
|
148
|
+
- Nesting depth within limits
|
|
149
|
+
- No regressions in existing tests
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Step 4: Report & Spec Updates
|
|
154
|
+
|
|
155
|
+
#### Summary Report
|
|
156
|
+
|
|
157
|
+
Present a structured report:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
## Spec Implementation Review
|
|
161
|
+
|
|
162
|
+
**Spec:** [feature name] ([spec file path])
|
|
163
|
+
**Date:** YYYY-MM-DD
|
|
164
|
+
**Reviewer:** /spec-review
|
|
165
|
+
|
|
166
|
+
### Requirement Coverage
|
|
167
|
+
- Functional: N/M addressed
|
|
168
|
+
- Non-Functional: N/M addressed
|
|
169
|
+
- Gaps: [list or "None"]
|
|
170
|
+
|
|
171
|
+
### Acceptance Criteria
|
|
172
|
+
- [x] Verified: N
|
|
173
|
+
- [~] Implemented, pending: N
|
|
174
|
+
- [ ] Not started / regressed: N
|
|
175
|
+
- Failures: [list or "None"]
|
|
176
|
+
|
|
177
|
+
### Code Quality
|
|
178
|
+
- Issues found: [list or "None"]
|
|
179
|
+
- Regressions: [list or "None"]
|
|
180
|
+
|
|
181
|
+
### Spec Consistency
|
|
182
|
+
- Key Files updates needed: [list or "None"]
|
|
183
|
+
- Discrepancies: [list or "None"]
|
|
184
|
+
|
|
185
|
+
### Recommendation
|
|
186
|
+
[ ] All clear — run `/spec-update` to close the loop
|
|
187
|
+
[ ] Fix issues first: [specific list]
|
|
188
|
+
[ ] Requires user input: [specific questions]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Spec Edits
|
|
192
|
+
|
|
193
|
+
Apply limited edits to the spec file:
|
|
194
|
+
|
|
195
|
+
1. **Acceptance criteria markers** — update based on test results:
|
|
196
|
+
- Passed tests: upgrade `[ ]` or `[~]` → `[x]`
|
|
197
|
+
- Failed tests: downgrade `[x]` → `[ ]` (regression), keep `[ ]` or `[~]` as-is
|
|
198
|
+
2. **Discrepancies** — add entries for any gaps found between spec and implementation
|
|
199
|
+
3. **Key Files** — update paths if files moved, were deleted, or new files were created
|
|
200
|
+
4. **Last Updated** — set to today's date
|
|
201
|
+
|
|
202
|
+
Do NOT modify `**Status:**` or `## Implementation Notes` — those are `/spec-update`'s responsibility.
|
|
203
|
+
|
|
204
|
+
#### Next Action
|
|
205
|
+
|
|
206
|
+
Based on the review outcome, recommend:
|
|
207
|
+
|
|
208
|
+
- **All clear**: "Run `/spec-update` to close the loop and mark the spec as implemented."
|
|
209
|
+
- **Issues found**: "Fix the issues listed above, then re-run `/spec-review` to verify."
|
|
210
|
+
- **User input needed**: Present specific questions and wait for direction.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Ambiguity Policy
|
|
215
|
+
|
|
216
|
+
- If `$ARGUMENTS` matches multiple specs, list them and ask which to review.
|
|
217
|
+
- If a spec has no acceptance criteria, warn and offer to review requirements only.
|
|
218
|
+
- If Key Files reference paths that don't exist, flag them as stale in the report and update the spec's Key Files section.
|
|
219
|
+
- If the spec has no requirements section, warn that there's nothing to audit against and suggest running `/spec-new` or `/spec-update` to add requirements.
|
|
220
|
+
- If all criteria are already `[x]`, still run the full review — regressions happen.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Anti-Patterns
|
|
225
|
+
|
|
226
|
+
- **Skipping test verification**: Marking criteria as `[x]` without running actual tests. Every `[x]` must be backed by a passing test or confirmed behavior.
|
|
227
|
+
- **Reviewing without reading code**: The review must read the implementation files, not just check metadata. That's what `/spec-check` is for.
|
|
228
|
+
- **Modifying implementation**: `/spec-review` is a review, not a fix. Report issues; don't fix them. The user decides what to do next.
|
|
229
|
+
- **Changing spec status**: `/spec-review` records findings. `/spec-update` changes status. Respect the boundary.
|
package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-update/SKILL.md
CHANGED
|
@@ -18,6 +18,18 @@ This is not optional. Every implementation ends with a spec update.
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
## Approval Gate
|
|
22
|
+
|
|
23
|
+
Before performing an as-built update, check the spec's `**Approval:**` status:
|
|
24
|
+
- If `user-approved` → proceed with the update
|
|
25
|
+
- If `draft` → warn the user: "This spec is still `draft`. It should have gone through `/spec-refine` before implementation. Run `/spec-refine` now to validate, or proceed with the as-built update if the user confirms."
|
|
26
|
+
|
|
27
|
+
This is a warning, not a blocker — the user decides whether to refine first or update as-is.
|
|
28
|
+
|
|
29
|
+
For manually-implemented features (not using `/spec-build`), consider running `/spec-review` first to verify implementation adherence before updating the spec.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
21
33
|
## The 6-Step Workflow
|
|
22
34
|
|
|
23
35
|
### Step 1: Find the Spec
|
|
@@ -46,6 +58,7 @@ Review each acceptance criterion in the spec:
|
|
|
46
58
|
- Mark as `[x]` if the criterion is met and verified (tests pass, behavior confirmed)
|
|
47
59
|
- Leave as `[ ]` if not yet implemented
|
|
48
60
|
- Add a note next to deferred criteria explaining why
|
|
61
|
+
- If a criterion is marked `[~]` (implemented but not yet verified from a `/spec-build` run), treat it as `[ ]` — verify it now and upgrade to `[x]` if confirmed, or leave as `[ ]` if unverifiable
|
|
49
62
|
|
|
50
63
|
If criteria were met through different means than originally planned, note the deviation.
|
|
51
64
|
|
|
@@ -71,7 +84,9 @@ Verify paths exist before listing them. Use absolute project-relative paths.
|
|
|
71
84
|
### Step 6: Update Metadata
|
|
72
85
|
|
|
73
86
|
- Set `**Last Updated:**` to today's date (YYYY-MM-DD)
|
|
74
|
-
- Verify `**
|
|
87
|
+
- Verify `**Domain:**` is correct
|
|
88
|
+
- Preserve the `**Approval:**` status — do NOT downgrade `user-approved` to `draft`
|
|
89
|
+
- If the as-built update introduces new decisions not in the original spec, add them to `## Resolved Questions` if the user confirmed them, or `## Open Questions` if they were assumed during implementation
|
|
75
90
|
|
|
76
91
|
---
|
|
77
92
|
|
|
@@ -109,7 +124,11 @@ Before finishing the update:
|
|
|
109
124
|
- [ ] Implementation Notes document deviations from original spec
|
|
110
125
|
- [ ] File paths in Key Files are accurate and verified
|
|
111
126
|
- [ ] Last Updated date is today
|
|
112
|
-
- [ ]
|
|
127
|
+
- [ ] `**Domain:**` is correct for the spec's location
|
|
128
|
+
- [ ] `**Approval:**` status is preserved (not downgraded)
|
|
129
|
+
- [ ] New implementation decisions are tracked in Resolved Questions or Open Questions
|
|
130
|
+
- [ ] If the spec has grown past ~200 lines, note it and suggest splitting into separate specs in the domain folder
|
|
131
|
+
- [ ] If `**Approval:**` is still `draft`, user was warned and confirmed proceeding
|
|
113
132
|
- [ ] No source code was pasted inline (references only)
|
|
114
133
|
|
|
115
134
|
---
|
|
@@ -122,3 +141,6 @@ Before finishing the update:
|
|
|
122
141
|
requirements to match what was built.
|
|
123
142
|
- If acceptance criteria are ambiguous about whether they're met, note the
|
|
124
143
|
ambiguity in Discrepancies rather than checking them off optimistically.
|
|
144
|
+
- A spec-reminder advisory hook fires at Stop when code was modified but
|
|
145
|
+
specs weren't updated. If you see "[Spec Reminder]" in context, that's
|
|
146
|
+
the trigger — use this skill to resolve it.
|
|
@@ -30,11 +30,11 @@ Write specifications with a hostile reader in mind -- someone who will interpret
|
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
|
-
## Spec Sizing
|
|
33
|
+
## Spec Sizing Guidelines
|
|
34
34
|
|
|
35
35
|
Specifications are loaded into AI context windows with limited capacity. Design for consumption.
|
|
36
36
|
|
|
37
|
-
**
|
|
37
|
+
**Recommended target:** ~200 lines per spec file. When a spec grows beyond that, consider splitting into sub-specs (one per sub-feature) with a concise overview linking them. Complex features may justify longer specs — completeness matters more than hitting a number.
|
|
38
38
|
|
|
39
39
|
**Reference, don't reproduce:** Never inline source code, SQL DDL, Pydantic models, or TypeScript interfaces. Reference the file path and line range instead. The code is the source of truth — duplicated snippets go stale silently.
|
|
40
40
|
|
|
@@ -176,12 +176,13 @@ Every spec file starts with metadata:
|
|
|
176
176
|
|
|
177
177
|
```
|
|
178
178
|
# Feature: [Name]
|
|
179
|
-
**
|
|
179
|
+
**Domain:** [domain-name]
|
|
180
180
|
**Status:** implemented | partial | planned
|
|
181
181
|
**Last Updated:** YYYY-MM-DD
|
|
182
|
+
**Approval:** draft | user-approved
|
|
182
183
|
```
|
|
183
184
|
|
|
184
|
-
Status tells you whether to trust it, version tells you where it belongs, last-updated tells you when it was last verified.
|
|
185
|
+
Status tells you whether to trust it, version tells you where it belongs, last-updated tells you when it was last verified. Approval tells you whether decisions in the spec have been explicitly validated by the user (`user-approved`) or are AI-generated hypotheses (`draft`).
|
|
185
186
|
|
|
186
187
|
### 1. Problem Statement
|
|
187
188
|
What problem does this feature solve? Who has this problem? What's the cost of not solving it? (2-3 sentences)
|
|
@@ -218,20 +219,22 @@ so that [I can detect suspicious reset patterns].
|
|
|
218
219
|
Use EARS format. Number each requirement for traceability:
|
|
219
220
|
|
|
220
221
|
```markdown
|
|
221
|
-
- FR-1: When a user requests a password reset, the system shall send a reset email
|
|
222
|
+
- FR-1 [assumed]: When a user requests a password reset, the system shall send a reset email
|
|
222
223
|
to the registered email address within 60 seconds.
|
|
223
|
-
- FR-2: The reset link shall contain a cryptographically random token (min 32 bytes).
|
|
224
|
-
- FR-3: If the reset token is expired or already used, then the system shall display
|
|
224
|
+
- FR-2 [assumed]: The reset link shall contain a cryptographically random token (min 32 bytes).
|
|
225
|
+
- FR-3 [assumed]: If the reset token is expired or already used, then the system shall display
|
|
225
226
|
an error message and offer to send a new reset email.
|
|
227
|
+
|
|
228
|
+
Tag each requirement `[assumed]` when first written. Requirements become `[user-approved]` only after explicit user validation via `/spec-refine`.
|
|
226
229
|
```
|
|
227
230
|
|
|
228
231
|
### 5. Non-Functional Requirements
|
|
229
232
|
Performance, security, scalability, accessibility:
|
|
230
233
|
|
|
231
234
|
```markdown
|
|
232
|
-
- NFR-1: The password reset endpoint shall respond within 200ms (p95).
|
|
233
|
-
- NFR-2: Reset tokens shall be stored as bcrypt hashes, not plaintext.
|
|
234
|
-
- NFR-3: The reset flow shall be accessible with screen readers (WCAG 2.1 AA).
|
|
235
|
+
- NFR-1 [assumed]: The password reset endpoint shall respond within 200ms (p95).
|
|
236
|
+
- NFR-2 [assumed]: Reset tokens shall be stored as bcrypt hashes, not plaintext.
|
|
237
|
+
- NFR-3 [assumed]: The reset flow shall be accessible with screen readers (WCAG 2.1 AA).
|
|
235
238
|
```
|
|
236
239
|
|
|
237
240
|
### 6. Edge Cases
|
|
@@ -249,13 +252,16 @@ The cases nobody thinks about until they happen:
|
|
|
249
252
|
### 7. Out of Scope
|
|
250
253
|
Explicit non-goals to prevent scope creep (can reference the Scope section or expand here).
|
|
251
254
|
|
|
252
|
-
### 8.
|
|
255
|
+
### 8. Resolved Questions
|
|
256
|
+
Decisions explicitly approved by the user via `/spec-refine`. Each entry: decision topic, chosen option, options considered, date, brief rationale. This section starts empty and is populated during the refinement process.
|
|
257
|
+
|
|
258
|
+
### 9. Key Files
|
|
253
259
|
Source files most relevant to this feature — paths an implementer should read.
|
|
254
260
|
|
|
255
|
-
###
|
|
261
|
+
### 10. Implementation Notes
|
|
256
262
|
Post-implementation only. Capture deviations from the original spec — what changed and why.
|
|
257
263
|
|
|
258
|
-
###
|
|
264
|
+
### 11. Discrepancies
|
|
259
265
|
Gaps between spec intent and actual build. Prevents the next session from re-planning decided work.
|
|
260
266
|
|
|
261
267
|
---
|
|
@@ -309,6 +315,7 @@ These defaults apply when the user does not specify a preference. State the assu
|
|
|
309
315
|
- **Edge cases:** Always include at least: empty input, maximum input, concurrent access, and external service failure.
|
|
310
316
|
- **Out of scope:** Always include an out-of-scope section, even if brief, to establish boundaries.
|
|
311
317
|
- **Numbering:** Number all requirements (FR-1, NFR-1) for traceability in code reviews and tests.
|
|
318
|
+
- **Approval markers:** All requirements start as `[assumed]`. Only `/spec-refine` with explicit user validation upgrades them to `[user-approved]`. Spec-level `**Approval:**` starts as `draft` and becomes `user-approved` only when all requirements are `[user-approved]`.
|
|
312
319
|
|
|
313
320
|
---
|
|
314
321
|
|
package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json
CHANGED
|
@@ -1,7 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "codeforge-lsp",
|
|
3
|
+
"description": "LSP servers for CodeForge (Python, TypeScript, Go)",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "AnExiledDev"
|
|
6
|
+
},
|
|
7
|
+
"lspServers": {
|
|
8
|
+
"pyright": {
|
|
9
|
+
"command": "pyright-langserver",
|
|
10
|
+
"args": ["--stdio"],
|
|
11
|
+
"extensionToLanguage": {
|
|
12
|
+
".py": "python",
|
|
13
|
+
".pyi": "python"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"typescript": {
|
|
17
|
+
"command": "typescript-language-server",
|
|
18
|
+
"args": ["--stdio"],
|
|
19
|
+
"extensionToLanguage": {
|
|
20
|
+
".ts": "typescript",
|
|
21
|
+
".tsx": "typescriptreact",
|
|
22
|
+
".js": "javascript",
|
|
23
|
+
".jsx": "javascriptreact",
|
|
24
|
+
".mts": "typescript",
|
|
25
|
+
".cts": "typescript",
|
|
26
|
+
".mjs": "javascript",
|
|
27
|
+
".cjs": "javascript"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"gopls": {
|
|
31
|
+
"command": "gopls",
|
|
32
|
+
"args": ["serve"],
|
|
33
|
+
"extensionToLanguage": {
|
|
34
|
+
".go": "go",
|
|
35
|
+
".mod": "go.mod",
|
|
36
|
+
".sum": "go.sum"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
7
40
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Enforce workspace scope for file operations",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PreToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "Read|Write|Edit|NotebookEdit|Glob|Grep",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/guard-workspace-scope.py",
|
|
11
|
+
"timeout": 5
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Enforce workspace scope for file operations.
|
|
4
|
+
|
|
5
|
+
Blocks write operations (Write, Edit, NotebookEdit) to files outside the
|
|
6
|
+
current working directory. Warns on read operations (Read, Glob, Grep)
|
|
7
|
+
outside the working directory. Allows unrestricted access when cwd is
|
|
8
|
+
/workspaces (the workspace root).
|
|
9
|
+
|
|
10
|
+
Exit code 2 blocks the operation with an error message.
|
|
11
|
+
Exit code 0 allows the operation to proceed (with optional warning context).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
# Paths that are always allowed regardless of working directory
|
|
19
|
+
ALLOWED_PREFIXES = [
|
|
20
|
+
"/workspaces/.claude/",
|
|
21
|
+
"/workspaces/.tmp/",
|
|
22
|
+
"/workspaces/.devcontainer/",
|
|
23
|
+
"/tmp/",
|
|
24
|
+
"/home/",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
WRITE_TOOLS = {"Write", "Edit", "NotebookEdit"}
|
|
28
|
+
READ_TOOLS = {"Read", "Glob", "Grep"}
|
|
29
|
+
|
|
30
|
+
# Tool input field that contains the target path
|
|
31
|
+
PATH_FIELDS = {
|
|
32
|
+
"Read": "file_path",
|
|
33
|
+
"Write": "file_path",
|
|
34
|
+
"Edit": "file_path",
|
|
35
|
+
"NotebookEdit": "notebook_path",
|
|
36
|
+
"Glob": "path",
|
|
37
|
+
"Grep": "path",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_target_path(tool_name: str, tool_input: dict) -> str | None:
|
|
42
|
+
"""Extract the target path from tool input.
|
|
43
|
+
|
|
44
|
+
Returns None if no path field is present or the field is empty,
|
|
45
|
+
which means the tool defaults to cwd (always in scope).
|
|
46
|
+
"""
|
|
47
|
+
field = PATH_FIELDS.get(tool_name)
|
|
48
|
+
if not field:
|
|
49
|
+
return None
|
|
50
|
+
return tool_input.get(field) or None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def is_in_scope(resolved_path: str, cwd: str) -> bool:
|
|
54
|
+
"""Check if resolved_path is within the working directory."""
|
|
55
|
+
cwd_prefix = cwd if cwd.endswith("/") else cwd + "/"
|
|
56
|
+
return resolved_path == cwd or resolved_path.startswith(cwd_prefix)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def is_allowlisted(resolved_path: str) -> bool:
|
|
60
|
+
"""Check if resolved_path falls under an allowed prefix."""
|
|
61
|
+
return any(resolved_path.startswith(prefix) for prefix in ALLOWED_PREFIXES)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main():
|
|
65
|
+
try:
|
|
66
|
+
input_data = json.load(sys.stdin)
|
|
67
|
+
tool_name = input_data.get("tool_name", "")
|
|
68
|
+
tool_input = input_data.get("tool_input", {})
|
|
69
|
+
|
|
70
|
+
cwd = os.getcwd()
|
|
71
|
+
|
|
72
|
+
# Unrestricted when working from the workspace root
|
|
73
|
+
if cwd == "/workspaces":
|
|
74
|
+
sys.exit(0)
|
|
75
|
+
|
|
76
|
+
target_path = get_target_path(tool_name, tool_input)
|
|
77
|
+
|
|
78
|
+
# No path specified — tool defaults to cwd, which is in scope
|
|
79
|
+
if target_path is None:
|
|
80
|
+
sys.exit(0)
|
|
81
|
+
|
|
82
|
+
resolved = os.path.realpath(target_path)
|
|
83
|
+
|
|
84
|
+
if is_in_scope(resolved, cwd):
|
|
85
|
+
sys.exit(0)
|
|
86
|
+
|
|
87
|
+
if is_allowlisted(resolved):
|
|
88
|
+
sys.exit(0)
|
|
89
|
+
|
|
90
|
+
# Out of scope
|
|
91
|
+
if tool_name in WRITE_TOOLS:
|
|
92
|
+
print(
|
|
93
|
+
json.dumps(
|
|
94
|
+
{
|
|
95
|
+
"error": (
|
|
96
|
+
f"Blocked: {tool_name} targets '{target_path}' which is "
|
|
97
|
+
f"outside the working directory ({cwd}). Move to that "
|
|
98
|
+
f"project's directory first or work from /workspaces."
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
sys.exit(2)
|
|
104
|
+
|
|
105
|
+
if tool_name in READ_TOOLS:
|
|
106
|
+
print(
|
|
107
|
+
json.dumps(
|
|
108
|
+
{
|
|
109
|
+
"additionalContext": (
|
|
110
|
+
f"Warning: {tool_name} targets '{target_path}' which is "
|
|
111
|
+
f"outside the working directory ({cwd}). This read is "
|
|
112
|
+
f"allowed but may indicate unintended cross-project access."
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
sys.exit(0)
|
|
118
|
+
|
|
119
|
+
# Unknown tool — allow by default
|
|
120
|
+
sys.exit(0)
|
|
121
|
+
|
|
122
|
+
except json.JSONDecodeError:
|
|
123
|
+
# Can't parse input — allow by default
|
|
124
|
+
sys.exit(0)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
# Don't block on hook failure
|
|
127
|
+
print(f"Hook error: {e}", file=sys.stderr)
|
|
128
|
+
sys.exit(0)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
main()
|
|
@@ -5,34 +5,37 @@
|
|
|
5
5
|
echo "CodeForge Setup Check"
|
|
6
6
|
echo "━━━━━━━━━━━━━━━━━━━━"
|
|
7
7
|
|
|
8
|
-
PASS=0
|
|
8
|
+
PASS=0
|
|
9
|
+
FAIL=0
|
|
10
|
+
WARN=0
|
|
9
11
|
|
|
10
12
|
check() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
local label="$1" cmd="$2"
|
|
14
|
+
if eval "$cmd" >/dev/null 2>&1; then
|
|
15
|
+
printf " ✓ %s\n" "$label"
|
|
16
|
+
PASS=$((PASS + 1))
|
|
17
|
+
else
|
|
18
|
+
printf " ✗ %s\n" "$label"
|
|
19
|
+
FAIL=$((FAIL + 1))
|
|
20
|
+
fi
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
warn_check() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
local label="$1" cmd="$2"
|
|
25
|
+
if eval "$cmd" >/dev/null 2>&1; then
|
|
26
|
+
printf " ✓ %s\n" "$label"
|
|
27
|
+
PASS=$((PASS + 1))
|
|
28
|
+
else
|
|
29
|
+
printf " ⚠ %s\n" "$label"
|
|
30
|
+
WARN=$((WARN + 1))
|
|
31
|
+
fi
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
echo ""
|
|
33
35
|
echo "Core:"
|
|
34
36
|
check "Claude Code installed" "command -v claude"
|
|
35
|
-
|
|
37
|
+
warn_check "Claude native binary" "[ -x /usr/local/bin/claude ]"
|
|
38
|
+
check "cc alias configured" "grep -q 'alias cc=' ~/.bashrc 2>/dev/null || grep -q 'alias cc=' ~/.zshrc 2>/dev/null"
|
|
36
39
|
check "Config directory exists" "[ -d '${CLAUDE_CONFIG_DIR:-/workspaces/.claude}' ]"
|
|
37
40
|
check "Settings file exists" "[ -f '${CLAUDE_CONFIG_DIR:-/workspaces/.claude}/settings.json' ]"
|
|
38
41
|
|
|
@@ -54,10 +57,6 @@ echo ""
|
|
|
54
57
|
echo "Development:"
|
|
55
58
|
warn_check "biome" "command -v biome"
|
|
56
59
|
warn_check "ruff" "command -v ruff"
|
|
57
|
-
warn_check "dprint" "command -v dprint"
|
|
58
|
-
warn_check "shfmt" "command -v shfmt"
|
|
59
|
-
warn_check "shellcheck" "command -v shellcheck"
|
|
60
|
-
warn_check "hadolint" "command -v hadolint"
|
|
61
60
|
warn_check "ast-grep" "command -v ast-grep"
|
|
62
61
|
warn_check "tmux" "command -v tmux"
|
|
63
62
|
|
|
@@ -66,7 +65,7 @@ echo "━━━━━━━━━━━━━━━━━━━━"
|
|
|
66
65
|
echo " $PASS passed, $FAIL failed, $WARN warnings"
|
|
67
66
|
|
|
68
67
|
if [ $FAIL -gt 0 ]; then
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
echo ""
|
|
69
|
+
echo " Run 'cc-tools' for detailed version info."
|
|
70
|
+
exit 1
|
|
72
71
|
fi
|