mirror of
https://github.com/dtzp555-max/memory-continuity.git
synced 2026-07-21 21:15:07 +00:00
Add continuity-guard skill skeleton and doctor script
This commit is contained in:
@@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
name: continuity-guard
|
||||||
|
description: Maintain short-term continuity and anti-silence discipline for OpenClaw agents using memory/CURRENT_STATE.md plus dual reporting rules. Use when creating/updating agent workspaces, after OpenClaw upgrades/restarts, when continuity seems broken, when a session may have lost context, or when you need to doctor/repair CURRENT_STATE coverage and reporting protocol drift across agents.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Continuity Guard
|
||||||
|
|
||||||
|
Use `memory/CURRENT_STATE.md` as a small overwrite-oriented workbench, not as a journal.
|
||||||
|
|
||||||
|
## Core rules
|
||||||
|
|
||||||
|
- Ensure every agent workspace has `memory/CURRENT_STATE.md`
|
||||||
|
- Keep `CURRENT_STATE.md` small
|
||||||
|
- main: target 25-40 lines, hard cap 50
|
||||||
|
- other agents: target 15-25 lines, hard cap 30
|
||||||
|
- Required sections:
|
||||||
|
- `In Flight`
|
||||||
|
- `Blocked / Waiting`
|
||||||
|
- `Recently Finished`
|
||||||
|
- `Next`
|
||||||
|
- `Reset Summary`
|
||||||
|
- Update only on state changes, not on a timer
|
||||||
|
- Remove stale items instead of endlessly appending
|
||||||
|
|
||||||
|
## Dual reporting protocol
|
||||||
|
|
||||||
|
### Worker → main
|
||||||
|
Execution agents must report to main at:
|
||||||
|
- accepted
|
||||||
|
- blocked
|
||||||
|
- milestone
|
||||||
|
- done
|
||||||
|
- model/environment abnormal
|
||||||
|
|
||||||
|
Preferred reply format:
|
||||||
|
- `status`
|
||||||
|
- `summary`
|
||||||
|
- `evidence`
|
||||||
|
- `risk`
|
||||||
|
- `next`
|
||||||
|
|
||||||
|
### main → Tao
|
||||||
|
Main must report to Tao at:
|
||||||
|
- task accepted / formally started
|
||||||
|
- worker dispatched
|
||||||
|
- blocked
|
||||||
|
- milestone reached
|
||||||
|
- task/phase completed
|
||||||
|
|
||||||
|
Preferred Tao update format:
|
||||||
|
- who
|
||||||
|
- status
|
||||||
|
- output
|
||||||
|
- next
|
||||||
|
|
||||||
|
Ordering rule:
|
||||||
|
- When a worker reports milestone/completion/blocker, first update `CURRENT_STATE.md`, then update Tao, then continue with review/commit/next dispatch.
|
||||||
|
- If no evidence point exists yet (sessionKey / commit / branch / PR / log), do not claim work has already started.
|
||||||
|
|
||||||
|
## When to use the doctor
|
||||||
|
Run `scripts/continuity_doctor.py` when:
|
||||||
|
- OpenClaw was upgraded
|
||||||
|
- gateway restarted and continuity feels suspicious
|
||||||
|
- an agent seems to have lost short-term context
|
||||||
|
- you need to confirm `CURRENT_STATE.md` coverage across workspaces
|
||||||
|
|
||||||
|
## How to use the doctor
|
||||||
|
From the main workspace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 skills/continuity-guard/scripts/continuity_doctor.py \
|
||||||
|
--main-workspace /Users/taodeng/.openclaw/workspace/main \
|
||||||
|
--agents-root /Users/taodeng/.openclaw/workspaces
|
||||||
|
```
|
||||||
|
|
||||||
|
The doctor checks:
|
||||||
|
- main `memory/CURRENT_STATE.md` exists
|
||||||
|
- all agent workspaces have `memory/CURRENT_STATE.md`
|
||||||
|
- required sections exist
|
||||||
|
- line-count caps are respected
|
||||||
|
- `AGENTS.md` still contains continuity + dual reporting rules
|
||||||
|
|
||||||
|
## Repair strategy
|
||||||
|
If drift is found:
|
||||||
|
1. Restore/create missing `memory/CURRENT_STATE.md`
|
||||||
|
2. Restore continuity guidance in `AGENTS.md`
|
||||||
|
3. Re-run doctor
|
||||||
|
4. Only then investigate deeper behavioral failures
|
||||||
|
|
||||||
|
## References
|
||||||
|
- For template and limits: read `references/template.md`
|
||||||
|
- For doctor semantics and PASS/WARN/FAIL meanings: read `references/doctor-spec.md`
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# continuity doctor spec
|
||||||
|
|
||||||
|
## PASS
|
||||||
|
The checked item exists and matches the required structure.
|
||||||
|
|
||||||
|
## WARN
|
||||||
|
The item exists but is drifting:
|
||||||
|
- file too long
|
||||||
|
- required text partly missing
|
||||||
|
- structure present but not ideal
|
||||||
|
|
||||||
|
## FAIL
|
||||||
|
The item is missing or materially broken:
|
||||||
|
- missing CURRENT_STATE.md
|
||||||
|
- missing required sections
|
||||||
|
- missing continuity rules in AGENTS.md
|
||||||
|
|
||||||
|
## Minimal checks
|
||||||
|
1. `main/memory/CURRENT_STATE.md` exists
|
||||||
|
2. each agent workspace has `memory/CURRENT_STATE.md`
|
||||||
|
3. every `CURRENT_STATE.md` contains:
|
||||||
|
- `## In Flight`
|
||||||
|
- `## Blocked / Waiting`
|
||||||
|
- `## Recently Finished`
|
||||||
|
- `## Next`
|
||||||
|
- `## Reset Summary`
|
||||||
|
4. main `AGENTS.md` contains continuity guidance and dual reporting protocol markers
|
||||||
|
5. line-count caps are respected
|
||||||
|
|
||||||
|
## Suggested actions on failure
|
||||||
|
- create missing files from template
|
||||||
|
- restore missing AGENTS continuity section
|
||||||
|
- trim oversized CURRENT_STATE files
|
||||||
|
- rerun doctor after repair
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# CURRENT_STATE template
|
||||||
|
|
||||||
|
## main agent (expanded)
|
||||||
|
|
||||||
|
```md
|
||||||
|
# CURRENT_STATE
|
||||||
|
|
||||||
|
_Last updated: YYYY-MM-DD HH:MM Australia/Brisbane_
|
||||||
|
|
||||||
|
## In Flight
|
||||||
|
- [status] task — owner — latest milestone
|
||||||
|
|
||||||
|
## Blocked / Waiting
|
||||||
|
- item — blocker / waiting on
|
||||||
|
|
||||||
|
## Recently Finished
|
||||||
|
- result — why it still matters now
|
||||||
|
|
||||||
|
## Next
|
||||||
|
- next action
|
||||||
|
|
||||||
|
## Reset Summary
|
||||||
|
- one short paragraph explaining what matters if a new session starts now
|
||||||
|
```
|
||||||
|
|
||||||
|
Capacity:
|
||||||
|
- target 25-40 lines
|
||||||
|
- hard cap 50 lines
|
||||||
|
- In Flight max 5
|
||||||
|
- Blocked / Waiting max 5
|
||||||
|
- Recently Finished max 3
|
||||||
|
- Next max 5
|
||||||
|
|
||||||
|
## other agents (standard)
|
||||||
|
Use the same template, but keep it smaller.
|
||||||
|
|
||||||
|
Capacity:
|
||||||
|
- target 15-25 lines
|
||||||
|
- hard cap 30 lines
|
||||||
|
- In Flight max 3
|
||||||
|
- Blocked / Waiting max 3
|
||||||
|
- Recently Finished max 2
|
||||||
|
- Next max 3
|
||||||
|
|
||||||
|
## Allowed status values
|
||||||
|
- planned
|
||||||
|
- dispatched
|
||||||
|
- in_progress
|
||||||
|
- blocked
|
||||||
|
- reviewing
|
||||||
|
- done
|
||||||
+143
@@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REQUIRED_SECTIONS = [
|
||||||
|
'## In Flight',
|
||||||
|
'## Blocked / Waiting',
|
||||||
|
'## Recently Finished',
|
||||||
|
'## Next',
|
||||||
|
'## Reset Summary',
|
||||||
|
]
|
||||||
|
|
||||||
|
AGENTS_MARKERS = [
|
||||||
|
'CURRENT_STATE.md - Your Short-Term Workbench',
|
||||||
|
'Dual reporting protocol',
|
||||||
|
'Execution agent → main',
|
||||||
|
'main → Tao',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def result(level: str, msg: str) -> tuple[str, str]:
|
||||||
|
print(f'{level:<5} {msg}')
|
||||||
|
return level, msg
|
||||||
|
|
||||||
|
|
||||||
|
def line_count(path: Path) -> int:
|
||||||
|
try:
|
||||||
|
return len(path.read_text().splitlines())
|
||||||
|
except Exception:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def has_sections(path: Path) -> list[str]:
|
||||||
|
text = path.read_text()
|
||||||
|
missing = [s for s in REQUIRED_SECTIONS if s not in text]
|
||||||
|
return missing
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
ap = argparse.ArgumentParser(description='Check continuity/CURRENT_STATE coverage and drift.')
|
||||||
|
ap.add_argument('--main-workspace', required=True)
|
||||||
|
ap.add_argument('--agents-root', required=True)
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
main_ws = Path(args.main_workspace)
|
||||||
|
agents_root = Path(args.agents_root)
|
||||||
|
|
||||||
|
failures = 0
|
||||||
|
warns = 0
|
||||||
|
|
||||||
|
print('continuity doctor\n')
|
||||||
|
|
||||||
|
# main AGENTS.md
|
||||||
|
agents_md = main_ws / 'AGENTS.md'
|
||||||
|
if not agents_md.exists():
|
||||||
|
failures += 1
|
||||||
|
result('FAIL', f'missing {agents_md}')
|
||||||
|
else:
|
||||||
|
text = agents_md.read_text()
|
||||||
|
missing = [m for m in AGENTS_MARKERS if m not in text]
|
||||||
|
if missing:
|
||||||
|
failures += 1
|
||||||
|
result('FAIL', f'AGENTS continuity markers missing: {", ".join(missing)}')
|
||||||
|
else:
|
||||||
|
result('PASS', 'AGENTS continuity rules present')
|
||||||
|
|
||||||
|
# main CURRENT_STATE
|
||||||
|
main_cs = main_ws / 'memory' / 'CURRENT_STATE.md'
|
||||||
|
if not main_cs.exists():
|
||||||
|
failures += 1
|
||||||
|
result('FAIL', 'main CURRENT_STATE missing')
|
||||||
|
else:
|
||||||
|
missing = has_sections(main_cs)
|
||||||
|
if missing:
|
||||||
|
failures += 1
|
||||||
|
result('FAIL', f'main CURRENT_STATE missing sections: {", ".join(missing)}')
|
||||||
|
else:
|
||||||
|
result('PASS', 'main CURRENT_STATE sections present')
|
||||||
|
n = line_count(main_cs)
|
||||||
|
if n > 50:
|
||||||
|
warns += 1
|
||||||
|
result('WARN', f'main CURRENT_STATE too long: {n} lines (cap 50)')
|
||||||
|
else:
|
||||||
|
result('PASS', f'main CURRENT_STATE length ok: {n} lines')
|
||||||
|
|
||||||
|
# agent workspaces
|
||||||
|
checked = 0
|
||||||
|
missing_files = []
|
||||||
|
missing_sections = []
|
||||||
|
oversize = []
|
||||||
|
|
||||||
|
if agents_root.exists():
|
||||||
|
for ws in sorted([p for p in agents_root.iterdir() if p.is_dir()]):
|
||||||
|
checked += 1
|
||||||
|
cs = ws / 'memory' / 'CURRENT_STATE.md'
|
||||||
|
if not cs.exists():
|
||||||
|
missing_files.append(ws.name)
|
||||||
|
continue
|
||||||
|
missing = has_sections(cs)
|
||||||
|
if missing:
|
||||||
|
missing_sections.append((ws.name, missing))
|
||||||
|
n = line_count(cs)
|
||||||
|
if n > 30:
|
||||||
|
oversize.append((ws.name, n))
|
||||||
|
|
||||||
|
if missing_files:
|
||||||
|
failures += 1
|
||||||
|
result('FAIL', f'agent CURRENT_STATE missing: {", ".join(missing_files)}')
|
||||||
|
else:
|
||||||
|
result('PASS', f'agent CURRENT_STATE files present: {checked}/{checked}')
|
||||||
|
|
||||||
|
if missing_sections:
|
||||||
|
failures += 1
|
||||||
|
details = '; '.join(f'{name}: {", ".join(m)}' for name, m in missing_sections)
|
||||||
|
result('FAIL', f'agent CURRENT_STATE missing sections: {details}')
|
||||||
|
else:
|
||||||
|
result('PASS', 'agent CURRENT_STATE sections present')
|
||||||
|
|
||||||
|
if oversize:
|
||||||
|
warns += 1
|
||||||
|
details = '; '.join(f'{name}: {n} lines' for name, n in oversize)
|
||||||
|
result('WARN', f'agent CURRENT_STATE oversize: {details}')
|
||||||
|
else:
|
||||||
|
result('PASS', 'agent CURRENT_STATE length caps respected')
|
||||||
|
|
||||||
|
print('\nSummary')
|
||||||
|
print(f'- failures: {failures}')
|
||||||
|
print(f'- warnings: {warns}')
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
print('\nSuggested actions:')
|
||||||
|
print('1. create/restore missing CURRENT_STATE files')
|
||||||
|
print('2. restore AGENTS continuity section if missing')
|
||||||
|
print('3. trim oversized CURRENT_STATE files')
|
||||||
|
print('4. rerun continuity doctor')
|
||||||
|
return 2
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
raise SystemExit(main())
|
||||||
Reference in New Issue
Block a user