app
AI Flow
Public Made by Adomby adom
Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board.
← Commit history
Count component-review evidence as continuation progress while ignoring activity timestamps
3 files changed
+32
docs/codex-supervisor.md+2@@ -24,3 +24,5 @@ On **any** user pause or cancellation, the AI must run `pause` immediately befor State and receipts live in `<run>/supervisor/{status,state,pause}.json` and `events.jsonl`. A process PID alone is not proof it is alive: check the last check time and the process. A `start-acknowledged` receipt is not proof the model completed subsequent work. Verify the next turn in the same conversation. No engineering gate, board or acceptance limit is changed by this helper. Validation: eleven policy/dispatch tests cover active/approval states, explicit pause, failed/interrupted turns, completion, malformed guards, queue interference, duplicate suppression, uncertain dispatch, state races and no-progress. Live metadata discovery was verified against Codex 0.154.0-alpha.6.2. Live continuation was observed in the same electronic-load thread: queue/add auto-started its next turn, carrying the exact client message ID. The initial observer incorrectly classified that as a race; it now attributes its own auto-start by client ID, covered by an additional regression test. Source availability, local activation and a packaged release are separate claims.++Component-review progress is included from the run’s `components.json`, excluding activity-only timestamps. This lets evidence and disposition changes count before a PCB mutation. Malformed component JSON fails closed. The three-unchanged-turn pause still applies; adding idle timestamps does not keep a run alive.
tools/continuation/supervisor.py+12@@ -104,6 +104,18 @@ def progress_hash(run, report): data = read(run/'run.json') payload = {k: data.get(k) for k in ['currentStep', 'outcomes', 'boards', 'delivery', 'continuation']} payload['remaining'] = report.get('remaining')+ # Component review is real engineering progress before any board change.+ # Keep activity-only stamps out of the comparison and fail closed on bad JSON.+ register = run/'components.json'+ if register.exists():+ def evidence(value):+ if isinstance(value, dict):+ return {k: evidence(v) for k, v in value.items()+ if k not in {'checkedAt', 'updatedAt', 'createdAt', 'timestamp', 'lastActivityAt'}}+ if isinstance(value, list):+ return [evidence(v) for v in value]+ return value+ payload['componentReview'] = evidence(read(register)) return hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
tools/continuation/test_supervisor.py+18@@ -34,6 +34,24 @@ class PolicyTests(unittest.TestCase): for g in [{},{'decision':'continue','mayStop':True},{'decision':'user-paused'}]: self.assertTrue(self.policy(guard=g).startswith('error')) +class ProgressTests(unittest.TestCase):+ def test_component_review_changes_count_but_activity_does_not(self):+ with tempfile.TemporaryDirectory() as d:+ p = Path(d)+ s.write(p/'run.json', {'currentStep':'components','updatedAt':'old'})+ s.write(p/'components.json', {'components':[{'reference':'Q1','review':{'status':'pending'}}]})+ before = s.progress_hash(p, {'remaining':['libraries']})+ s.write(p/'run.json', {'currentStep':'components','updatedAt':'new'})+ s.write(p/'components.json', {'updatedAt':'new','components':[{'reference':'Q1','review':{'status':'pending','checkedAt':'new'}}]})+ self.assertEqual(before, s.progress_hash(p, {'remaining':['libraries']}))+ s.write(p/'components.json', {'components':[{'reference':'Q1','review':{'status':'stale','geometryEvidence':['lead-hole-review.json']}}]})+ self.assertNotEqual(before, s.progress_hash(p, {'remaining':['libraries']}))+ def test_invalid_component_register_fails_closed(self):+ with tempfile.TemporaryDirectory() as d:+ p=Path(d);s.write(p/'run.json', {})+ (p/'components.json').write_text('{broken')+ with self.assertRaises(ValueError):s.progress_hash(p, {})+ class FakeClient: calls=[] race=False