feat(automation): add durable runner and signed approval recovery
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# AUTONOMOUS-ROADMAP-01 acceptance — 29 October 2026
|
||||
|
||||
**Controller implementation and synthetic qualification: delivered. Real backlog execution: disabled. Phase 10 implementation: NO-GO.** No production or main-merge authority is granted.
|
||||
|
||||
Source branch: `codex/autonomous-roadmap-01`, isolated managed worktree based on the actual local `5032ccb`. The queue/source checkpoint is `4da3939547a327fe27572b081a893fdf6cb1638c`, pushed and independently read back from origin. The final controller checkpoint is identified by Git history and the final handoff; tested source hashes are in the machine-readable results below. Publishing this branch does not publish or accept the pending pre-Phase-10 ref.
|
||||
|
||||
## Final decision matrix
|
||||
|
||||
| Required area | Decision | Evidence and boundary |
|
||||
|---|---|---|
|
||||
| Queue configuration | **PASS** | Seven actual source workstreams in requested order; full byte-preserved master/detail packs; 49 bounded checkpoints; manifest/source hash validation; source gaps resolved by owner-supplied folders |
|
||||
| Codex non-interactive runner | **PASS for implemented synthetic protocol** | Installed 0.163.0 help and official docs verified; actual subprocess fake-CLI tests exercise full prompt delivery, JSONL completion, structured result, independent test process/report and captured session ID. **Real model/native-sandbox worker NOT RUN / BLOCKED** |
|
||||
| Resume/recovery | **PASS in synthetic/local process scope** | Durable state/backup/OS lock, interruption, pending-publication resume, corrupt-state recovery, unsigned-recovery rejection, actual killed controller/child/grandchild and suspended-launch tests |
|
||||
| Acceptance gate enforcement | **PASS in synthetic scope** | Dependency/order gates; fresh report membership/failure/skip/retry rules; artifact tamper detection; unknown/missing sources and unqualified adapters block; conditional advancement requires declared deferral plus signature |
|
||||
| Owner approval enforcement | **PASS in synthetic/cryptographic scope** | Actual .NET verifier exercised end-to-end with signed queue/stage approvals; six separate valid/replay/forgery/expiry/wrong-owner/plain-JSON cases; design revision/selection text persists |
|
||||
| Git safety | **PASS in disposable repositories and scoped feature publication** | Explicit feature refs; no force/merge/rebase/deploy path; baseline/publication verification, unavailable remote, push failure/mismatch and integration fast-forward tests; real own-branch publication read back |
|
||||
| Isolation/security | **CONDITIONAL** | Windows suspended launch and Job process-tree behavior tested locally. Native Codex sandbox failed CryptUnprotectData; dedicated account/VM, ACL/read/egress/tool/secret/CPU qualification and actual test adapters are not provisioned or certified |
|
||||
| Synthetic orchestration tests | **PASS** | **48 controller tests**, zero failures/errors/skips; source hashes stable throughout full run. **6 separate signature cases**, exit 0. These are disjoint lanes, not additions to Jobjakt's application counts |
|
||||
| Ready to run Phase 10 | **NO-GO** | Existing acceptance withholds implementation; unpublished pre-Phase-10 baseline, owner scope/entry, qualified runtime and adapter gates remain |
|
||||
|
||||
This is a qualified development handoff, not a claim that the real CLI can safely run the roadmap on the current desktop. A direct model-backed execution was deliberately not attempted as a workaround for failed isolation. The shipped real-stage composite test adapter is unconfigured and fails closed until actual provider/browser/Python/PDF/security/preservation lanes and test membership are installed and approved. Static `dry-run` configuration PASS means the queue/source structure is valid, not that the runner identity, certificate, credentials or application runtime are ready.
|
||||
|
||||
## Reproducible evidence
|
||||
|
||||
- `automation/reports/synthetic-results.json`: final test totals, zero failure/error/skip lists, before/after source-stability assertion and exact controller/manifest/test/PowerShell hashes.
|
||||
- `automation/reports/synthetic-tests.txt`: full final 48-case test output.
|
||||
- `automation/reports/signature-results.json` and `signature-tests.txt`: six separate .NET cryptographic cases using temporary keys/certificates only.
|
||||
- `automation/reports/disabled-dry-run.json`: static queue validation, zero source gaps, 49 checkpoints, unqualified adapter explicitly listed, execution disabled and **zero real sessions** independently asserted from durable state.
|
||||
- `automation/SOURCE_INVENTORY.json` and `automation/backlog.json`: actual prompt names/sizes/SHA256 and immutable workstream/checkpoint policy. `.gitattributes` prevents prompt newline normalization.
|
||||
|
||||
The final full run supersedes earlier focused runs and deliberately failing regression runs; those are not added to the final 48. The six signature cases are reported separately. No historical application suite counts were rerun, combined or promoted by this task.
|
||||
|
||||
## Requested failure scenarios
|
||||
|
||||
| Scenario | Synthetic evidence |
|
||||
|---|---|
|
||||
| Queue ordering and dependencies | `test_success_orders_stages_and_verifies_remote`, `test_dependency_cannot_be_bypassed`, forward/cyclic dependency rejection |
|
||||
| Successful and failed stages | actual two-stage fake-worker Git flow; bounded failed model/check flow |
|
||||
| Conditional acceptance | no-declared-deferral stop; declared deferral still waits for signed approval |
|
||||
| Missing approval / bypass | missing signature launches no model; worker JSON cannot approve; actual signed resume E2E; six crypto cases |
|
||||
| CLI interruption / network-style failure | fake CLI exit 17 and interrupted runner never accept; bounded retry with stored failure context |
|
||||
| Restart/resume | persistent RUNNING with/without marker blocks; unsigned recovery cannot clear guard; actual killed parent kills contained child/grandchild |
|
||||
| Missing/changed prompt | source absence/hash change blocks before model execution |
|
||||
| Unavailable remote / push failure / wrong remote HEAD | baseline check prevents work, tested local commit retained, publication-only resume, mismatch blocks |
|
||||
| Repeated failure limit | retry budget exhaustion stops; resetting requires a signed explicit request; total session budget remains finite |
|
||||
| Duplicate start | OS-held common-Git-directory lock rejects second controller, including a different ControlRoot |
|
||||
| Corrupt state | checksum/last-good recovery marked for reconciliation; double corruption fails closed |
|
||||
| Accidental main operation | main/master/production/detached initial checkout and unsafe branch policies rejected; no merge/deploy implementation |
|
||||
| Source/evidence falsification | modified artifact blocks approval; structured reports reject empty/failing/skipped/retried or wrong-membership output |
|
||||
| Resource and shutdown faults | stalled stdin timeout, huge no-newline log limit, PID-marker disk failure cleanup, suspended pre-assignment launch, Job kill-on-parent-death |
|
||||
| Human design loop | signed Revise returns to same checkpoint, persists element choices; later signed Approve advances without another copied prompt |
|
||||
|
||||
This simulates reboot/restart conditions and tests actual process termination; it does not claim a physical PC reboot occurred. Windows Job memory/process limit configuration is implemented; adversarial memory-exhaustion/load qualification of the actual Codex/native sandbox remains operator work.
|
||||
|
||||
## Review and graph evidence
|
||||
|
||||
A read-only independent code review identified blocking stdin delivery, marker-write cleanup, unbounded log allocation, unsigned-recovery state mutation and pre-assignment process execution. Each was corrected and covered by regression tests. Credential redaction now preserves valid JSONL event structure; its regression was observed failing before the fix. Review is supporting evidence, not proof of real-host isolation.
|
||||
|
||||
`graphify update .` rebuilt the separate worktree's AST graph without LLM/API cost. It reports unsupported/no-symbol files and missing SQL/PDF extraction dependencies; graph orientation does not establish runtime routing, security, test completeness or acceptance. The primary checkout's graph was not modified.
|
||||
|
||||
The inspected Gitea deployment workflow triggers on pushes to main (plus PR testing), and the MariaDB workflow lists other explicit qualification branches. This task published only its development branch and created no PR, workflow dispatch, production operation or scheduled runner.
|
||||
|
||||
## Owner handoff
|
||||
|
||||
Use [README](README.md) for exact installation/start/status/pause/resume/approval commands. **First complete Pre-Phase-10 acceptance, publish and verify its final branch, and explicitly approve Phase 10 development entry on a named baseline and exact candidate scope.** Preserve the separate human, S01/PDF, model, CI/security and production conditions in [GATES](GATES.md). Then qualify the isolated runner/test adapters and sign the enabled manifest/environment/roadmap/entry requests. This task intentionally grants none of those decisions.
|
||||
|
||||
No Jobjakt application code, existing tests, schema, local application stack, real CV, production database, Docker service, Ollama/model cache, main branch or production filesystem was changed by this implementation branch.
|
||||
@@ -14,13 +14,13 @@ Atomic checksummed state with last-good backup, an OS-held repository lock, a du
|
||||
|
||||
## Scope and checkpoints
|
||||
|
||||
- [ ] AUTO-00: Audit actual source prompts, CLI 0.163.0, local/remote Git state and Phase 10 authority. Record missing/contradictory sources and sandbox failure.
|
||||
- [ ] AUTO-01: Preserve original prompt bytes; implement strict queue validation and stage/checkpoint gates in `automation/backlog.json` and schemas.
|
||||
- [ ] AUTO-02–03: Implement PowerShell entry point, bounded runner, atomic state, exclusive locking, pause/resume, windows and budgets in `automation/controller.py`.
|
||||
- [ ] AUTO-04–05: Implement signed owner decisions, real test/report verification, safe feature commits and verified publication.
|
||||
- [ ] AUTO-06: Implement status, current-stage and redacted logs plus local event notifications.
|
||||
- [ ] AUTO-07: Write failing tests first, implement, then run disposable-repository end-to-end tests for every requested failure mode. No application services or real roadmap sessions.
|
||||
- [ ] AUTO-08: Document install, authentication, protected approval setup, scheduling, recovery and exact first-entry owner action; record honest final acceptance.
|
||||
- [x] AUTO-00: Audit actual source prompts, CLI 0.163.0, local/remote Git state and Phase 10 authority. Record source mismatches and sandbox failure; import the owner's subsequently supplied I18N/security packs.
|
||||
- [x] AUTO-01: Preserve original prompt bytes; implement queue validation and stage/checkpoint gates in `automation/backlog.json` and schemas.
|
||||
- [x] AUTO-02–03: Implement PowerShell entry point, bounded runner, atomic state, exclusive locking, pause/resume, windows and budgets in `automation/controller.py`.
|
||||
- [x] AUTO-04–05: Implement signed owner decisions, test/report verification, safe feature commits and verified publication. Live-host/application qualification remains independently gated.
|
||||
- [x] AUTO-06: Implement status, current-stage and redacted logs plus local event notifications.
|
||||
- [x] AUTO-07: Red/green tests, 48 passing controller tests and six signature cases; disposable-repository end-to-end coverage, actual subprocess/Windows containment and real verifier paths. No application services or real roadmap sessions.
|
||||
- [x] AUTO-08: Document install, authentication, protected approval setup, scheduling, recovery and exact first-entry owner action; record qualified final acceptance.
|
||||
|
||||
Files touched: new `automation/`, `scripts/Run-JobjaktBacklog.ps1`, `scripts/Approve-JobjaktBacklog.ps1`, documentation, and runtime ignore rules. No application callers, database schemas, production configuration or existing tests change.
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
# Autonomous Jobjakt backlog controller
|
||||
|
||||
This implementation builds the orchestrator only. **The real backlog is disabled. Phase 10 is NO-GO pending its own entry decision.** See [audit](AUDIT.md), [gate register](GATES.md), [security boundary](SECURITY.md), and [acceptance evidence](ACCEPTANCE.md).
|
||||
|
||||
## What is installed
|
||||
|
||||
`scripts/Run-JobjaktBacklog.ps1` provides the Windows command interface. `automation/controller.py` uses Python's standard library; no package installation or application service is required for controller tests. `automation/backlog.json` preserves sequence 05–11 with 49 bounded checkpoints and full source snapshots. Runtime state, approvals, reports and logs belong in a separate protected ControlRoot, never in the model-writable repository. JSON is sufficient because one controller owns an OS-held repository lock and all state writes are atomic/checksummed; SQLite would add no useful concurrency here.
|
||||
|
||||
Requirements: PowerShell **7.2+**, Python **3.12+**, Git and **Codex CLI 0.163.0** (the version audited here; qualify later versions before unattended use). `codex exec` structured output and sandbox flags are described in the [official non-interactive documentation](https://learn.chatgpt.com/docs/non-interactive-mode). Windows 0.163.0 runs test commands as `codex sandbox -C <workspace> -c sandbox_mode="workspace-write" <command> ...`; see local help and the [Windows sandbox documentation](https://learn.chatgpt.com/docs/windows/windows-sandbox).
|
||||
|
||||
## Commands already safe to run now
|
||||
|
||||
The validation installation at `C:\Users\Connor\.codex\orchestrator-validation\autonomous-roadmap-01-final` is a disabled snapshot for dry runs. It references the separate implementation worktree. It is **not** a qualified unattended deployment; start/resume cannot launch the real queue while disabled.
|
||||
|
||||
```powershell
|
||||
$control = 'C:\Users\Connor\.codex\orchestrator-validation\autonomous-roadmap-01-final'
|
||||
$run = Join-Path $control 'Run-JobjaktBacklog.ps1'
|
||||
pwsh -NoProfile -File $run -Command validate -ControlRoot $control
|
||||
pwsh -NoProfile -File $run -Command dry-run -ControlRoot $control
|
||||
pwsh -NoProfile -File $run -Command status -ControlRoot $control
|
||||
pwsh -NoProfile -File $run -Command current -ControlRoot $control
|
||||
pwsh -NoProfile -File $run -Command logs -ControlRoot $control
|
||||
```
|
||||
|
||||
Run the reproducible isolated tests from this implementation worktree:
|
||||
|
||||
```powershell
|
||||
Set-Location 'C:\Users\Connor\.codex\worktrees\autonomous-roadmap-01\Job tracker'
|
||||
python -m unittest discover -s automation/tests -v
|
||||
pwsh -NoProfile -File automation/tests/Test-Approvals.ps1 -Verifier "$PWD\scripts\Approve-JobjaktBacklog.ps1"
|
||||
```
|
||||
|
||||
Tests create disposable local worker repositories and bare remotes. The subprocess double exercises the real supervision/result/report paths without a model or network. RSA tests use temporary in-memory keys/certificates and do not install an owner key. They do not qualify the Windows sandbox or real application acceptance.
|
||||
|
||||
## Provision an actual runner, after approval
|
||||
|
||||
Use a dedicated development Windows account/VM with no production credentials, mounts, Docker socket, remote admin access or production network routes. Keep the owner's signing identity separate. A source worktree provides edit isolation; it is not a production security boundary. Prefer a **separate clone** for unattended execution, avoiding shared Git metadata/hooks with ongoing human work. The owner must protect main/production refs server-side and grant the publisher only the intended development refs.
|
||||
|
||||
Create the runner clone from the accepted development branch after its final publication; never default to main. Do not copy private `.env` files from the live checkout. Configure Git author identity and an approved development-only credential helper. Install dependencies and qualify local synthetic service fixtures separately. Do not let the controller install infrastructure or enable workers on your behalf.
|
||||
|
||||
Initialize a new control directory using the implementation source:
|
||||
|
||||
```powershell
|
||||
$source = 'C:\Users\Connor\.codex\worktrees\autonomous-roadmap-01\Job tracker'
|
||||
pwsh -NoProfile -File "$source\scripts\Run-JobjaktBacklog.ps1" `
|
||||
-Command init -ControlRoot 'C:\JobjaktControl' -Repository 'C:\JobjaktWorker'
|
||||
```
|
||||
|
||||
`init` snapshots code, schemas, source prompts and initial manifest outside the worker. It refuses to overwrite existing state. Keep the trusted installation read-only to model shell commands, with the runner able to persist its state and reports outside the sandbox. The owner provisions ACLs/VM policy; this task does not change machine accounts, firewall or system permissions.
|
||||
|
||||
Edit protected `config.json` as the operator: exact worker path; Codex/pwsh executable paths; owner SID; separate runner SID; public certificate filename/SHA256; dedicated auth-only `workerCodeXHome`; time/log budgets; optional execution windows. Authenticate **as the development runner** with `codex login` using that dedicated CODEX_HOME. Never print/copy auth tokens into logs. Default child environment excludes API-key/production secret variables. Do not use the owner's normal CODEX_HOME with its plugins or credentials.
|
||||
|
||||
Real execution verifies the runner identity, certificate pin, version, disjoint paths, auth-only configuration and a negative sandbox write probe. It refuses missing/failed sandbox controls and never falls back to unrestricted execution. The current host's CryptUnprotectData error must be resolved and the real boundary qualified before any worker can run. A signed environment qualification additionally records OS ACLs, read/network access, CPU/RAM quotas, synthetic service isolation and credential exposure: a successful single write probe cannot certify all of these.
|
||||
|
||||
The security source pack requires Codex Security plugins and actual scanner artifacts. The default auth-only worker intentionally has no plugin capability. A platform owner can provision a vetted, constrained development-only plugin/MCP runner and add explicit `trustedCodexOverrides` entries (`key` under `mcp_servers.*` or `plugins.*`, plus its exact TOML `toml` value) to protected config. Other override namespaces are rejected; explicit sandbox/approval flags remain fixed. This changes the policy hash and requires fresh signed environment/roadmap approval. Qualify every server's identity, permissions, egress, costs and tool exposure before signing: MCP/plugin tools are not automatically confined by the shell sandbox. Missing required scan capability remains BLOCKED. Do not remove source requirements or use unrestricted config loading to make a scan appear to pass.
|
||||
|
||||
## Configure gates and enable the exact queue
|
||||
|
||||
The core backend/frontend/type/lint/build commands are specified. The composite provider/browser/Python/PDF/security/preservation adapter is marked `configured:false`. Before real execution, the platform owner must install its **actual** checkpoint-specific commands and structured report definitions in a proposed manifest, with exact test-suite membership (`expectedNames`) or a trusted independently verified membership adapter. Use original preservation/PDF oracles; do not rewrite them to match current failures. Human/provider/hosted/model requirements remain separate signed evidence decisions. No successful dry run changes these gates.
|
||||
|
||||
Copy `backlog.json` to `proposed-backlog.json` in ControlRoot. Set the exact accepted/published baseline commit and branch, resolved branch/substage policy, qualified checks/artifacts, and finally `executionEnabled:true`. Do this only after the owner explicitly authorizes first execution. Never modify active state JSON to enable it.
|
||||
|
||||
```powershell
|
||||
pwsh -NoProfile -File C:\JobjaktControl\Run-JobjaktBacklog.ps1 `
|
||||
-Command configure -ControlRoot C:\JobjaktControl -Manifest C:\JobjaktControl\proposed-backlog.json
|
||||
```
|
||||
|
||||
The first invocation writes a `manifest-policy-update` request and exits without applying the policy. Sign that request through the protected owner workflow below, then run the same command again. It adopts the manifest without resetting completed work. Started-stage policy is immutable. A crash between policy/state writes fails closed; restore the verified previous pair from operator backups rather than guessing which policy ran.
|
||||
|
||||
## Owner signing and decisions
|
||||
|
||||
On the **owner's separate Windows identity or machine**, create a nonexportable signing key once:
|
||||
|
||||
```powershell
|
||||
pwsh -NoProfile -File .\Approve-JobjaktBacklog.ps1 -Action NewKey
|
||||
pwsh -NoProfile -File .\Approve-JobjaktBacklog.ps1 -Action ExportPublicKey `
|
||||
-Thumbprint '<OWNER_CERTIFICATE_THUMBPRINT>' -CertificatePath .\owner.cer
|
||||
Get-FileHash .\owner.cer -Algorithm SHA256
|
||||
```
|
||||
|
||||
Record the printed owner SID and certificate hash in the protected runner configuration. Transfer only `owner.cer` to the runner, never a PFX/private key. A certificate file placed inside a worker checkout is not a protected approval mechanism.
|
||||
|
||||
`status` shows the exact pending request path. Review that JSON and its linked source/evidence. Transfer the exact request bytes to the owner; signing does not alter them. Example:
|
||||
|
||||
```powershell
|
||||
pwsh -NoProfile -File .\Approve-JobjaktBacklog.ps1 -Action Sign `
|
||||
-RequestPath '.\requests\<REQUEST_SHA256>.json' `
|
||||
-ApprovalPath '.\approvals\<REQUEST_SHA256>.json' `
|
||||
-Thumbprint '<OWNER_CERTIFICATE_THUMBPRINT>' -ExpectedOwnerSid '<OWNER_SID>' `
|
||||
-Disposition Approve -Decision 'Approve the exact stated scope and evidence' -ValidHours 72
|
||||
```
|
||||
|
||||
Transfer the signed envelope to `C:\JobjaktControl\approvals\<REQUEST_SHA256>.json`, then resume. The controller checks its signature, owner, certificate pin, request digest and expiry. Editing a worker `approval.json` or copying a previous commit's approval will not work.
|
||||
|
||||
For homepage feedback, sign the pending design request with `-Disposition Revise -Decision 'Keep concept A layout; use D buttons; revise mobile spacing'`, transfer it, then resume. The next session revises the same checkpoint using that exact decision. After the revised artifacts are published, approve the **new** request with your final selection. `Reject` blocks advancement. The model never chooses on your behalf. Signed decision text is passed to subsequent sessions, so no roadmap prompt copying is needed.
|
||||
|
||||
Environment and roadmap-execution approval are shared for the exact queue policy; later stages reuse those grants while they remain valid. Scope-specific grants, Product Review selection, language review, design choice, security decisions and final requirement reviews are still required at their actual checkpoints. If a grant expires before use, renew that exact request; an accepted earlier checkpoint is not silently undone by a later expiry.
|
||||
|
||||
## Start, monitor, pause, resume and retry
|
||||
|
||||
These commands are for the **qualified, explicitly enabled** installation only:
|
||||
|
||||
```powershell
|
||||
$run = 'C:\JobjaktControl\Run-JobjaktBacklog.ps1'
|
||||
pwsh -NoProfile -File $run -Command start -ControlRoot C:\JobjaktControl
|
||||
pwsh -NoProfile -File $run -Command status -ControlRoot C:\JobjaktControl
|
||||
pwsh -NoProfile -File $run -Command current -ControlRoot C:\JobjaktControl
|
||||
pwsh -NoProfile -File $run -Command logs -ControlRoot C:\JobjaktControl
|
||||
pwsh -NoProfile -File $run -Command pause -ControlRoot C:\JobjaktControl
|
||||
pwsh -NoProfile -File $run -Command resume -ControlRoot C:\JobjaktControl
|
||||
pwsh -NoProfile -File $run -Command retry -ControlRoot C:\JobjaktControl -Stage PHASE-10
|
||||
```
|
||||
|
||||
`start` stays in the foreground until the queue completes, hits a genuine gate or reaches a configured window/budget. Use a separate terminal for monitoring/pause. `pause` writes a durable request without racing the controller's state lock; supervision stops the active child tree. `resume` clears the pause and runs the next allowed work. Ordinary failures receive bounded remediation sessions with failure context; `retry` never silently resets an exhausted budget. Its explicit reset request requires a signed owner decision. Session totals remain capped even after resetting attempts.
|
||||
|
||||
The state store records initial/accepted commits, checkpoint progress, attempts/sessions, pending publication, approvals, tests, artifacts, reports and recent sessions. `NOT_RUN` is distinct from verified zero failures. Status never combines overlapping suite counts into one roadmap total.
|
||||
|
||||
## Recovery
|
||||
|
||||
- **Push/network failure:** local verified commits remain. Restore development remote access and run `resume`. Only that publication is retried; the model and tests are not repeated for an unchanged candidate. Remote HEAD mismatch or non-fast-forward stops advancement. No force push/rebase/main merge occurs.
|
||||
- **CLI failure/context limit:** failed/incomplete output cannot advance. Retry/continuation starts a fresh bounded session with full applicable prompt, stored result, source identities, prior decisions and failures. CLI thread IDs are recorded for inspection; raw `exec resume --last` is deliberately avoided because it can select unrelated work or inherit unsuitable permissions.
|
||||
- **Parent killed/reboot:** the OS releases the Git lock. A persistent active-process marker or RUNNING state blocks a new worker. Inspect recorded PID, creation time/session/command and all descendants before stopping an orphan; never kill a reused PID blindly. After the tree is gone, run `recover`, sign its exact reconciliation request, then rerun `recover` and `resume`. A launch marker with no PID requires operator inspection/clearance, not an automatic guess. Native time limits apply while the controller lives; VM/Task Scheduler job limits are required for hard orphan resource bounds.
|
||||
- **Corrupt state:** checksum failure loads the last verified backup and sets recovery-required. It does not restart from zero. `recover` requires a signed owner reconciliation. If both copies are corrupt, restore a verified **state + manifest + reports** backup; do not run `init` over the installation. Restore/reconcile exact Git HEAD and remote publication before resuming.
|
||||
- **Unexpected source/Git/policy changes:** stop and investigate. Resume refuses changed prompt hashes, unexpected branch/HEAD, altered evidence, diverged integration or modified manifest. Preserve logs and local commits. Do not reset the worker or silently remove tests.
|
||||
|
||||
## Scheduling and resource limits
|
||||
|
||||
No task or recurring automation is installed by this build. The CLI works without an interactive GUI. An optional Windows Task Scheduler task may invoke the installed `start` command at logon/startup and/or a periodic interval under the dedicated runner. `start` continues existing state while respecting a durable manual pause; reserve `resume` for the owner's deliberate unpause. Use **Run whether user is logged on or not**, **Run with highest privileges disabled**, a maximum duration and **Do not start a new instance**. The repository lock remains the final concurrency guard. Do not use the owner signing account as the scheduled worker.
|
||||
|
||||
Example task action (configure it through Task Scheduler after approval):
|
||||
|
||||
```text
|
||||
Program: <absolute path to pwsh.exe>
|
||||
Arguments: -NoProfile -File C:\JobjaktControl\Run-JobjaktBacklog.ps1 -Command start -ControlRoot C:\JobjaktControl -Python <absolute path to python.exe>
|
||||
Start in: C:\JobjaktControl
|
||||
```
|
||||
|
||||
The PC must be awake, with its approved development fixtures, authentication, dependencies and remote available. The controller does not bypass lock/sleep or wake the computer. `executionWindows` uses the Windows runner's local time; configure its timezone as Europe/Paris if that is the intended window. Overnight windows are supported and a running session stops when its window closes. Defaults are no time window, eight-hour controller budget, two-hour sessions, one-hour checks, 50 MiB per output stream, 64 processes and 8 GiB total child-tree memory. Windows Job Objects enforce process/memory/kill-on-close limits after a suspended launch; CPU and whole-host limits still belong to the qualified VM. Limits stop continuation; they do not assert completion.
|
||||
|
||||
Notifications are local sanitized `events.jsonl` records and terminal status. No paid provider is added. Existing Jobjakt user notifications belong to the application and are not reused for developer orchestration. Event records contain IDs/status, never documents or credentials; an operator can attach an approved local event watcher later. Full session files remain private access-controlled evidence. No unchanged-state notification loop is created.
|
||||
|
||||
## Add future prompts
|
||||
|
||||
Preserve original bytes and record SHA256. `automation/prepare_queue.py --source <folder> --output <new-folder> --project <repository>` imports the actual mapped pack into a **new** queue, refusing to overwrite one. Add stable workstream IDs/dependencies, exact branch/checkpoint policies, source/supplement hashes, all required gates/checks/artifacts/owner decisions and finite budgets. Validate source identity and qualify tests in a disposable repository. Adding IDs needs a new installation/owner-reviewed queue migration; `configure` deliberately cannot splice new stages into a running queue. Never derive authorization from a filename such as `done`.
|
||||
|
||||
## Exact first owner action
|
||||
|
||||
**Finish pre-Phase-10 acceptance and explicitly approve Phase 10 development entry on a named, published baseline and candidate scope.** This is not yet granted. Publish/verify the pending pre-Phase-10 commits, disposition the scoped CV/PDF/human/AI/CI/security conditions according to their actual gate authority, qualify the isolated runner and test adapters, then sign the proposed enabled policy, environment/roadmap grants and `phase10-development-entry` request. Until those steps, use the disabled dry-run installation. No real backlog command was executed by this task.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Controller trust boundaries
|
||||
|
||||
## Threat model
|
||||
|
||||
Treat the worker model, repository content, test/build scripts, uploaded inputs and tool output as untrusted execution. Protect owner approvals, controller policy/code, durable state, test receipts, source identity, development publication and all production assets. Threats include forged PASS/approval JSON, replayed decisions, modified tests/artifacts, policy replacement, overlapping workers, branch/push manipulation, secret exposure and orphan processes.
|
||||
|
||||
The approval signature is implemented with .NET RSA PKCS#1/SHA256, using a pinned public certificate and an owner identity separate from the runner. The owner private key must never be exported or accessible from the worker. Signatures bind exact request bytes, manifest/controller/config hashes, source hashes via the manifest, baseline/candidate commit and evidence digests, expiry and decision. Revising/selecting a design is an explicit signed disposition. A JSON file saying approved, a model summary or a state checksum is not authority.
|
||||
|
||||
## Required deployment boundary
|
||||
|
||||
1. Use a dedicated non-administrator development account/VM without production credentials, `.env`, secret mounts, SSH agent, Docker socket, host management APIs or routes to production/LAN services. The signing owner uses another account/machine. `runnerSid` must match the live account and differ from `ownerSid`. Public-key trust is provisioned by the owner, not discovered from model output.
|
||||
2. Install the trusted controller, immutable prompt/manifest snapshot, certificate/config and state **outside** the worker checkout. Native Codex workspace-write shell commands must not modify or read private control-plane records or owner material. Auth uses a dedicated minimal CODEX_HOME. Do not run the repository's mutable controller copy as the unattended trust authority.
|
||||
3. Qualify real filesystem/read/network/process restrictions and resource limits in the actual runner. The built-in negative write probe is one preflight check, not a sandbox certification. Windows native workspace-write denies external writes; it does not by itself prove all external reads or privileged tool calls are safe. Record negative access attempts to owner key/state/config/Git metadata/production paths and denied egress, plus permitted synthetic build/test needs.
|
||||
4. External plugin/MCP tools require their own qualified host boundary and least permissions. Protected `trustedCodexOverrides` allows only explicit MCP/plugin namespaces, passed as separate supported `-c` arguments; it cannot select unrestricted sandbox/approval behavior. The defaults load no user config or plugins. A configured tool still cannot be assumed safe merely because its namespace is allowed. Hash/config changes invalidate policy-bound approvals.
|
||||
5. Tests execute through `codex sandbox` too. Never execute a repository-controlled build/test command directly as the trusted host publisher. If sandbox execution cannot access a required safe development fixture, stop and qualify an appropriate constrained setup; do not disable sandbox/network controls to get green output.
|
||||
6. The trusted publisher controls Git serially, disables hooks, uses explicit non-production refs, never force-pushes and verifies remote HEAD. Provision server-side protected main/production refs and branch-limited development credentials. Use a separate clone so a worker does not share the human workspace's Git directory or hooks. All controllers for one Git common directory use the same OS-held lock.
|
||||
|
||||
The current task runs in an unrestricted assistant environment, but **does not use that permission level for unattended workers**. Real execution is initially disabled and additionally rejects the current unprovisioned identity/certificate/sandbox conditions. No approval key or unattended system task was installed. These operational boundaries require owner qualification and remain CONDITIONAL until then.
|
||||
|
||||
## Durable state, tests and process safety
|
||||
|
||||
The store uses same-directory atomic replace, fsync, checksum and a last-verified backup. It preserves RUNNING before launch. A launch-intent marker precedes process creation; after spawn, cleanup protection covers PID-marker failures. Input is a local file, so a child refusing stdin cannot block timeout/pause supervision. stdout/stderr are drained concurrently in bounded chunks; byte and line budgets prevent unbounded logging allocations. Each session has a wall-clock budget; the host VM/job must enforce hard CPU/RAM/process constraints and parent-death behavior.
|
||||
|
||||
Windows workers launch suspended, are attached to a kill-on-close Job Object, then resume. The Job imposes a configurable process-count and total-memory cap and kills contained descendants when the controller closes/dies. The delayed-assignment regression proves no worker code executes before attachment; the abrupt-parent-death test checks both child and grandchild termination. A crash before attachment can leave a suspended, non-executing process, so persistent RUNNING/launch markers still require signed owner reconciliation before relaunch. An old PID may have been reused. Do not blindly kill it. The operator must inspect the recorded tree/session and confirm it is gone. A lock prevents controller overlap; it cannot independently prove an old process stopped. No automatic deletion of a recovery marker occurs merely because time elapsed. CPU/whole-host limits and native sandbox enforcement still require operator qualification.
|
||||
|
||||
Test process exits, fresh structured results, expected identities, required artifacts and hashes are checked independently. A model's "complete" or "conditional" output is only a proposal. Missing adapters/scans/approvals block. Artifact tampering between verification/publication and approval blocks. A commit written just before a crash can be reconciled only when its exact controller transaction trailer, parent and durably prepared verification/content hashes match. Otherwise stop for operator recovery. A publication failure retries the same local commit without model rerun.
|
||||
|
||||
Final qualitative acceptance uses independent signed review of all source requirements. All seven stage completions remain development decisions. There is no code path for production deployment, main merge, destructive migration, paid service signup, risk suppression or production credential retrieval. This does not claim a sandbox can prevent every malicious Git/API command by itself; server and OS policy remain essential.
|
||||
|
||||
## Secrets and evidence
|
||||
|
||||
Child environments inherit a small OS/path allowlist, CODEX_HOME and an orchestration marker. They do not inherit arbitrary API-key/production variables or sockets. Authentication material and protected logs must have owner-reviewed ACLs. Source snapshots are prompts and technical instructions, not private CVs or production documents.
|
||||
|
||||
Logs redact common password/token/API-key/Bearer/basic-URL patterns. Generic free text, encoded secrets and personal documents cannot be reliably scrubbed by regular expressions. Full stdin, result, structured test reports and session files are **private local evidence**, not public logs. Do not commit or send them externally. Notifications contain only stage IDs and bounded redacted status, never raw documents. Error output remains a reason to inspect private logs, not permission to paste them into a provider. The checked-in reports contain only synthetic test results and safe technical identities.
|
||||
|
||||
Back up control state, manifest, config, prompt versions, approvals, reports and Git checkpoint identities using the operator's approved encrypted backup policy. Do not put the signing private key into runner backups. Corruption recovery is an availability feature, not proof of tamper resistance; ACL/VM isolation protects against malicious writes.
|
||||
|
||||
## Current limitations
|
||||
|
||||
- Native sandbox failed with `CryptUnprotectData failed: 2148073483`; real shell isolation, plugin isolation and model execution were not qualified here.
|
||||
- Automated tests cover state transitions and .NET signature enforcement with disposable inputs. They do not qualify real hosted CI, provider licences, live models, physical devices, language accuracy, production infrastructure or hard host resource quotas.
|
||||
- Runtime services, mandatory scan capabilities and stage-specific membership/qualification adapters must be installed and independently approved before their checkpoint can execute.
|
||||
- Accepted stage policy cannot be rewritten in place. New scope/new stages require owner-reviewed migration or a separate queue. No automatic production stage exists.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Autonomous roadmap follow-up
|
||||
|
||||
Implementation checkpoints AUTO-00–08 are complete in the qualified scope described in ACCEPTANCE.md. The following are deliberately **not authorized/completed** by installing the controller:
|
||||
|
||||
- [ ] Finish current Pre-Phase-10 acceptance; owner records final accepted baseline and candidate-specific cleanup entry.
|
||||
- [ ] Publish and independently verify the final pre-Phase-10 development ref (last verified remote still `994bf8f`, local reported `5032ccb`).
|
||||
- [ ] Provision dedicated non-production runner/signing identities and protected control-plane installation; resolve/qualify native sandbox failure and actual read/egress/tool/resource boundaries.
|
||||
- [ ] Qualify checkpoint-specific provider/browser/Python/PDF/security/preservation adapters, exact suite membership and synthetic runtime fixtures. Do not flip configured merely to bypass this gate.
|
||||
- [ ] Review the packs' substage/finding branch preferences and resolve the exact authorized branch policy explicitly.
|
||||
- [ ] Sign the proposed enabled policy, environment and roadmap grants plus `phase10-development-entry` only after explicit owner authorization. No real stage has run.
|
||||
- [ ] Later, provide mandatory Product Review, provider rights, locale/native, four-concept homepage, security findings and release-evidence decisions at their actual gates.
|
||||
- [ ] Optionally provision Task Scheduler under the qualified runner; no schedule is installed now.
|
||||
|
||||
Production/main merge remains outside this queue, requiring a separate explicit owner process.
|
||||
Reference in New Issue
Block a user