MCPcopy Create free account
hub / github.com/boringstack-xyz/boringstack / main

Function main

tools/spec-loop/hooks/solo_spec_gate.py:144–182  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

142
143
144def main() -> None:
145 try:
146 payload = json.load(sys.stdin)
147 except Exception:
148 allow("No hook payload parsed; fail open.")
149
150 cwd = Path.cwd()
151 spec = find_spec(cwd)
152 if spec is None:
153 allow("No .specs/next.md found in this project; spec loop not active.")
154
155 root = project_root_for(spec)
156 paths = extract_paths(payload, root)
157 if not paths:
158 allow("No file path detected.")
159
160 if not any(is_source(path) for path in paths):
161 allow("Specs, tests, docs, config, and workflow files are allowed before approval.")
162
163 try:
164 text = spec.read_text(encoding="utf-8")
165 except (OSError, UnicodeDecodeError) as exc:
166 # Fail open: spec exists but we can't read it cleanly. Better to let
167 # the human notice the issue than to lock the project out.
168 allow(f"Spec found but unreadable ({exc.__class__.__name__}); failing open.")
169
170 if len(text.splitlines()) > MAX_SPEC_LINES:
171 block(
172 f"Source write blocked: {spec.relative_to(root)} is over "
173 f"{MAX_SPEC_LINES} lines. Shrink the slice; don't add ceremony."
174 )
175
176 if not is_approved(text):
177 block(
178 f"Source write blocked. Review {spec.relative_to(root)}, then "
179 "run your spec slash command with `approve` (Claude Code plugin: `/solo-spec-loop:spec approve`) once you have explicitly approved the slice."
180 )
181
182 allow("Approved micro-spec found; source writes allowed for this slice.")
183
184
185if __name__ == "__main__":

Callers 1

solo_spec_gate.pyFile · 0.70

Calls 7

find_specFunction · 0.85
project_root_forFunction · 0.85
extract_pathsFunction · 0.85
is_sourceFunction · 0.85
is_approvedFunction · 0.85
allowFunction · 0.70
blockFunction · 0.70

Tested by

no test coverage detected