File size: 3,963 Bytes
b67a1e9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #!/usr/bin/env python3
from intake_common import *
def job_for(p):
pid = p["project_id"]
job_id = f"pit-{pid}-review"
outdir = f"jobs/done/{job_id}"
return {
"job_id": job_id,
"project_name": p["name"],
"project_path": p["path"],
"mode": "review_only",
"task_type": "review",
"objective": f"Read-only handoff for {p['name']}: collapse open mental tabs into one verified next action.",
"allowed_actions": [
"read non-secret project files",
"read ProjectIntakeTower evidence and project card",
"run non-destructive metadata commands only when needed",
"write result artifacts inside ProjectIntakeTower/jobs/done/<job_id>/ only",
],
"forbidden_actions": [
"modify project files",
"delete files",
"commit",
"push",
"merge",
"read or print secrets",
"create GitHub issues",
"run dependency installs or build steps that write into the project",
],
"allowed_files": [
f"{p['path']}/** read-only, excluding secrets and ignored dependency/build directories",
f"{str(ROOT)}/inventory/project_cards/{pid}.md read-only",
f"{str(ROOT)}/{p.get('evidence_file')} read-only",
f"{str(ROOT)}/{outdir}/** write",
],
"expected_artifacts": [
f"{outdir}/result.json",
f"{outdir}/handoff.md",
],
"required_artifacts": [
f"{outdir}/result.json",
f"{outdir}/handoff.md",
],
"verifier_commands": [
f"python3 verifier/verify_artifacts.py --job jobs/pending/{job_id}.json --require-done"
],
"verifier": {"type": "command", "command": f"python3 verifier/verify_artifacts.py --job jobs/pending/{job_id}.json --require-done"},
"stop_conditions": [
"credentials required",
"write outside ProjectIntakeTower needed",
"destructive action needed",
"project ownership or intent unclear",
"secret-like file must be opened to proceed",
],
"scope": {
"allowed_paths": [p["path"], str(ROOT)],
"allowed_tools": ["read_file", "search_files", "terminal", "write_file"],
"allowed_actions": ["read-only inspection", "write handoff artifacts under ProjectIntakeTower/jobs/done"],
"forbidden_actions": ["modify source project", "commit", "push", "merge", "delete", "read secrets", "create issues"],
},
"inputs": {
"project_card": f"inventory/project_cards/{pid}.md",
"evidence_file": p.get("evidence_file"),
"triage_status": p.get("triage_status"),
"score": p.get("score"),
},
"timeout_minutes": 30,
"max_iterations": 2,
"if_blocked": "write status=needs_human in result.json and stop",
"rejoin_policy": "summarize status, changed_files, artifact_paths, verifier result, needs_human, next_action",
}
def main():
ensure_dirs()
# Pending contracts are generated artifacts owned by this harness; clear stale v0 contracts before writing v1.
for old in PENDING.glob("*.json"):
old.unlink()
projects = sorted(load_jsonl(INV / "projects.jsonl"), key=project_sort_key)
selected = [p for p in projects if p.get("triage_status") in {"needs_human", "active", "quick_win", "review"}]
if len(selected) < min(20, len(projects)):
selected = projects[:min(40, len(projects))]
else:
selected = selected[:40]
for p in selected:
job = job_for(p)
(PENDING / f"{job['job_id']}.json").write_text(json.dumps(job, ensure_ascii=False, indent=2), encoding="utf-8")
print(json.dumps({"status": "succeeded", "jobs_pending_written": len(selected)}, indent=2))
if __name__ == "__main__":
main()
|