marketplace/bundles/plan-marshall/skills/extension-api/SKILL.md
Extension API for domain bundle discovery, module detection, and canonical command generation
npx skillsauth add cuioss/plan-marshall extension-apiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Unified API for domain bundle extensions providing module discovery, build system detection, and command generation. Provides the ExtensionBase abstract base class that all domain extensions must inherit from.
Execution mode: Reference library; load on-demand when creating or modifying extensions.
Prohibited actions:
Constraints:
ExtensionBasepython3 .plan/execute-script.py plan-marshall:extension-api:extension_discovery {command} {args}CMD_* constants for command namesPROFILE_PATTERNS vocabulary for classificationReference when:
extension.py for a domain bundlediscover_modules() for a build systemextension-api/
├── SKILL.md # This file
├── scripts/
│ ├── extension_base.py # ExtensionBase ABC, canonical commands
│ ├── extension_discovery.py # Extension discovery, loading, aggregation
│ ├── _build_discover.py # Module discovery, path building
│ ├── _build_result.py # Log file creation, result construction, validation (co-located build utility)
│ ├── _build_parse.py # Issue structures, warning filtering (co-located build utility)
│ ├── _build_format.py # TOON and JSON output formatting (co-located build utility)
│ ├── _build_execute.py # Subprocess execution, timeout learning, wrapper detection (co-located build utility)
│ ├── _build_execute_factory.py # Factory for build-system-specific handlers (co-located build utility)
│ ├── _build_shared.py # Shared CLI helpers, cmd_run_common (co-located build utility)
│ ├── _build_check_warnings.py # Warning categorization factory (co-located build utility)
│ ├── _build_coverage_report.py # Coverage report parsing factory (co-located build utility)
│ ├── _build_jvm_patterns.py # Shared JVM error patterns (co-located build utility)
│ ├── _build_parser_registry.py # Multi-parser registry (co-located build utility)
│ ├── _coverage_parse.py # Format-agnostic coverage parsing (co-located build utility)
│ ├── _warnings_classify.py # Warning categorization with matchers (co-located build utility)
│ └── _module_aggregation.py # Virtual module splitting
└── standards/
├── extension-contract.md # Extension API contract (core methods, overview, examples)
├── ext-point-build.md # Build system extension point contract
├── ext-point-build-verify-step.md # Phase-5 build/verify command step contract
├── ext-point-domain-bundle.md # Domain bundle shape contract (plan-marshall-plugin marker)
├── ext-point-dynamic-level-executor.md # Per-level agent variant emission contract
├── ext-point-execution-context-workflow.md # Dispatchable workflow document contract
├── ext-point-finalize-step.md # Phase-6 finalize step contract
├── ext-point-lane-element.md # Lane-element frontmatter contract — lane.{class,tier,prunable_when,cost_size} (every phase/finalize-step element)
├── ext-point-outline.md # Outline extension point contract
├── ext-point-provider.md # Credential extension point contract
├── ext-point-recipe.md # Recipe extension point contract
├── ext-point-retrospective.md # Retrospective check contract
├── ext-point-self-review-surfacing.md # Pre-submission self-review surfacing contract
├── ext-point-triage.md # Triage extension point contract — PR review comments + Sonar issues
├── ext-point-verify.md # Verify extension point contract — finding validity-verification before triage
├── dispatch-granularity.md # Dispatch granularity guidance
├── marshal-json-reference.md # Central marshal.json config path reference
├── module-discovery.md # Module discovery contract + output specification
├── canonical-commands.md # Command vocabulary and resolution
├── build-execution.md # Build execution API + return structure
├── build-api-reference.md # Build API internal reference
├── build-systems-common.md # Common patterns across build systems
├── profiles.md # Profile override mechanism + profile contracts
└── workflow-overview.md # Architecture overview + phase contracts + user review gate
All extensions must inherit from ExtensionBase and implement required methods.
| Method | Purpose |
|--------|---------|
| get_skill_domains() -> list[dict] | Return domain metadata with profiles |
| Method | Default | Purpose |
|--------|---------|---------|
| discover_modules(project_root: str) -> list | [] | Discover modules with paths, metadata, stats, commands |
| Method | Default | Purpose |
|--------|---------|---------|
| config_defaults(project_root: str) -> None | no-op | Configure project defaults (called during init) |
| provides_triage() -> str \| None | None | Return triage skill reference (covers PR review comments and Sonar issues) |
| provides_outline_skill() -> str \| None | None | Return domain-specific outline skill reference |
| provides_recipes() -> list[dict] | [] | Return recipe definitions for predefined transformations |
Each extension point has a dedicated contract document with formal parameters, pre-conditions, and post-conditions. All 15 contracts:
| Extension Point | Declared Via | Contract |
|-----------------|--------------|----------|
| Build System | discover_modules() + ExecuteConfig | ext-point-build.md |
| Build Verify Step | frontmatter implements: on step documents | ext-point-build-verify-step.md |
| Domain Bundle | skills/plan-marshall-plugin/ marker skill + extension.py | ext-point-domain-bundle.md |
| Domain Verb | provides_domain_verb() | ext-point-domain-verb.md |
| Dynamic Level Executor | frontmatter implements: on agent files | ext-point-dynamic-level-executor.md |
| Execution Context Workflow | frontmatter implements: on workflow documents | ext-point-execution-context-workflow.md |
| Finalize Step | frontmatter implements: on finalize-step skills | ext-point-finalize-step.md |
| Lane Element | lane: frontmatter block (every phase / finalize-step element) | ext-point-lane-element.md |
| Outline | provides_outline_skill() | ext-point-outline.md |
| Provider | *_provider.py | ext-point-provider.md |
| Recipe | provides_recipes() / frontmatter implements: | ext-point-recipe.md |
| Retrospective | frontmatter implements: on check skills | ext-point-retrospective.md |
| Self-Review Surfacing | frontmatter implements: | ext-point-self-review-surfacing.md |
| Triage (PR comments + Sonar issues) | provides_triage() | ext-point-triage.md |
| Verify (finding validity-verification) | producer verification_profile | ext-point-verify.md |
Implementation counts are deliberately not listed here — they drift. Enumerate live implementors with:
python3 .plan/execute-script.py plan-marshall:extension-api:extension_discovery implementors --ext-point plan-marshall:extension-api/standards/ext-point-{name}
For all extension-related configuration paths, see marshal-json-reference.md.
┌─────────────────────────────────────────────────────────────────┐
│ WORKFLOW ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ LAYER 1: PHASE SKILLS (System only - NO domain override) │
│ phase-1-init → phase-2-refine → phase-3-outline → phase-4-plan │
│ → phase-5-execute → phase-6-finalize │
│ │ │
│ │ delegates to │
│ ▼ │
│ LAYER 2: PROFILE SKILLS (System default, domain CAN override) │
│ execute-task (profiles: implementation, module_testing, etc.) │
│ │ │
│ │ loads │
│ ▼ │
│ LAYER 3: EXTENSIONS (Domain provides, loaded BY system skills) │
│ outline-ext: Codebase analysis, deliverable patterns │
│ triage-ext: Suppression syntax, severity guidelines │
│ │ │
│ │ loads │
│ ▼ │
│ LAYER 4: DOMAIN SKILLS (Loaded from task.skills at execution) │
│ java-core, java-cdi, junit-core, javascript, etc. │
│ │
└─────────────────────────────────────────────────────────────────┘
| Layer | Extension Point | Override Model | Contract Location | |-------|-----------------|----------------|-------------------| | Phase Skills | None | System only, no override | Phase SKILL.md files | | Profile Skills | workflow_skills / workflow_skill_extensions in marshal.json | Domain can replace default | profiles/ | | Extensions | provides_*() in extension.py | Additive (domain provides) | extensions | | Domain Skills | skills_by_profile in module analysis | Selected per deliverable | Domain bundle SKILL.md |
For understanding the complete system architecture, reference these documents:
| Document | Purpose | When to Read |
|----------|---------|--------------|
| extension-contract.md | Core extension API contract (ExtensionBase, get_skill_domains, examples) | Creating or modifying an extension |
| ext-point-*.md | Individual extension point contracts (14 documents) | Implementing a specific extension point |
| marshal-json-reference.md | Central marshal.json config path reference | Understanding where extension config is stored |
| module-discovery.md | Module discovery + output specification | Implementing discover_modules() |
| canonical-commands.md | Command vocabulary and resolution | Implementing discover_modules() commands |
| build-execution.md | Build execution API + return structure | Running build commands, formatting output |
| build-api-reference.md | Build API internal reference | Working with build script internals |
| build-systems-common.md | Common patterns across build systems | Understanding shared build patterns |
| profiles.md | Profile override mechanism + contracts | Understanding/overriding profile skills |
| workflow-overview.md | 6-phase workflow + user review gate | Understanding phase transitions and contracts |
| Script | Type | Purpose |
|--------|------|---------|
| extension_base.py | Library | ExtensionBase ABC, canonical commands, profile patterns |
| extension_discovery.py | Library + CLI | Extension discovery, loading, aggregation, config defaults |
| configurable_contract.py | Library + CLI | Fail-loud parser for the step-owned configurable frontmatter contract (see Configurable step-param contract) |
| _build_discover.py | Library | Module discovery, path building, README detection |
| _module_aggregation.py | Library | Virtual module splitting (depends on plan_logging) |
These are co-located here for PYTHONPATH convenience but are NOT part of the extension API. They are imported directly by build scripts (build-maven, build-npm, etc.), not through extension_base.
| Script | Type | Purpose |
|--------|------|---------|
| _build_execute.py | Library | Subprocess execution, timeout learning, capture strategies |
| _build_execute_factory.py | Library | Factory for build-system-specific execute_direct/cmd_run |
| _build_result.py | Library | Log file creation, result dict construction |
| _build_parse.py | Library | Issue structures, warning filtering |
| _build_format.py | Library | TOON and JSON output formatting |
| _build_shared.py | Library | cmd_run_common(), bash timeout helpers, canonical command generation |
| _build_coverage_report.py | Library | Coverage report parsing with factory |
| _build_check_warnings.py | Library | Warning categorization with factory |
| _build_jvm_patterns.py | Library | Shared JVM error/warning category patterns |
| _build_parser_registry.py | Library | Registry-based multi-parser for build output |
| _coverage_parse.py | Library | Format-agnostic coverage report parsing (JaCoCo, Cobertura, LCOV, Jest) |
| _warnings_classify.py | Library | Warning categorization with pluggable matchers |
The extension_discovery.py script provides CLI commands for extension operations:
# Apply config_defaults() callback for all extensions
python3 .plan/execute-script.py plan-marshall:extension-api:extension_discovery apply-config-defaults
Output (TOON):
status: success
extensions_called: 3
extensions_skipped: 2
errors_count: 0
errors[0]:
The executor sets PYTHONPATH to include extension-api/scripts/, so imports work directly:
# Extension framework (public API via extension_base re-exports)
from extension_base import (
ExtensionBase,
discover_descriptors, # Re-exported from _build_discover
build_module_base, # Re-exported from _build_discover
find_readme, # Re-exported from _build_discover
CMD_VERIFY,
CMD_MODULE_TESTS,
)
# Discovery functions
from extension_discovery import (
discover_all_extensions,
discover_project_modules,
get_skill_domains_from_extensions,
apply_config_defaults,
)
# Build utilities (co-located, not part of extension API)
from _build_result import (
create_log_file,
success_result,
error_result,
)
from _build_parse import (
Issue,
filter_warnings,
partition_issues,
)
A param-owning finalize step declares its step-owned params self-describingly
in the ----fenced YAML frontmatter of its own body doc, under a configurable:
block. configurable_contract.py is the single fail-loud reader of that
declaration; manage-config and manage-execution-manifest consume it as the
canonical default/description source for step-owned params.
---
name: sonar-roundtrip
order: 80
configurable:
- key: touched_file_cleanup
default: new_code_only
description: Which surface the Sonar roundtrip success criterion covers.
- key: do_transition
default: false
description: Gate the server-side SonarCloud dismissal path.
- key: ce_wait_timeout_seconds
default: 600
description: Budget (seconds) for the synchronous CE-readiness wait.
---
Each entry MUST carry exactly the three mandatory sub-fields:
| Sub-field | Type | Rule |
|-----------|------|------|
| key | str | The param key (snake_case, scoped within the owning step) |
| default | any JSON scalar | The seeded default value (string, int, float, bool, or null) |
| description | non-empty str | Human-readable description of what the param controls |
A param is addressed as {step_id}.{param_key} — e.g.
default:sonar-roundtrip.touched_file_cleanup. The step id carries its prefix
(default: for built-in steps, project: for project-local steps); param keys
stay snake_case with no camelCase variant.
The body doc that declares a step's configurable: block is the step's
canonical body doc, resolved by resolve_step_doc_path(step_id):
| Step kind | Body doc |
|-----------|----------|
| Built-in default: | phase-6-finalize/workflow/{name}.md, falling back to phase-6-finalize/standards/{name}.md |
| project: | .claude/skills/{name}/SKILL.md |
The placement contract and its enforcement (a param-owning step MUST declare a
well-formed block; missing/malformed declarations fail loud) are owned centrally
by the plugin-doctor step-configurable-contract rule — see that rule for the
authoritative enforcement body. This skill does not restate the enforcement
rules; it owns only the parser and the declaration shape above.
from configurable_contract import parse_configurable, resolve_step_defaults
# Parse a step body doc's configurable block to the full schema.
schema = parse_configurable(step_doc_path)
# -> {"touched_file_cleanup": {"default": "new_code_only", "description": "..."}, ...}
# Resolve a step id to just its param defaults (resolves the body-doc path first).
defaults = resolve_step_defaults('default:sonar-roundtrip')
# -> {"touched_file_cleanup": "new_code_only", "do_transition": False, ...}
Both functions raise ValueError (fail loud, no silent fallback) on every
malformed-declaration case: file not found, no frontmatter, no configurable:
block, an empty block, an entry missing any of key/default/description, a
non-string key/description, an empty description, or a duplicate key.
Import CMD_* constants from extension_base for type-safe command references:
from extension_base import (
CMD_CLEAN, # "clean"
CMD_COMPILE, # "compile"
CMD_TEST_COMPILE, # "test-compile"
CMD_MODULE_TESTS, # "module-tests"
CMD_INTEGRATION_TESTS, # "integration-tests"
CMD_COVERAGE, # "coverage"
CMD_BENCHMARK, # "benchmark"
CMD_QUALITY_GATE, # "quality-gate"
CMD_VERIFY, # "verify"
CMD_INSTALL, # "install"
CMD_CLEAN_INSTALL, # "clean-install"
CMD_PACKAGE, # "package"
ALL_CANONICAL_COMMANDS,
PROFILE_PATTERNS, # Profile ID to canonical mapping (for internal use)
)
Required commands: quality-gate (all modules), verify (non-pom), module-tests (if tests exist). clean is always separate — other commands do NOT include clean goal.
See canonical-commands.md for the complete vocabulary, resolution logic, and requirements.
#!/usr/bin/env python3
"""Extension API for {bundle-name} bundle."""
from pathlib import Path
from extension_base import ExtensionBase
class Extension(ExtensionBase):
"""Extension for {bundle-name} bundle."""
def get_skill_domains(self) -> list[dict]:
"""Domain metadata for skill loading."""
return [{
"domain": {
"key": "domain-key",
"name": "Domain Name",
"description": "Domain description"
},
"profiles": {
"core": {"defaults": [], "optionals": []},
"implementation": {"defaults": [], "optionals": []},
"module_testing": {"defaults": [], "optionals": []},
"quality": {"defaults": [], "optionals": []}
}
}]
def discover_modules(self, project_root: str) -> list:
"""Discover modules in the project.
Returns list of module dicts with:
- name, build_systems, paths, metadata, packages, dependencies, stats, commands
"""
# Find descriptors
from _build_discover import discover_descriptors, build_module_base
descriptors = discover_descriptors(project_root, "descriptor-file")
modules = []
for desc_path in descriptors:
base = build_module_base(project_root, desc_path)
# Enrich with extension-specific metadata, stats, commands
modules.append({
"name": base.name,
"build_systems": ["my-build-system"],
"paths": base.paths.to_dict(),
"metadata": {},
"packages": {},
"dependencies": [],
"stats": {"source_files": 0, "test_files": 0},
"commands": self._resolve_commands(base)
})
return modules
.plan/project-architecture/*.json filesdiscover_all_extensions() for domain configurationextension.py inheriting from ExtensionBaseThe canonical argparse surface for the skill's CLI entry-points, extension_discovery.py and configurable_contract.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".
python3 .plan/execute-script.py plan-marshall:extension-api:extension_discovery apply-config-defaults \
(--project-dir PROJECT_DIR | --plan-id PLAN_ID)
--project-dir and --plan-id are mutually exclusive.
python3 .plan/execute-script.py plan-marshall:extension-api:extension_discovery implementors \
--ext-point EXT_POINT
Enumerates every component declaring implements: {EXT_POINT} — scans every bundle's skills/*/SKILL.md, the phase-6-finalize workflow/*.md + standards/*.md step docs, and project-local .claude/skills/finalize-step-*/SKILL.md. Global discovery; takes no project-dir / plan-id routing.
python3 .plan/execute-script.py plan-marshall:extension-api:configurable_contract parse \
--path PATH
python3 .plan/execute-script.py plan-marshall:extension-api:configurable_contract resolve \
--step-id STEP_ID
development
Domain-owned OpenRewrite log-line finding parser for the java-cui domain — parses the
development
Domain-owned OpenRewrite marker detection for the java-cui domain — scans Java/Kotlin sources for cui-rewrite TODO markers, categorizes them by recipe, and fails the gate on any detected marker
development
Operator control surface for the marshalld build server — enrol/drop a project in the machine-global registry (the opt-in enable signal and anti-laundering wall), manage the daemon lifecycle (start, stop, drain, status, install, upgrade) version-pinned to the verified bundle copy, and inspect the daemon's per-project interaction-audit log (read-only)
tools
The tiny build-consumption client for the marshalld build server — submit a build job, bounded long-poll for its result, ping the daemon identity, and preflight registry-plus-liveness in one call; consumption only, never provisioning or enrolment