Files
aios/runbooks/agent-fix-action-contracts-20260825.md
T

12 KiB

Agent Execution Contract — Action Contract Regression Repair

Objective

Fully repair the current AIOS Action runtime/contract overlay regressions on the single server, without modifying protected refs directly and without introducing new infrastructure. The task is not complete until the deployed staging/action overlay passes all acceptance gates.

Authority and scope

  • Repository: aios/aios
  • Base at task creation: 3244f0f17f8845592ac94d585f5ebd65693c9f29
  • Governed task: fix-action-contracts-20260825-1407
  • Target branch: agent/fix-action-contracts-20260825-1407
  • Protected refs must not be directly written: main, release tags, baseline registry, production runtime.
  • No new SaaS, database, agent framework, or monitoring platform may be introduced.

Non-interactive rules

The Agent must run the whole flow unnattended:

  1. Collect facts.
  2. Determine root causes.
  3. Make the smallest correct changes.
  4. Run unit/integration/contract tests.
  5. Deploy to staging only.
  6. Restart only the affected non-production services.
  7. Run the full Action smoke suite.
  8. On failure, automatically collect logs, diagnose, fix, and retry.
  9. If a change causes a new regression, automatically roll back the staging change to the previous known-good configuration and record the failure.
  10. Stop only if an owner decision is required for a high-risk, irreversible, or production-boundary action.

Fact collection — required before editing

Record all of the following in the final evidence bundle:

  • id, hostname, uname -a, date --iso-seconds
  • git rev-parse --show HEAD for authority worktree and running overlay source
  • git status --porcelaine=v2
  • git remote -v
  • current systemd service unit(s), drop-ins, Environment/EnvironmentFile sources for GitOps/Bredge/release services
  • systemctl show <affected-service> including User=, Group=, Environment=, EnvironmentFile=, ExecStart=
  • resolved Gitea API base URL after env/config expansion; redact secrets but not scheme/host
  • stat -c, namei -l, getfacl, als -ld on /var/lib/aios-gitops/silent-release` and its parents
  • find Action OpenAPI/schema generator and runtime operation definitions for commitFilesGoverned
  • find the release version validator(s) and all callers of getTagPublicationStatus
  • find reconcileGitOpsJob implementation and durable binding validation logic
  • find `getDiff implementation and transport output limits

Do not edit any file until the actual implementation and configuration sources have been located.

Repair 1 — Gitea API URL

Symptoms:

  • getReleaseConsistency → Gitea API URL must be HTTP(S)
  • runReleaseAcceptance → `Gitea API URL must be HTTP(ÊX

Required behavior:

  • Determine which env/config key is projected into the current contract overlay.
  • Compare the deployed overlay with V2R2C1 known-good configuration/deployment manifests.
  • Restore a valid HTTP:// or HTTPS:// Gitea API base URL.
  • Add startup config validation so invalid schemes fail at health/startup with a config-specific message, not during a release check.
  • Never hard-code a different Gitea host if the existing deployment already has a single authoritative source.

Repair 2 — durable release state permissions

Symptom:

  • getReleaseSaga → Permission denied: '/var/lib/aios-gitops/silent-release'

Required behavior:

  • Identify the actual runtime service User/Group.
  • Grant only the required traverse/read/write permissions for the durable state directories the service must use.
  • Prefer ownership + group mode or a specific ACL; keep the directory non-world-writable.
  • Persist the permission in deployment/install logic so restart/reboot does not regress.
  • Verify create/read/update of a staging-only saga state file under the service identity.

Repair 3 — release version contract

Symptom:

  • getTagPublicationStatus("V2R2C1") → invalid release version
  • The same runtime exposes V2R2C1 as approved_release_version.

Required behavior:

  • Locate all version validators; consolidate onto one canonical parser.
  • Accept the AIOS canonical namespace ^V[0-9]+R[0-9]+C[0-9]+$.
  • Preserve any additional already-supported legacy formats unless they are security-sensitive.
  • Add contract tests proving that the version accepted by capabilities is accepted by status, candidate, consistency, acceptance, and tag publication.

Repair 4 — commitFilesGoverned schema parity

Symptom:

  • Runtime capability metadata requires files.
  • Published Action tool schema does not expose files.
  • Call reaches Bridge and fails BRIDGE_REQUEST_FIELDS_MISSING.

Required behavior:

  • Find the canonical runtime operation contract.
  • Generate the external tool schema from the same source of truth; do not manually copy a parallel schema.
  • files must be required and must represent a list of file objects with at least path and content_base64.
  • Add a parity test that compares runtime required fields with published Action required fields.
  • Add a real governed commit test that writes two test files to an isolated agent/ ibranch and verifies remote OID.

Repair 5 — terminal reconciliation

Symptom:

  • A governed job read back as COMPLETED' but reconcileGitOpsJobfailedDURABLE_BINDING_INVALID`.

Required behavior:

  • Reconciling a terminal successful job must be idempotent.
  • An expired writer lease must not invalidate a durable binding for a job that is already terminal.
  • Active-job reconciliation may require a live lease; terminal read-back must not.
  • Add cases for COMPLETED, FAILED, CANCELLED / equivalent terminal states.

Repair 6 — bounded getDiff output

Symptom:

  • Large valid diffs fail with ResponseTooLargeError or GIT_OUTPUT_LIMIT_EXCEEDED.

Required behavior:

  • Do not load unbounded diff text into the Action response.
  • Return bounded summary data: commit identities, changed paths/stats, total bytes, and truncated: true when the full patch exceeds the safe limit.
  • If pagination already exists in the contract use it; otherwise prefer deterministic truncation over a breaking schema change.
  • Add tests for small, empty, and oversize diffs.

Staging deployment procedure

  1. Run the existing mandatory test suite before modification; record baseline.
  2. Apply code and config changes only on the governed branch/worktree.
  3. Run focused regression tests.
  4. Run the full mandatory suite.
  5. Build the staging contract overlay using the repository's existing build/deploy path.
  6. Deploy to staging/non-production only.
  7. If systemd units are changed: systemctl daemon-reload, then restart only the affected staging services.
  8. Wait for the existing health endpoint/runtime status to become healthy.
  9. Run the acceptance suite below.

If any step fails:

  • collect journalctl logs and relevant app logs;
  • diagnose root cause;
  • automatically repair and retry when non-destructive;
  • if a new change breaks staging, restore the previous staging artifact/config and restart the affected service;
  • never silently continue after a failed gate.

Acceptance suite

All of the following must pass on the same deployed staging overlay:

  • Runtime status is active and healthy after restart.
  • Gitea Git/API readback works from the runtime service identity.
  • `getReleaseConsistency(V2R2C1, 998d303047, a8b906d1bc, approved_plan) returns a structured result and reaches evaluation.
  • runReleaseAcceptance for the same identities reaches policy evaluation, not URL validation error.
  • getTagPublicationStatus("V2R2C1") returns structured state, not invalid release version.
  • getReleaseSaga for a nonexistent candidate returns NOT_FOUND/empty-state semantics, not filesystem permission failure.
  • commitFilesGoverned exposes its required files parameter in the published Action schema.
  • A real two-file governed commit to an isolated agent/ branch succeeds and remote branch OID matches.
  • Resuming a COMPLETED job returns the existing JOB_TERMINAL semantics or idempotent success as designed.
  • Reconciling a COMPLETED governed job is successful/idempotent and does not require an active lease.
  • Small/empty `getDiff still works.
  • Large getDiff returns bounded output with truncation metadata instead of a transport exception.
  • Existing protected-ref controls remain unchange: no direct main/tag/baseline/production write.

Restart / reboot persistence

After the first full pass:

  • Restart the staging Action/Bridge/release services one more time without changing files.
  • Rerun the acceptance suite.
  • Permissions, Gitea URL, and schema must still be correct after restart.
  • If the repository already has a safe staging reboot test, run it as well.

Evidence and completion

Create a single durable report in the repository, e.g. reports/action-contract-repair-evidence-20260825.md, containing:

  • pre-change facts
  • root cause for each regression
  • files changed and why
  • config/permission changes
  • test commands and exact results
  • staging deployment identity (commit/artifact/config digest)
  • restart-persistence results
  • final Action smoke results
  • any remaining risks

Commit all source, test, deployment config, and runbook changes to the governed task branch. Do not mark the task SUCCEEDED until all acceptance gates pass on the actually deployed staging overlay.

Automatic rollback conditions

Automatically roll back the staging deployment if any of the following occur:

  • service fails to become healthy after restart
  • protected-ref write boundary is broken
  • Gitea readback that worked before the change stops working
  • durable saga state cannot be read or recovered
  • mandatory test suite regresses below the pre-change baseline

Do not automatically roll back an existing production release. Rollback here refers only to the staging overlay/service configuration changes made by this task.

2026-08-25 execution record

The repair branch was deployed through the existing immutable staging builder. The final source code before the evidence commit was 2ec49005bde44f6981b14351500847d594e0276c; the deployed artifact was built from that source with SHA256 f67aed6cc0cce1f08197485c3eea204d3ef4d3989f44dc98e8ea2691e5886cbf. The final staging drop-ins use a lexically highest zzzz...-999.conf layer so they override earlier diagnostic overlays.

The runtime configuration is staging-only: User=aiman, Group=gitops, API base https://g.cnnetmkt.top/git/api/v1, baseline authority /var/lib/aios-gitops/model-api-staging/baseline/current.json, and read/write access to the staging state plus the authoritative bare repository required by the governed Writer/CAS path. No main, protected tag, baseline registry, or production write is enabled.

The release executor now binds both the configured staging baseline and the immutable runtime package's versions/V2R2C1.json projection. The bridge passes AIOS_GITOPS_BASELINE_AUTHORITY into RuntimeConfig; this prevents release consistency and acceptance from falling back to missing publication-workspace files.

The final acceptance result is recorded in reports/action-contract-repair-evidence-20260825.md. Contract smoke is green, and release consistency is PASS; release acceptance is structured policy output but remains accepted=false because the pre-existing publication state is REMOTE_PUSH_PENDING for the protected V2R2C1 tag. The task must therefore remain NEEDS_REWORK until an authorized owner resolves that independent protected-tag state.

External Action Surface final closure attempt (2026-08-25)

本轮仅部署 staging/non-production;没有直接写入 main�release tag�baseline registry 或 production。

Public route ownership: /api/governed-write-capabilities, /api/control-plane-snapshot, /api/online-agent-task, and /api/online-agent-task-events are exact-location proxied to 127.0.0.1:18890; generic /api/ remains on 127.0.0.1:18893. The durable installer is ops/gitops-migration/bind_external_action_surface_final_staging.sh; it backs up Nginx, runs nginx -t, reloads, and forwards Authorization/X-AIOS-Token.

A task-control token, local Writer grant, Gitea consumer, SSH credential, or old token file is not an external Action bearer. If formal issuance is unavailable, do not print or rotate secrets, enable disabled writes, or manufacture commit evidence; record FORMAL_STAGING_ACTION_BEARER_ISSUANCE_NOT_AVAILABLE. Public release-consistency and release-acceptance use the canonical Bridge v2 evaluator. A Task API continuation remains QUEUED until a legitimate Agent claims it and gives durable result evidence.