-
Notifications
You must be signed in to change notification settings - Fork 0
Fix/detector readiness #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
3e76426
fix: wait for the detector between requests, not inside one
inesaranab 7c4226f
fix: do not overwrite a settled job, and size the request as it is pu…
inesaranab d1ba259
fix: bound the detector call below the limit that can actually stop it
inesaranab 27956d4
chore: keep unrelated editor tooling out of this change
inesaranab d216ed0
fix: measure the readiness deadline in elapsed time, and settle atomi…
inesaranab File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| [mcp_servers.linear-server] | ||
| url = "https://mcp.linear.app/mcp" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| { | ||
| "hooks": { | ||
| "PreToolUse": [ | ||
| { | ||
| "matcher": "WebSearch|WebFetch", | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "echo '{\"systemMessage\":\"Scope check - what decision does this research change? If there is no answer, it is a bookmark (INE-18), not a task. Current objective: .claude/FOCUS.md\"}'" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "matcher": "Write|Edit", | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "python3 '/Users/inesarana/screening/.codex/hooks/conventions_reminder.py' 2>/dev/null || true" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "SessionStart": [ | ||
| { | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "cd \"$CLAUDE_PROJECT_DIR\" 2>/dev/null; python3 -c \"import json,pathlib;print(json.dumps({'hookSpecificOutput':{'hookEventName':'SessionStart','additionalContext':pathlib.Path('.claude/FOCUS.md').read_text()}}))\" 2>/dev/null || true" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "UserPromptSubmit": [ | ||
| { | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "python3 -c \"import json,time,pathlib;f=pathlib.Path('/tmp/.claude_last_prompt');now=time.time();prev=float(f.read_text()) if f.exists() else now;f.write_text(str(now));g=int(now-prev);print(json.dumps({'hookSpecificOutput':{'hookEventName':'UserPromptSubmit','additionalContext':'[clock] '+time.strftime('%H:%M')+' | '+str(g//60)+'m '+str(g%60)+'s since previous message'}}))\" 2>/dev/null || true" | ||
| }, | ||
| { | ||
| "type": "command", | ||
| "command": "python3 '/Users/inesarana/screening/.codex/hooks/response_style.py' 2>/dev/null || true" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| """PreToolUse hook: restate the project's writing conventions before an edit. | ||
|
|
||
| Fires on Write and Edit. Emits nothing for files the conventions do not cover, | ||
| so the reminder stays attached to source rather than appearing on every write. | ||
| """ | ||
|
|
||
| import json | ||
| import sys | ||
|
|
||
| _EXTENSIONS = (".py", ".yaml", ".yml", ".md") | ||
|
|
||
| _REMINDER = ( | ||
| "screening-conventions (.claude/skills/screening-conventions/SKILL.md):\n" | ||
| "- Google-style docstrings: summary line, then Args/Returns/Raises for " | ||
| "functions, Attributes for models.\n" | ||
| "- State the PROPERTY, not the incident that taught it. No war stories, " | ||
| "dates, measurements, or 'we' — those belong in infra/*/README.md or the " | ||
| "commit message.\n" | ||
| "- Self-contained: never explain one symbol by referring to another.\n" | ||
| "- No prose constants: explanation assigned to a module-level string is " | ||
| "dead code.\n" | ||
| "- app/domain and app/ports stay vendor-free; adapters hold the vendors.\n" | ||
| "- Test first: a failing test before the implementation." | ||
| ) | ||
|
|
||
|
|
||
| def main() -> None: | ||
| """Print the reminder when the target file is one the conventions govern.""" | ||
| try: | ||
| payload = json.load(sys.stdin) | ||
| except json.JSONDecodeError, ValueError: | ||
| return | ||
| path = payload.get("tool_input", {}).get("file_path", "") | ||
| if not path.endswith(_EXTENSIONS): | ||
| return | ||
| print( | ||
| json.dumps( | ||
| { | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "additionalContext": _REMINDER, | ||
| } | ||
| } | ||
| ) | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| """UserPromptSubmit hook: restate how answers to Ines should be written. | ||
|
|
||
| Emits on every prompt. Carries the response-shape rules only; the writing | ||
| conventions for source files are in conventions_reminder.py. | ||
| """ | ||
|
|
||
| import json | ||
|
|
||
| _REMINDER = ( | ||
| "Response style:\n" | ||
| "- Short. Answer the question asked, then stop.\n" | ||
| "- High level first, in plain words. Then the low-level version, so the " | ||
| "vocabulary is picked up in context rather than assumed.\n" | ||
| "- Define a term the first time it appears, in the same sentence.\n" | ||
| "- No jargon without its plain-language equivalent alongside it." | ||
| ) | ||
|
|
||
|
|
||
| def main() -> None: | ||
| """Print the reminder.""" | ||
| print( | ||
| json.dumps( | ||
| { | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "UserPromptSubmit", | ||
| "additionalContext": _REMINDER, | ||
| } | ||
| } | ||
| ) | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| """Adapter: waiting for the Article 9 detector to start serving. | ||
|
|
||
| The detector scales to zero and takes minutes to load its weights. Platform | ||
| ingress closes any single request long before that, so readiness is established | ||
| by repeating a short request rather than by holding one open. | ||
| """ | ||
|
|
||
| import time | ||
| from collections.abc import Awaitable, Callable | ||
| from typing import Any, Protocol | ||
|
|
||
|
|
||
| class HttpClientLike(Protocol): | ||
| """The subset of an async HTTP client this module uses.""" | ||
|
|
||
| async def get(self, url: str) -> Any: ... | ||
|
|
||
|
|
||
| def http_probe(client: HttpClientLike, url: str) -> Callable[[], Awaitable[bool]]: | ||
| """Build a readiness probe that calls an endpoint over HTTP. | ||
|
|
||
| Args: | ||
| client: Issues the request. Injected so the caller owns its lifetime | ||
| and its per-request timeout. | ||
| url: The endpoint that answers only once the detector is serving. | ||
|
|
||
| Returns: | ||
| A callable returning True when the endpoint answers 200. | ||
| """ | ||
|
|
||
| async def probe() -> bool: | ||
| return (await client.get(url)).status_code == 200 | ||
|
|
||
| return probe | ||
|
|
||
|
|
||
| async def wait_until_ready( | ||
| probe: Callable[[], Awaitable[bool]], | ||
| *, | ||
| deadline_s: float, | ||
| interval_s: float, | ||
| sleep: Callable[[float], Awaitable[None]], | ||
| now: Callable[[], float] = time.monotonic, | ||
| ) -> bool: | ||
| """Repeat a readiness probe until it succeeds or the deadline passes. | ||
|
|
||
| The deadline covers elapsed time, not time spent sleeping. A probe against | ||
| an endpoint that is not listening consumes its own timeout before failing, | ||
| so counting only the intervals would let the total reach a multiple of the | ||
| deadline. | ||
|
|
||
| Args: | ||
| probe: Returns True once the detector is serving. | ||
| deadline_s: How long to keep trying, in seconds. | ||
| interval_s: Seconds between attempts. | ||
| sleep: Suspends for the given seconds. Injected so tests need no real | ||
| time. | ||
| now: Reads a monotonic clock, one that only moves forward and is | ||
| unaffected by the system clock being adjusted. | ||
|
|
||
| Returns: | ||
| True if the detector became ready, False if the deadline passed first. | ||
| """ | ||
| started = now() | ||
| while True: | ||
| try: | ||
| ready = await probe() | ||
| except Exception: # noqa: BLE001 - any failure means "not ready yet" | ||
| # The probe is supplied by the caller, so the ways it can fail are | ||
| # not knowable here. A detector that has not started refuses the | ||
| # connection, which is the expected state while it loads rather | ||
| # than a failure to report. | ||
| ready = False | ||
| if ready: | ||
| return True | ||
| if now() - started + interval_s > deadline_s: | ||
| return False | ||
| await sleep(interval_s) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.