Skill v1.0.0
currentTrusted Publisher100/100version: "1.0.0" name: batch-modernization description: Deterministic local control-plane utilities for parsing, preflighting, validating, and tracking multi-repository modernization batches. user-invocable: false
Batch Modernization Control Plane
This skill owns deterministic batch configuration and state operations. It does not assess source code, generate plans, execute migrations, or invoke MCP tools.
Batch Assessment provides a config-aware multi-repository workflow. modernize is the only public entry. Every new request uses the read-only default-config probe first. When .github/modernize/repos.json exists, the first question always asks Batch or Single, regardless of scope wording; when absent, explicit scope applies and otherwise classic Single remains the default. Configuration discovery never selects Batch or approves execution. Planning, Execution, retry, and takeover scheduling remain disabled. Use only the scripts under scripts/; never edit batch state files manually.
Hard Boundaries
- Deterministic scripts do not invoke agents, MCP tools, Assessment, Planning, or Execution. The internal coordinator owns phase-agent dispatch.
- Do not modify application source or existing Git worktrees.
- Do not stash, switch branches, fetch, rewrite origins, discard changes, push, or create commits.
- Keep credentials out of command-line arguments and persisted files.
- Treat unknown schema versions, malformed inputs, path escapes, wrong owner tokens, and invalid evidence as blocking errors.
- A takeover lease is read-only. It cannot mutate batch state or schedule work until worker fencing exists.
- Batch Assessment starts only attempt 1 for a pending execution unit and permits only one active phase invocation across the batch.
Inputs
config-path: Absolute or workspace-relative path torepos.json.launch-root: Absolute directory that owns.github/modernize/batches/and the defaultrepos/clone root.allowed-roots: Canonical paths already authorized by the host. Supply each separately to workspace inspection.batch-root:.github/modernize/batches/<batch-id>under the launch root.batch-runtime: For Review, derivescripts/prepare-review.mjsfrom the absolute loadedbatch-modernizationskill path. Review materializes a batch-private runtime under<batch-root>/runtimeand returns its exact digest-boundbatchAttemptScriptPath; use only that path afterward. Do not depend on a plugin-root environment variable across resumed host processes.
Read references/repos-json-compatibility.md before resolving configuration and references/phase-contract.md before creating state or validating a phase result.
0. Probe The Default Configuration
For every new top-level request, the internal batch-mode-probe checks the fixed default path without reading the file, loading this skill, installing runtime, or creating artifacts. found requires modernize to ask Process repositories from repos.json or Only process the current repository. Only the first choice permits Batch Review; neither choice is execution approval.
1. Resolve Configuration
node <batch-runtime>/scripts/resolve-repos.mjs `--config <config-path> `--launch-root <launch-root> `--output <batch-scratch>/resolved-repos.json
The resolver accepts v1/v2, assigns stable repository and execution-unit IDs, preserves safe unknown metadata, strips URL secrets, and rejects invalid names, path collisions, unsafe include paths, branches, and app references. Do not proceed after a nonzero exit.
2. Clone Missing URL Repositories
Clone only repositories approved in the Review. Pass the original URL through the process environment, never an argument or persisted intermediate file:
$env:BATCH_CLONE_URL = <original-url>node <batch-runtime>/scripts/inspect-workspaces.mjs clone `--target <target-workspace> `--allowed-root <clone-root> `--branch <configured-branch>Remove-Item Env:BATCH_CLONE_URL
The script strips HTTP credentials/query/fragment before invoking Git, clones into a unique temporary sibling, and publishes with an atomic rename. Failure removes the temporary directory and leaves the target absent.
3. Inspect Workspaces
node <batch-runtime>/scripts/inspect-workspaces.mjs inspect `--resolved <batch-scratch>/resolved-repos.json `--allowed-root <authorized-root-1> `--allowed-root <authorized-root-2> `--output <batch-scratch>/inspected-repos.json
Inspection resolves real paths, rejects symlink/junction escapes, detects supported project languages, and checks Git origin, branch, and dirty state without modifying the repository. needs_attention requires a batch-level decision; blocked cannot run.
4. Initialize Batch State
Initialize Batch Assessment from the post-clone inspected repositories and the digest-bound approved Review. The input file contains only userRequest:
node <batchAttemptScriptPath> initialize-assessment `--batch-root <batch-root> `--resolved <post-clone-inspected-repos.json> `--review <review.json> `--review-sha256 <review-sha256> `--review-markdown-sha256 <review-markdown-sha256> `--input <assessment-input.json>
The initializer verifies Review identity and artifact digests, then derives the batch ID, execution-unit selection, attention approvals, and Assessment decisions from review.json. Blocked, substituted, or unapproved items fail closed. Preserve the digest-bound pre-clone inspected-repos.json; write reinspection output to a separate file.
5. Open A Lease Session
$session = node <batchAttemptScriptPath> open-session `--batch-root <batch-root> `--invocation-id <coordinator-invocation-id> `--execution-unit-id <first-execution-unit-id> | ConvertFrom-Json
open-session starts the first unit and returns its requestPath plus a random leaseSessionId. The private local worker keeps the raw owner token only in memory. The token is never returned, logged, written to disk, placed in a terminal environment, or sent to a phase agent. Use the session ID only for coordinator lifecycle commands and never include it in the phase prompt.
6. Takeover Is Read-Only
A stale lease may be inspected or explicitly taken over for read-only inspection, but schedulingAllowed remains false. Do not start a new attempt after takeover.
7. Validate Attempt Results
validate-result.mjs checks schema, identity, status/payload consistency, secret safety, canonical artifact containment, artifact existence, and Assessment evidence. Any failure returns protocol_error; never convert it to success based on agent prose.
8. Batch Assessment Attempt Lifecycle
open-session starts the first pending unit. Start each later unit through the same lease session:
node <batchAttemptScriptPath> session-start `--lease-session-id <lease-session-id> `--execution-unit-id <execution-unit-id>
The command writes immutable request.json, persists Running before dispatch, and returns the request path. Pass only that path to batch-assessment.
The phase agent publishes exactly one identity-bound result without an owner token:
node <batchAttemptScriptPath> publish `--request <request.json> `--outcome <outcome.json>
After the phase invocation returns, commit the result regardless of its natural-language return:
node <batchAttemptScriptPath> session-commit `--lease-session-id <lease-session-id> `--request <request.json>
Missing, malformed, mismatched, or unsupported evidence becomes protocol_error. Once all units are terminal, write the aggregate summary and release the lease:
node <batchAttemptScriptPath> session-finalize-assessment `--lease-session-id <lease-session-id>
Completion
Batch Assessment completion means an explicitly approved set of execution units can run sequential attempts, preserve the verified canonical repository reports, and atomically publish a user-facing assessment/reports-<timestamp>/ tree containing index.html, aggregate-report.json, and digest-identical per-repository snapshots. Internal batch state remains under batches/<batch-id>/. It does not authorize Planning or Execution, retry terminal units, or schedule work after takeover. Single-repository defaults and artifacts remain unchanged.