File size: 10,684 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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env python3
from __future__ import annotations

import json
from datetime import datetime, timezone
from pathlib import Path

ROOT = Path('/home/smlflg/Projekte/AgentProjectMinenraeumer/ProjectIntakeTower')
PENDING = ROOT / 'jobs' / 'pending'
DRAFTS = ROOT / 'github' / 'issue_drafts'
TRIAGE = ROOT / 'triage'

PENDING.mkdir(parents=True, exist_ok=True)
DRAFTS.mkdir(parents=True, exist_ok=True)

now = datetime.now(timezone.utc).replace(microsecond=0).isoformat()

common_forbidden = [
    'modify source project files unless Samuel explicitly changes this contract',
    'delete/archive/move source projects',
    'commit', 'push', 'merge',
    'read or print secrets',
    'create GitHub issues',
    'run dependency installs that write into source projects',
]

def job(job_id, project_name, project_path, task_type, objective, extra_allowed, expected, verifier_commands, inputs=None, stop_extra=None, allowed_files_extra=None, mode='review_only'):
    outdir = f'jobs/done/{job_id}'
    return {
        'job_id': job_id,
        'project_name': project_name,
        'project_path': project_path,
        'mode': mode,
        'task_type': task_type,
        'objective': objective,
        'allowed_actions': [
            'read non-secret files in allowed source paths',
            'read ProjectIntakeTower inventory/evidence/triage files',
            'write artifacts only inside ProjectIntakeTower/jobs/done/<job_id>/',
        ] + extra_allowed,
        'forbidden_actions': common_forbidden,
        'allowed_files': [
            f'{project_path}/** read-only, excluding secrets and dependency/build/cache dirs',
            f'{ROOT}/inventory/** read-only',
            f'{ROOT}/triage/** read-only',
            f'{ROOT}/{outdir}/** write',
        ] + (allowed_files_extra or []),
        'expected_artifacts': [f'{outdir}/{x}' for x in expected],
        'required_artifacts': [f'{outdir}/{x}' for x in expected],
        'verifier_commands': verifier_commands,
        'verifier': {'type': 'command', 'command': verifier_commands[0] if verifier_commands else 'python3 verifier/verify_artifacts.py'},
        'stop_conditions': [
            'credentials required',
            'write outside ProjectIntakeTower needed',
            'destructive action needed',
            'project ownership or intent unclear',
            'secret-like file must be opened to proceed',
        ] + (stop_extra or []),
        'scope': {
            'allowed_paths': [project_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': inputs or {},
        'timeout_minutes': 45,
        'max_iterations': 2,
        'if_blocked': 'write status=needs_human in result.json and stop',
        'rejoin_policy': 'summarize status, artifact_paths, verifier result, needs_human, next_action',
        'created_by': 'operator_intake_command',
        'created_at': now,
    }

jobs = [
    job(
        'intake-audit-komandozentral', 'KomandoZentral', '/home/smlflg/Projekte/KomandoZentral', 'audit',
        'Audit KomandoZentral read-only and produce an owner-facing audit: purpose, state, risks, verifier status, and one next action.',
        ['run non-destructive metadata/test discovery commands only if they do not mutate the repo'],
        ['result.json', 'audit.md'],
        ['python3 verifier/verify_artifacts.py --job jobs/pending/intake-audit-komandozentral.json --require-done'],
        {'project_card': 'inventory/project_cards/komandozentral-46af91fa1c.md', 'evidence_file': 'inventory/evidence/komandozentral-46af91fa1c.json'}
    ),
    job(
        'intake-generate-tests-werbinich', 'WerBinIch', '/home/smlflg/Projekte/WerBinIch', 'test_design',
        'Generate a test plan and ready-to-apply test patch for WerBinIch without editing the source repo.',
        ['inspect existing code/tests read-only', 'write proposed test files as patch/diff artifacts under ProjectIntakeTower only'],
        ['result.json', 'test_plan.md', 'proposed_tests.patch'],
        ['python3 verifier/verify_artifacts.py --job jobs/pending/intake-generate-tests-werbinich.json --require-done'],
        {'project_card': 'inventory/project_cards/werbinich-4b2f31741d.md', 'evidence_file': 'inventory/evidence/werbinich-4b2f31741d.json'},
        stop_extra=['source repo test creation requires owner approval before applying patch']
    ),
    job(
        'intake-consolidate-agent-control-tower-repos', 'Agent Control Tower repos', '/home/smlflg/Projekte', 'consolidation_plan',
        'Consolidate the Agent Control Tower family conceptually: map overlaps, pick system of record candidates, and propose merge/archive sequence. No repo edits.',
        ['compare related project cards/evidence', 'produce consolidation matrix and recommended owner decision tree'],
        ['result.json', 'consolidation_matrix.md', 'owner_decision_tree.md'],
        ['python3 verifier/verify_artifacts.py --job jobs/pending/intake-consolidate-agent-control-tower-repos.json --require-done'],
        {
          'candidate_projects': [
            'Zentrale /home/smlflg/Projekte/Zentrale',
            'KomandoZentral /home/smlflg/Projekte/KomandoZentral',
            'ACT-agentcommandotower /home/smlflg/Projekte/ACT-agentcommandotower',
            'AIOS-Cockpit /home/smlflg/Projekte/AIOS-Cockpit',
            'MultiHarnessStudio /home/smlflg/Projekte/MultiHarnessStudio',
            'FusionKomandoZentraleZentrale /home/smlflg/Projekte/FusionKomandoZentraleZentrale'
          ]
        },
        allowed_files_extra=[
            '/home/smlflg/Projekte/Zentrale/** read-only, excluding secrets and dependency/build/cache dirs',
            '/home/smlflg/Projekte/ACT-agentcommandotower/** read-only, excluding secrets and dependency/build/cache dirs',
            '/home/smlflg/Projekte/AIOS-Cockpit/** read-only, excluding secrets and dependency/build/cache dirs',
            '/home/smlflg/Projekte/MultiHarnessStudio/** read-only, excluding secrets and dependency/build/cache dirs',
            '/home/smlflg/Projekte/FusionKomandoZentraleZentrale/** read-only, excluding secrets and dependency/build/cache dirs',
        ]
    ),
    job(
        'intake-archive-dead-prototype-xyz', 'XYZ prototype candidate', '/home/smlflg/Projekte', 'archive_review',
        'Find the intended dead prototype XYZ candidate from inventory evidence and produce an archive recommendation. Do not move/delete/archive anything.',
        ['search inventory/project cards for XYZ-like candidates', 'write archive recommendation only'],
        ['result.json', 'archive_review.md'],
        ['python3 verifier/verify_artifacts.py --job jobs/pending/intake-archive-dead-prototype-xyz.json --require-done'],
        {'known_status': 'No exact project named XYZ found in current inventory search; human confirmation required before any archive action.'},
        stop_extra=['exact XYZ target cannot be identified', 'archive/delete/move requested']
    ),
    job(
        'intake-build-verifier-hermes-profile-health', 'Hermes profile health', '/home/smlflg/.hermes/profiles', 'verify',
        'Run and improve the ProjectIntakeTower Hermes profile health verifier; summarize unhealthy profiles and safe next actions.',
        ['run verifier/verify_hermes_profile_health.py', 'inspect report only; do not read .env/auth/token files'],
        ['result.json', 'hermes_profile_health_summary.md'],
        ['python3 verifier/verify_artifacts.py --job jobs/pending/intake-build-verifier-hermes-profile-health.json --require-done'],
        {'verifier_script': 'verifier/verify_hermes_profile_health.py', 'report': 'verifier/hermes_profile_health_report.json'},
        allowed_files_extra=[f'{ROOT}/verifier/verify_hermes_profile_health.py read/write', f'{ROOT}/verifier/hermes_profile_health_report.json read/write']
    ),
]

for j in jobs:
    (PENDING / f"{j['job_id']}.json").write_text(json.dumps(j, ensure_ascii=False, indent=2), encoding='utf-8')
    draft = [
        f"# [ProjectIntakeTower] {j['objective']}", '',
        '## Intake command', '',
        f"- Job: `{j['job_id']}`",
        f"- Project: `{j['project_name']}`",
        f"- Path/scope: `{j['project_path']}`",
        f"- Mode: `{j['mode']}`",
        '', '## Safety', '',
        '- Review-only by default.',
        '- No source project modifications.',
        '- No secrets, commits, pushes, deletes, or automatic issue creation.',
        '', '## Expected artifacts', '',
    ]
    for a in j['expected_artifacts']:
        draft.append(f'- `{a}`')
    draft += ['', '## Verifier', '', f"`{j['verifier']['command']}`", '']
    (DRAFTS / f"{j['job_id']}.md").write_text('\n'.join(draft), encoding='utf-8')

intake_md = TRIAGE / 'INTAKE_COMMANDS.md'
intake_lines = ['# Intake Commands', '', f'Generated: {now}', '', '| Command | Job | Status | Human gate |', '|---|---|---|---|']
rows = [
    ('Audit KommandoZentral', 'intake-audit-komandozentral', 'ready', 'no destructive action'),
    ('Generate tests for WerBinIch', 'intake-generate-tests-werbinich', 'ready as patch artifact', 'apply patch requires approval'),
    ('Consolidate Agent Control Tower repos', 'intake-consolidate-agent-control-tower-repos', 'ready', 'merge/archive decisions require approval'),
    ('Archive dead prototype XYZ', 'intake-archive-dead-prototype-xyz', 'needs_human target ambiguous', 'yes: exact XYZ target not found'),
    ('Build verifier for Hermes profile health', 'intake-build-verifier-hermes-profile-health', 'verifier script created; job ready', 'profile fixes require approval'),
]
for cmd, jid, status, gate in rows:
    intake_lines.append(f'| {cmd} | `{jid}` | {status} | {gate} |')
intake_md.write_text('\n'.join(intake_lines)+'\n', encoding='utf-8')

owner = ROOT / 'OWNER_DIGEST.md'
old = owner.read_text(encoding='utf-8') if owner.exists() else '# OWNER DIGEST\n'
section = '\n## Explicit intake commands queued\n\n' + '\n'.join(f'- {cmd}: `jobs/pending/{jid}.json` — {status}' for cmd, jid, status, gate in rows) + '\n'
if '## Explicit intake commands queued' in old:
    old = old.split('## Explicit intake commands queued')[0].rstrip() + section
else:
    old = old.rstrip() + '\n' + section
owner.write_text(old, encoding='utf-8')

print(json.dumps({'status':'succeeded','jobs_written':len(jobs),'drafts_written':len(jobs),'intake_commands':str(intake_md.relative_to(ROOT))}, indent=2))