Preserve failed scanner preflight and add value-free read-only diagnosis

This commit is contained in:
codex 2026-11-02 01:42:08 +01:00
parent 26d4efd280
commit a2e57251ac
8 changed files with 219 additions and 5 deletions

View file

@ -15,3 +15,7 @@ The exact native preparation is now [revision 2](native-r2/PLAN.md), under the s
Native activation awaits exact founder approval under `docs/agent-autonomy-decision.md` ("The supervisor approves that proposal or performs it through the privileged execution path."). The agent must not borrow the founder admin kubeconfig. The prepared founder launcher is `/tmp/forge-scanner-rollout.sh`. Its sealed runner refuses unknown initial identity/guard/hook/source state and any packet drift.
The staged scanner in repo-manager and live receiver have not been altered by this candidate. Independent clean-file commits continue under the original policy.
## Current execution outcome, 2026-11-02
The founder ran the exact revision-2 launcher. It failed during preflight with a suppressed Kubernetes command error, before staging or native mutation (`native_mutation: false`, no events). The exact failed read is not yet identified. Failure evidence is preserved in `attempt-r2-preflight/`; the reviewed packet is unchanged. A separate read-only diagnostic labels each check and outputs fixed failure categories; three tests passed, including raw-diagnostic suppression and receipt preservation. Founder invocation: `bash /tmp/forge-scanner-diagnose.sh`. Do not retry the old apply while this failure is unresolved; its existing receipt prevents an unreviewed retry.

View file

@ -0,0 +1,119 @@
"""Founder-run read-only replay of sealed r2 preflight, with value-free failures.
Never invokes apply, staging, patch, diff, server dry-run or rollback. Never
prints command arguments, shell diagnostics, Kubernetes objects or credentials.
The original failed execution receipt is not modified.
"""
from pathlib import Path
import importlib.util
import json
import re
import subprocess
HERE = Path(__file__).resolve().parent
ORIGINAL = HERE.parent / 'native-r2'
EXPECTED_PACKET = 'd22b1f555af96c203b7d68efd25e80815ce18ca4e3bf0dd3ab96b6f699d50237'
OUTPUT = Path('/tmp/forge-scanner-diagnostic-receipt.json')
def failure_category(returncode, stderr):
# Fixed labels only. Raw stderr stays in memory and is discarded.
if returncode == 0:
return 'passed'
for needle, label in [(b'Forbidden', 'forbidden'), (b'Unauthorized', 'unauthorized'),
(b'certificate has expired', 'certificate-expired'),
(b'certificate signed by unknown authority', 'certificate-authority'),
(b'connection refused', 'connection-refused'),
(b'no such host', 'name-resolution'),
(b'context deadline exceeded', 'deadline-exceeded'),
(b'NotFound', 'not-found')]:
if needle in stderr:
return label
if re.search(rb'command terminated with exit code [0-9]+', stderr):
return 'remote-check-nonzero'
return 'unclassified-command-failure'
def step_label(args, cfg, inventory):
if 'exec' in args:
# Exact known shell only, including the literal check argument.
ensure(args[-1:] in [('check',), ('sh',)], 'unexpected-exec-tail')
if cfg['guard_command'][2] in args and args[-1] == 'check':
return 'installed-artifact-guard'
if inventory in args:
return 'existing-repository-hook-inventory'
raise RuntimeError('unexpected-exec-script')
if args[:2] == ('get', 'nodes'):
return 'node-identity-read'
for resource, label in [('deployment', 'deployment-read'), ('replicasets', 'replicaset-read'),
('pods', 'pod-list-read'), ('pod', 'initial-pod-uid-read'),
('configmap', 'old-public-hook-read')]:
if args[:4] == ('-n', 'forgejo', 'get', resource):
return label
raise RuntimeError('unexpected-read-command')
def ensure(condition, reason):
if not condition:
raise RuntimeError(reason)
def main():
spec = importlib.util.spec_from_file_location('sealed_r2_rollout', ORIGINAL / 'rollout.py')
module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module)
ensure(module.verify_packet() == EXPECTED_PACKET, 'reviewed-packet-drift')
cfg = json.loads((ORIGINAL / 'inputs.json').read_bytes())
receipt = {'read_only': True, 'replayed_packet_sha256': EXPECTED_PACKET, 'steps': [],
'native_mutation': False, 'original_failed_receipt_preserved': True}
def save():
OUTPUT.write_text(json.dumps(receipt, indent=2) + '\n')
class Diagnostic(module.Rollout):
def k(self, *args, data=None, timeout=60):
ensure(data is None, 'unexpected-stdin')
label = step_label(args, cfg, module.inventory_script())
try:
q = subprocess.run(['kubectl', *args], capture_output=True, timeout=min(timeout, 60))
except subprocess.TimeoutExpired:
receipt['steps'].append({'step': label, 'category': 'timeout'})
save(); print(json.dumps(receipt['steps'][-1]), flush=True)
raise RuntimeError('read-only-command-timeout')
item = {'step': label, 'returncode': q.returncode,
'category': failure_category(q.returncode, q.stderr)}
if q.returncode:
match = re.search(rb'command terminated with exit code ([0-9]+)', q.stderr)
if match:
item['remote_exit_code'] = int(match[1])
receipt['steps'].append(item); save(); print(json.dumps(item), flush=True)
ensure(q.returncode == 0, 'read-only-step-failed:' + label)
return q.stdout
def event(self, name, **details):
# No writes to the native r2 receipt; details contain public counters only.
receipt['checks'] = {'event': name, **details}; save()
def dry_run(self, d):
receipt['server_dry_run'] = 'intentionally-not-replayed'
def ready_pod(self, d, seconds=180):
return super().ready_pod(d, seconds=10)
try:
Diagnostic(cfg).preflight()
receipt['result'] = 'read-only-preflight-passed'
except Exception as exc:
receipt['result'] = 'read-only-preflight-refused'
receipt['reason'] = str(exc) if isinstance(exc, RuntimeError) else type(exc).__name__
save()
print(json.dumps({'result': receipt['result'], 'reason': receipt.get('reason'),
'receipt': str(OUTPUT), 'native_mutation': False}), flush=True)
return 0 if receipt['result'] == 'read-only-preflight-passed' else 1
if __name__ == '__main__':
try:
raise SystemExit(main())
except Exception as error:
print(json.dumps({'result': 'diagnostic-refused', 'reason': str(error) if isinstance(error, RuntimeError) else type(error).__name__}))
raise SystemExit(1)

View file

@ -0,0 +1,17 @@
{
"proposal_id": "SYNC-SCANNER-JSON-DIGEST-20261101",
"executed_revision": 2,
"executed_packet_sha256": "d22b1f555af96c203b7d68efd25e80815ce18ca4e3bf0dd3ab96b6f699d50237",
"execution_identity": "founder; attended terminal",
"execution_evidence": "User returned bash /tmp/forge-scanner-rollout.sh failure output in active conversation, 2026-11-02",
"outcome": "failed",
"reported_reason": "kubectl-command-failed; raw diagnostics withheld",
"verified_phase": "preflight; exact failed read/remote check not yet identified",
"native_mutation": false,
"receipt_sha256": "35e4ba1b09065ec765762d4238235cb02286c42e19baad0f0ae505167c44a500",
"recovery": "No native mutation, no rollback required; original receipt and sealed packet preserved. Read-only diagnostic prepared.",
"diagnostic_sha256": "301919aa82b9e9ae5f1a2d55175d2e988ba4c4ac955598651d7f25ba71ddc21c",
"tests": "3 passed; failure label/redaction, command restrictions and preservation of original receipt",
"promotion_evidence": false,
"score": "unscored; no signed approval or separate approval evidence backfilled"
}

View file

@ -0,0 +1 @@
{"proposal_id": "SYNC-SCANNER-JSON-DIGEST-20261101", "revision": 2, "events": [], "native_mutation": false, "packet_sha256": "d22b1f555af96c203b7d68efd25e80815ce18ca4e3bf0dd3ab96b6f699d50237", "mode": "apply"}

View file

@ -0,0 +1,54 @@
"""Value-free diagnostics and refusal boundaries; no cluster access."""
import contextlib
import importlib.util
import io
import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location('read_only_diagnostic', HERE / 'diagnose.py')
d = importlib.util.module_from_spec(spec); spec.loader.exec_module(d)
class Tests(unittest.TestCase):
def test_error_categories_never_echo_raw_diagnostics(self):
sentinel = b'PRIVATE_SENTINEL_DO_NOT_EMIT'
for raw, expected in [(b'Forbidden: ' + sentinel, 'forbidden'),
(b'command terminated with exit code 1 ' + sentinel, 'remote-check-nonzero'),
(sentinel, 'unclassified-command-failure')]:
self.assertEqual(d.failure_category(1, raw), expected)
def test_only_expected_reads_and_exact_check_scripts_are_labeled(self):
cfg = {'guard_command': ['sh', '-c', 'EXACT_PUBLIC_GUARD']}
self.assertEqual(d.step_label(('get', 'nodes', '-o', 'json'), cfg, 'INVENTORY'), 'node-identity-read')
self.assertEqual(d.step_label(('-n', 'forgejo', 'exec', '-i', 'pod', '--', 'sh', '-c', 'EXACT_PUBLIC_GUARD', 'sh', 'check'), cfg, 'INVENTORY'), 'installed-artifact-guard')
self.assertEqual(d.step_label(('-n', 'forgejo', 'exec', '-i', 'pod', '--', 'sh', '-c', 'INVENTORY', 'sh'), cfg, 'INVENTORY'), 'existing-repository-hook-inventory')
for argv in [('create', '-f', '-'), ('patch', 'deployment', 'forge'), ('get', 'secrets'),
('exec', 'pod', '--', 'sh', '-c', 'OTHER', 'sh'),
('exec', 'pod', '--', 'sh', '-c', 'EXACT_PUBLIC_GUARD', 'sh', 'apply')]:
with self.subTest(argv=argv), self.assertRaises(RuntimeError): d.step_label(argv, cfg, 'INVENTORY')
def test_failed_read_is_labeled_and_original_native_receipt_is_preserved(self):
native = Path('/tmp/forge-scanner-rollout-receipt.json')
before = native.read_bytes() if native.exists() else None
class Failed:
stdout = b'PRIVATE_STDOUT_SENTINEL'
stderr = b'Forbidden: PRIVATE_STDERR_SENTINEL'
returncode = 1
with tempfile.TemporaryDirectory() as temp, patch.object(d, 'OUTPUT', Path(temp) / 'receipt.json'), patch.object(d.subprocess, 'run', return_value=Failed()) as command:
captured = io.StringIO()
with contextlib.redirect_stdout(captured): result = d.main()
text = captured.getvalue(); receipt = json.loads(d.OUTPUT.read_bytes())
self.assertEqual(result, 1)
self.assertEqual(command.call_count, 1)
self.assertEqual(receipt['steps'], [{'step': 'node-identity-read', 'returncode': 1, 'category': 'forbidden'}])
self.assertFalse(receipt['native_mutation'])
self.assertNotIn('PRIVATE_', text)
self.assertNotIn('PRIVATE_', d.OUTPUT.read_text())
self.assertEqual(native.read_bytes() if native.exists() else None, before)
if __name__ == '__main__': unittest.main()