Capstone Architecture¶
Guide Maps¶
graph LR
family["Python Programming"]
program["Python Meta-Programming"]
guide["Capstone docs"]
section["Docs"]
page["Capstone Architecture"]
proof["Proof route"]
family --> program --> guide --> section --> page
page -.checks against.-> proof
flowchart LR
orient["Read the guide boundary"] --> inspect["Inspect the named files, targets, or artifacts"]
inspect --> run["Run the confirm, demo, selftest, or proof command"]
run --> compare["Compare output with the stated contract"]
compare --> review["Return to the course claim with evidence"]
Use this guide when the capstone technically works but the mechanism boundaries still feel blurred. The point of the architecture is not to look clever. The point is to keep each kind of runtime pressure visible enough that you can say where behavior begins, where it becomes public, and where it should be tested.
The capstone in one sentence¶
This capstone builds a small plugin runtime that uses descriptors for configuration, decorators for action metadata, and a metaclass for class-definition-time registration, while still keeping public inspection separate from action execution.
If that sentence still sounds too compressed, stay in this guide before widening into tests or extension work.
Read the architecture in this order¶
- Read the runtime story by time.
- Read the ownership map by file.
- Read the built-in plugins as pressure tests for the framework.
- Read the common misreads and review questions.
That order keeps cause before implementation detail.
Runtime story by time¶
| Time | What should happen | What must not happen | Main owner |
|---|---|---|---|
| class-definition time | fields and wrapped actions are collected, constructor signatures are generated, and plugins are registered | concrete plugin actions running during class creation | framework.py |
| attribute time | field descriptors validate, coerce, and store per-instance configuration | registry policy leaking into simple attribute access | fields.py |
| call time | action wrappers preserve signatures, invoke plugin behavior, and record visible history | hidden retries, caching, or policy that erases the callable contract | actions.py and plugins.py |
| inspection time | manifest, registry, and signature views are rendered from the public surface | action execution hidden inside "inspection" commands | framework.py and cli.py |
This time model matters because beginners often collapse every advanced Python feature into "runtime magic." The capstone exists to separate those moments cleanly.
Ownership map by file¶
framework.py¶
Owns:
- class creation
- generated constructor signatures
- plugin registration
- manifest export
- public runtime helpers used by the CLI
Should not own:
- descriptor coercion details
- concrete delivery behavior
- wrapper-specific invocation history decisions
fields.py¶
Owns:
- descriptor-backed configuration semantics
- defaults, required values, and coercion
- field metadata exported through manifests
Should not own:
- plugin registration
- action execution behavior
- public command assembly
actions.py¶
Owns:
- action wrapping
- callable metadata preservation
- invocation-history recording
Should not own:
- field validation
- registry policy
- concrete delivery outputs
plugins.py¶
Owns:
- concrete adapters that force the framework to stay honest
- realistic payload shaping
- ordinary runtime code that can be reviewed without framework folklore
Should not own:
- broad framework policy
- registration rules for the whole system
- hidden command-line behavior
cli.py¶
Owns:
- public inspection and invocation commands
- conversion from runtime facts into inspectable CLI output
- durable review routes used by saved bundles
Should not own:
- private runtime tricks unavailable outside the CLI
- field semantics
- wrapper internals that belong in source and tests
Why the architecture is split this way¶
The architecture teaches three durable lessons:
- Advanced Python mechanisms are easiest to learn when each one owns one kind of pressure.
- Public inspection is a different responsibility from execution.
- Concrete plugins are not ornamental examples. They are the evidence that the abstraction still behaves like ordinary application code.
Built-in plugins as pressure tests¶
| Plugin | What pressure it adds | Why the architecture needs it | Best proof surface |
|---|---|---|---|
console |
defaults, choices, and boolean coercion | proves the framework still handles everyday configuration cleanly | make demo, make plugin, tests/test_fields.py |
webhook |
required fields, integer coercion, and structured payload assembly | proves manifests stay observational while real runtime data stays concrete | make plugin, make trace, tests/test_runtime.py |
pager |
multiple actions, nested history, and JSON preview output | proves wrapper history and plugin behavior remain visible together | make trace, tests/test_runtime.py, tests/test_cli.py |
Architecture questions to ask before opening more files¶
- Is this behavior happening at class-definition time, attribute time, call time, or inspection time?
- Which file should own that kind of pressure?
- Does the public surface show the behavior honestly, or only the private implementation?
- Which built-in plugin would reveal the weakness first?
If you cannot answer those questions yet, do not widen into bundle guides or extension work.
Common misreads¶
| Misread | Why it is wrong | Better reading move |
|---|---|---|
| "The metaclass owns the whole framework." | the metaclass owns class-definition-time rules, not every behavior | compare framework.py with fields.py and actions.py |
| "Manifest output proves runtime behavior." | manifests prove public exported structure, not invocation | pair make manifest with make trace |
| "Concrete plugins are just examples." | concrete plugins are the honesty check on framework claims | inspect plugins.py before proposing a framework change |
| "The CLI is the system." | the CLI reports the runtime; it should not secretly become the runtime | compare cli.py with runtime helpers and tests |
Best companion routes¶
- Read DESIGN_BOUNDARIES.md when the confusion is which mechanism should own a new rule.
- Read PACKAGE_GUIDE.md when the confusion is file order, class names, or where to open source first.
- Read COMMAND_GUIDE.md when the confusion is which command proves an architectural claim.
- Read EXTENSION_GUIDE.md when the architecture is clear but change placement is not.
Good stopping point¶
Stop when you can explain:
- why this capstone needs descriptors, decorators, and a metaclass instead of only one of them
- which file owns class-definition-time behavior
- which file owns attribute ownership
- which file owns wrapper behavior
- why public inspection must stay separate from action execution