Resources
2Install
npx skillscat add cuioss/plan-marshall/manage-run-config Install via the SkillsCat registry.
Manage Run Config Skill
Run configuration handling for persistent command configuration storage.
Enforcement
Base contract: See manage-contract.md for shared enforcement rules, TOON output format, and error response patterns.
Skill-specific constraints:
- Do not bypass initialization (run-config.json must exist before queries)
- Timeout and warning operations use the noun-verb pattern (e.g.,
timeout get,warning add) - Cleanup operations use
cleanupandcleanup-statussubcommands - Architecture-refresh operations use the noun-verb pattern (
architecture-refresh get-tier-0,architecture-refresh set-tier-0, etc.) - Build-queue-limit operations use the noun-verb pattern (
build-queue-limit get,build-queue-limit set) - CI-duration operations use the noun-verb pattern (
ci-duration record,ci-duration p50)
Run Configuration Structure
{
"version": 1,
"commands": {
"<command-name>": {
"last_execution": {"date": "...", "status": "SUCCESS|FAILURE"},
"acceptable_warnings": [],
"skipped_files": []
}
},
"maven": {
"acceptable_warnings": {
"transitive_dependency": [],
"plugin_compatibility": [],
"platform_specific": []
}
},
"architecture_refresh": {
"tier_0": "enabled",
"tier_1": "prompt"
},
"build": {
"queue": {
"upper_limit_seconds": 600
}
},
"ci_durations": {
"<command-name>": [420, 380, 455]
},
"ci": {
"authenticated_tools": [],
"verified_at": null
}
}See standards/run-config-standard.md for complete schema.
Scripts
| Script | Notation |
|---|---|
| init | plan-marshall:manage-run-config:run_config init |
| validate | plan-marshall:manage-run-config:run_config validate |
| timeout get | plan-marshall:manage-run-config:run_config timeout get |
| timeout measured | plan-marshall:manage-run-config:run_config timeout measured |
| timeout set | plan-marshall:manage-run-config:run_config timeout set |
| warning add | plan-marshall:manage-run-config:run_config warning add |
| warning list | plan-marshall:manage-run-config:run_config warning list |
| warning remove | plan-marshall:manage-run-config:run_config warning remove |
| architecture-refresh get-tier-0 | plan-marshall:manage-run-config:run_config architecture-refresh get-tier-0 |
| architecture-refresh set-tier-0 | plan-marshall:manage-run-config:run_config architecture-refresh set-tier-0 |
| architecture-refresh get-tier-1 | plan-marshall:manage-run-config:run_config architecture-refresh get-tier-1 |
| architecture-refresh set-tier-1 | plan-marshall:manage-run-config:run_config architecture-refresh set-tier-1 |
| build-queue-limit get | plan-marshall:manage-run-config:run_config build-queue-limit get |
| build-queue-limit set | plan-marshall:manage-run-config:run_config build-queue-limit set |
| ci-duration record | plan-marshall:manage-run-config:run_config ci-duration record |
| ci-duration p50 | plan-marshall:manage-run-config:run_config ci-duration p50 |
| cleanup | plan-marshall:manage-run-config:run_config cleanup |
| cleanup-status | plan-marshall:manage-run-config:run_config cleanup-status |
Script characteristics:
- Uses Python stdlib only (json, argparse, pathlib)
- All commands output TOON to stdout
- Exit code 0 for success, 1 for errors
- Supports
--helpflag
Calling convention: All commands use plan-marshall:manage-run-config:run_config {command}. The cleanup module is integrated into run_config as cleanup/cleanup-status subcommands.
Standards
| Document | Purpose | When to Read |
|---|---|---|
| run-config-standard.md | Schema, timeouts, warnings, cleanup | Full run configuration reference |
Operations
Script: plan-marshall:manage-run-config:run_config
init
Initialize run-config.json with defaults.
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config initvalidate
Validate configuration structure.
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config validate --file run-configuration.jsontimeout get / measured / set
Manage adaptive command timeouts. Every value on this surface is in SECONDS — the persisted field is timeout_seconds, and --default, --explicit, and --duration are all seconds, never milliseconds.
Resolution order for timeout get:
--explicit Nsupplied →Noverrides the persisted learned value outright; no learned value can reduce it.--explicitomitted → the persisted learned value applies (scaled by the safety margin), falling back to--defaultwhen nothing is persisted.- A 120-second floor binds on both paths — an explicit bound does not waive it, because the floor protects against under-specification.
# Get current timeout for a command (--default: fallback seconds when unlearned)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout get \
--command mvn-verify --default 300
# Override the learned value with an explicit bound (seconds)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout get \
--command mvn-verify --default 300 --explicit 1800
# Record an observed duration (seconds) into the adaptive value
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout set \
--command mvn-verify --duration 180
# Ask whether a key has EVER been measured (raw persisted value, unscaled/unfloored)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout measured \
--command mvn-verifytimeout measured answers a question timeout get structurally cannot: get returns an int for a measured and an unmeasured key alike, so its value carries no signal about whether the command has ever been observed. measured returns measured: true|false plus the RAW persisted timeout_seconds (null when unmeasured), with neither the safety margin nor the 120 s floor applied — any adjustment would blur the distinction the verb exists to expose. Its consumer is the execution_tier fail-closed rule in `manage-architecture` § Lookup Path: an unmeasured build command routes to the orchestrator rather than being run in-leaf on an unobserved first run.
warning add / list / remove
Manage acceptable build warning patterns.
# Add an acceptable warning
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config warning add \
--category transitive_dependency --pattern "jakarta.json-api"
# List warnings for a category
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config warning list \
--category transitive_dependency
# Remove a warning pattern
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config warning remove \
--category transitive_dependency --pattern "jakarta.json-api"architecture-refresh get-tier-0 / set-tier-0 / get-tier-1 / set-tier-1
Manage the architecture_refresh tier knobs consumed by the phase-6-finalize architecture-refresh step. Defaults are returned when the section is absent — init does not need to materialise the section. Tier-0 controls the deterministic architecture discover --force step (default enabled); Tier-1 controls LLM re-enrichment (default prompt).
# Read current tier settings (defaults: tier_0=enabled, tier_1=prompt)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh get-tier-0
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh get-tier-1
# Disable the deterministic refresh entirely
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh set-tier-0 \
--value disabled
# Switch LLM re-enrichment to fully automatic (prompt|auto|disabled)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh set-tier-1 \
--value autoAllowed values:
tier_0:enabled,disabledtier_1:prompt,auto,disabled
Invalid values surface the standard status: error, error: invalid_value, allowed: [...] contract.
build-queue-limit get / set
Manage the adaptive build.queue.upper_limit_seconds knob consumed by build_queue.validate_lock_queue — the self-healing build-queue stale reaper. The limit is the per-build held-duration ceiling the reaper measures against: an active slot is reaped once its age exceeds 2 × this limit. It defaults to and floors at 600 s (10 min), is capped at a 3600 s (1 h) ceiling, and is monotonic-up but clamped — build_queue release grows it toward the longest observed real build held-duration so a legitimately long build is never falsely reaped, while the ceiling prevents a single anomalously long hold from ratcheting it beyond an hour. The knob lives under the build.queue block in the main-anchored run-configuration.json, so reads/writes resolve against the main checkout regardless of caller cwd.
# Read the current limit (default/floor 600 s, always clamped to [600, 3600])
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config build-queue-limit get
# Set the limit explicitly (positive int seconds; clamped to [600, 3600])
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config build-queue-limit set \
--value 1800A non-positive --value surfaces the standard status: error, error: invalid_value contract; a value outside [600, 3600] is clamped (not rejected) on write.
ci-duration record / p50
Manage the bounded rolling window of observed successful CI-run durations that seeds the adaptive CI-wait first-sleep. Durations are persisted per command key under the top-level ci_durations map (mirroring the commands keyed shape) in the main-anchored run-configuration.json, so reads/writes resolve against the main checkout regardless of caller cwd. record appends the observed duration and bounds the window to the newest CI_DURATION_WINDOW_SIZE (default 5) entries, evicting the oldest. p50 returns the median of the window as the first-sleep seed — p50_seconds: null when the window is empty or absent (the consumer skips the seed on a null signal).
# Record an observed successful CI-run duration (seconds) into the key's window
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config ci-duration record \
--command ci:wait --duration 420
# Get the p50 (median) seed for the key (p50_seconds: null on an empty window)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config ci-duration p50 \
--command ci:waitFor an odd-sized window p50_seconds is the middle observed duration; for an even-sized window it is the mean of the two middle values.
language-server get / set / list / remove
Manage the machine-local language_servers binding read by the `lsp-client` skill — the language-to-server map a phase-5-execute leaf uses for opt-in symbol lookup and verified edits. The binding is machine-local (server availability is per-machine tooling) and lives under the top-level language_servers map in the main-anchored run-configuration.json. An absent or enabled: false language is not configured, and lsp-client degrades to the Read / Edit path. See run-config-standard.md § "Language-Servers Section" for the schema.
# Bind a language server (--command is a JSON array of strings)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config language-server set \
--language python --command '["pyright-langserver", "--stdio"]' --language-id python
# Read the binding for a language (configured: false when absent)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config language-server get \
--language python--disabled on set stores the binding but leaves it inactive; list reports the configured language keys; remove deletes a binding.
display-timezone get / set
Manage the display-only render timezone — a single top-level display_timezone IANA zone name (default UTC). It is consumed exclusively at rendering surfaces to convert a stored UTC timestamp for human reading, and is never consulted on a write or compare path: storage and comparison stay UTC unconditionally. The default UTC makes the unset behaviour byte-identical to the pre-knob rendering, so no existing artifact changes unless the operator opts in. See run-config-standard.md § "Display-Timezone Section".
# Read the display timezone (default UTC when absent)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config display-timezone get
# Set the display timezone (validated as an IANA zone name)
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config display-timezone set \
--value America/New_Yorkset rejects a value that is not a loadable IANA zone with an invalid_value error and persists nothing.
cleanup / cleanup-status
Directory cleanup using retention settings from marshal.json.
# Check what would be cleaned up
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config cleanup-status
# Run cleanup
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config cleanup
# Clean a single target
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config cleanup --target no-plan-bodies--target selects one of five cleanable targets, or all (the default) to run every one:
| Target | Retention knob | Cleans |
|---|---|---|
temp |
temp_on_maintenance |
The project-local .plan/temp/ scratch tree |
logs |
logs_days |
Aged *.log files under the runtime logs directory |
archived-plans |
archived_plans_days |
Aged archived-plan directories |
no-plan-bodies |
no_plan_body_days |
Aged prepared CI body files (*.md) under the plan-less NO_PLAN sentinel |
build-results |
build_results_days |
Aged build-result files under a NON-live plan's build-results/ tree, and under the NO_PLAN sentinel's |
The no-plan-bodies target exists because the NO_PLAN sentinel is a shared, permanent plan directory that is never archived — archived_plans_days never reaches it, so without this target the body files plan-less callers prepare would accumulate indefinitely. It removes only the aged body files; the sentinel directory, its work/ subtree, and its status.json marker are never removed, and a missing sentinel directory is a clean no-op rather than an error.
The build-results target ages the per-plan build-output trees, and is guarded so it can never reap a running plan's results. It enumerates plan directories from the plan store and skips a LIVE plan's tree entirely — a plan is live for as long as its directory carries a status.json marker. A live plan's results appear in NEITHER the cleanup nor the cleanup-status population, so they are never counted as reclaimable rather than merely spared deletion. Only a plan directory whose status.json is absent, and the never-archived NO_PLAN sentinel, are subject to the age threshold; a finished plan is aged instead by archived_plans_days once archive-plan has moved it under archived-plans/.
See `manage-config` data-model.md § Retention Fields for the canonical knob semantics of both targets.
Error Responses
See manage-contract.md for the standard error response format.
| Error Code | Cause |
|---|---|
key_not_found |
Configuration key doesn't exist |
invalid_value |
Value fails type/enum validation (e.g., non-numeric timeout, architecture-refresh enum mismatch) |
not_initialized |
run-config.json missing (run init first) |
invalid_category |
Warning category not in: transitive_dependency, plugin_compatibility, platform_specific |
marshal_not_found |
marshal.json missing (cleanup needs retention settings) |
Integration
Producers
| Client | Operation | Purpose |
|---|---|---|
marshall-steward |
init | Initialize run configuration during setup |
marshall-steward |
architecture-refresh set-tier-0/1 | Persist user-selected tier knobs from setup/maintenance wizard |
| Build skills | timeout set | Update timeouts after command execution |
| Build skills | warning add | Register acceptable warning patterns |
manage-locks build_queue release |
build-queue-limit set | Persist the clamped adaptive upper limit from the released entry's held duration |
CI-wait handlers (_github_ci, gitlab_ops) |
ci-duration record | Record an observed successful CI-run duration into the p50 window on natural completion |
Consumers
| Client | Operation | Purpose |
|---|---|---|
| Build skills | timeout get | Read timeout values for command execution |
manage-architecture _lookup_bash_timeout |
timeout measured | Read measured-ness for the execution_tier fail-closed rule (unmeasured → orchestrator) |
| Build skills | warning list | Filter build warnings against accepted patterns |
phase-6-finalize architecture-refresh step |
architecture-refresh get-tier-0/1 | Read tier knobs to decide deterministic refresh / LLM re-enrichment behaviour |
manage-locks build_queue acquire/release |
build-queue-limit get | Read the adaptive upper limit to compute the 2 × stale-reclaim threshold |
CI-wait handlers (_github_ci, gitlab_ops) |
ci-duration p50 | Read the p50 seed for the adaptive CI-wait first-sleep (skip on a null window) |
Canonical invocations
The canonical argparse surface for run_config.py. The plugin-doctor analyzer (_analyze_manage_invocation.py) reads this section as source-of-truth for the manage-invocation-invalid and missing-canonical-block rules. Consuming docs xref this section by name instead of restating the command inline. See `pm-plugin-development:plugin-script-architecture` cross-skill-integration.md § "Script invocation in documentation".
init
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config init [--force]validate
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config validate --file FILEtimeout
timeout carries the nested sub-verbs get, measured, and set:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout get \
--command COMMAND --default DEFAULT [--explicit EXPLICIT]
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout measured \
--command COMMAND
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config timeout set \
--command COMMAND --duration DURATIONDEFAULT, EXPLICIT, and DURATION are all in seconds. --explicit overrides the persisted learned value.
warning
warning carries the nested sub-verbs add, list, and remove:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config warning add \
--category {transitive_dependency,plugin_compatibility,platform_specific} --pattern PATTERN \
[--build-system BUILD_SYSTEM]
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config warning list \
[--category {transitive_dependency,plugin_compatibility,platform_specific}] [--build-system BUILD_SYSTEM]
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config warning remove \
--category {transitive_dependency,plugin_compatibility,platform_specific} --pattern PATTERN \
[--build-system BUILD_SYSTEM]architecture-refresh
architecture-refresh carries the nested sub-verbs get-tier-0, set-tier-0, get-tier-1, and set-tier-1:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh get-tier-0
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh set-tier-0 \
--value {enabled,disabled}
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh get-tier-1
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config architecture-refresh set-tier-1 \
--value {prompt,auto,disabled}build-queue-limit
build-queue-limit carries the nested sub-verbs get and set:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config build-queue-limit get
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config build-queue-limit set \
--value VALUEci-duration
ci-duration carries the nested sub-verbs record and p50:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config ci-duration record \
--command COMMAND --duration DURATION
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config ci-duration p50 \
--command COMMANDlanguage-server
language-server carries the nested sub-verbs get, set, list, and remove:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config language-server get \
--language LANGUAGE
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config language-server set \
--language LANGUAGE --command COMMAND [--language-id LANGUAGE_ID] [--disabled]
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config language-server list
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config language-server remove \
--language LANGUAGEdisplay-timezone
display-timezone carries the nested sub-verbs get and set:
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config display-timezone get
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config display-timezone set \
--value VALUEcleanup
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config cleanup \
[--dry-run] [--target {all,temp,logs,archived-plans,no-plan-bodies,build-results}]cleanup-status
python3 .plan/execute-script.py plan-marshall:manage-run-config:run_config cleanup-statusRelated
manage-config— Project-level marshal.json configuration (provides retention settings)manage-lessons— Complementary global persistence (lessons learned)