feat(apm): redesign primitives-architect with design discipline + runtime-affordance layering#939
feat(apm): redesign primitives-architect with design discipline + runtime-affordance layering#939danielmeppiel wants to merge 3 commits intomainfrom
Conversation
…time-affordance layering Replaces the style/lint persona with a durable architectural mental model plus a new apm-primitives-architecture skill that drives a 7-step design discipline: intent -> component diagram -> thread/sequence diagram -> SoC review -> compliance check -> handoff packet. Key shifts: - Persona disambiguates persona-scoping (text loaded into a thread to bias inference) from subagent (runtime-spawned child thread with fresh context window). Conflating these is the central error in agentic design. - Architecture patterns catalog (P1-P6) with selection heuristic: >=3 independent lenses with no shared state -> fan-out + parent synthesizer. - Runtime-affordances split into common substrate + per-harness adapters (copilot, claude-code, cursor, opencode, codex). Adding a harness = drop one file in per-harness/, no other edits (open-closed). - Worked example re-architects apm-review-panel from single-loop to fan-out + synthesizer to demonstrate the discipline. Files for LLMs to execute, not humans to read; assets load on demand to respect SKILL.md token budget. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Redesigns the apm-primitives-architect primitive from a style/lint-focused auditor into a durable architecture persona, and introduces a new apm-primitives-architecture skill that drives a structured, diagram-first design discipline with runtime-affordance layering across harnesses.
Changes:
- Rewrites
.apm/agents/apm-primitives-architect.agent.mdto focus on durable runtime mental models, threading semantics, and diagram-first design discipline. - Adds
.apm/skills/apm-primitives-architecture/with a 7-step design process and modular assets (patterns catalog, Mermaid conventions, worked example). - Introduces a runtime-affordances substrate (
common.md) plus portability rules and per-harness adapters (Copilot, Claude Code, Cursor, OpenCode, Codex).
Show a summary per file
| File | Description |
|---|---|
| .apm/agents/apm-primitives-architect.agent.md | Replaces the previous architect guidance with durable runtime + threading design discipline and artifact-first outputs. |
| .apm/skills/apm-primitives-architecture/SKILL.md | New entrypoint skill encoding the stepwise architecture process and lazy-loading of supporting assets. |
| .apm/skills/apm-primitives-architecture/assets/architecture-patterns.md | Adds a topology catalog (P1–P6) to drive consistent orchestration shape selection. |
| .apm/skills/apm-primitives-architecture/assets/mermaid-conventions.md | Defines diagram conventions + GitHub Mermaid rendering gotchas for reliable artifacts. |
| .apm/skills/apm-primitives-architecture/assets/worked-example-review-panel.md | Provides a canonical before/after example for refactoring multi-lens panels into fan-out + synthesizer. |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/common.md | Defines the harness-agnostic substrate concepts used for portability-first designs. |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/portability-rules.md | Adds rules for when/how to justify per-harness reach beyond the substrate. |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/copilot.md | Documents Copilot mapping for substrate concepts (with TODOs for missing public docs). |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/claude-code.md | Documents Claude Code mapping for substrate concepts with doc citations. |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/cursor.md | Documents Cursor mapping for substrate concepts (currently misaligned with repo integration paths). |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/opencode.md | Documents OpenCode mapping for substrate concepts (includes citations to missing snapshot files). |
| .apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/codex.md | Documents Codex mapping for substrate concepts (currently misaligned with repo integration paths/defaults). |
Copilot's findings
Comments suppressed due to low confidence (1)
.apm/skills/apm-primitives-architecture/assets/worked-example-review-panel.md:95
- Same issue for the sequenceDiagram block: it is not fenced as Mermaid, so it will render as plain text on GitHub. Update the fence to a Mermaid code block so the diagram is actually viewable.
sequenceDiagram
participant Orchestrator
participant LensA as Architect
participant LensB as LoggingUX
participant LensC as DevXUX
participant LensD as Security
participant LensE as Growth
participant Auth as Auth (cond)
participant Arbiter
Orchestrator->>LensA: spawn(load Architect persona, scope=PR)
Orchestrator->>LensB: spawn(load LoggingUX persona, scope=PR)
Orchestrator->>LensC: spawn(load DevXUX persona, scope=PR)
Orchestrator->>LensD: spawn(load Security persona, scope=PR)
Orchestrator->>LensE: spawn(load Growth persona, scope=PR)
alt conditional fires
Orchestrator->>Auth: spawn(load Auth persona, scope=PR)
Auth-->>Orchestrator: findings
end
LensA-->>Orchestrator: findings
LensB-->>Orchestrator: findings
LensC-->>Orchestrator: findings
LensD-->>Orchestrator: findings
LensE-->>Orchestrator: findings
Note over Orchestrator: completeness gate
Orchestrator->>Arbiter: spawn(load Arbiter persona, plus all findings as input)
Arbiter-->>Orchestrator: synthesized verdict
Note over Orchestrator: single-writer interlock on output sink
- Files reviewed: 12/12 changed files
- Comments generated: 11
| ## 1. PERSONA SCOPING FILE | ||
|
|
||
| In Cursor: Project Rule with frontmatter, or AGENTS.md (legacy). | ||
| - File extension: .mdc (recommended) or .md (legacy AGENTS.md) | ||
| - Folder: .cursor/rules/ (project), AGENTS.md in root (legacy) | ||
| - Frontmatter fields: description, globs, alwaysApply | ||
| - Activation: Rules are loaded when alwaysApply=true (always) or | ||
| when Agent determines relevance based on description. AGENTS.md | ||
| is automatically loaded as project-level instructions. | ||
| - Notes: alwaysApply=false means Cursor Agent decides relevance. | ||
| Nested AGENTS.md files are supported in subdirectories. | ||
| - Source: https://docs.cursor.com/context/rules |
There was a problem hiding this comment.
This section says Cursor persona scoping is done via rules (.cursor/rules/*.mdc) or AGENTS.md, but APM's Cursor target mapping treats persona scoping as an agent primitive deployed to .cursor/agents/*.md (separate from rules/instructions). Align this adapter to the repo's actual integration paths so designers don't conflate rules vs agents.
| - Closest equivalent: .agents/skills/ directory containing SKILL.md + assets/ | ||
| - Standard body fields: name, description, steps with asset references | ||
| - Assets folder: .agents/skills/<skill-name>/assets/ | ||
| - Activation: Agents select skills matching task description | ||
| - Notes: Cursor implements agentskills.io SKILL.md container and discovery; | ||
| assets load on demand as agents execute steps. |
There was a problem hiding this comment.
The skill deployment path here doesn't match APM's Cursor integration. In this repo, Cursor skills deploy under .cursor/skills/<name>/SKILL.md (not .agents/skills/). Using the wrong path in the adapter will cause incorrect portability decisions and incorrect emitted files.
| - Closest equivalent: .agents/skills/ directory containing SKILL.md + assets/ | |
| - Standard body fields: name, description, steps with asset references | |
| - Assets folder: .agents/skills/<skill-name>/assets/ | |
| - Activation: Agents select skills matching task description | |
| - Notes: Cursor implements agentskills.io SKILL.md container and discovery; | |
| assets load on demand as agents execute steps. | |
| - Closest equivalent: .cursor/skills/<skill-name>/ directory containing SKILL.md + assets/ | |
| - Standard body fields: name, description, steps with asset references | |
| - Assets folder: .cursor/skills/<skill-name>/assets/ | |
| - Activation: Agents select skills matching task description | |
| - Notes: Cursor discovers SKILL.md-based skill containers under | |
| .cursor/skills/; assets load on demand as agents execute steps. |
| In Cursor: Hooks (.cursor/hooks/*.json) for event-driven actions. | ||
| - Mechanism: JSON hook configuration in .cursor/hooks/ directory. | ||
| Each hook file specifies trigger event and associated action. | ||
| - Trigger types: TODO: official docs needed (repository events, | ||
| schedule, user invocation presumed). | ||
| - Scope: Repo-local; not yet integrated with global ~/.cursor/ scope. | ||
| - Notes: Hook semantics not fully documented in official API. |
There was a problem hiding this comment.
Cursor hooks are integrated by APM into a merged .cursor/hooks.json (plus per-package scripts under .cursor/hooks/<pkg>/), not individual .cursor/hooks/*.json files. Documenting the wrong hook shape will lead to non-functional orchestrator designs.
| In Cursor: Hooks (.cursor/hooks/*.json) for event-driven actions. | |
| - Mechanism: JSON hook configuration in .cursor/hooks/ directory. | |
| Each hook file specifies trigger event and associated action. | |
| - Trigger types: TODO: official docs needed (repository events, | |
| schedule, user invocation presumed). | |
| - Scope: Repo-local; not yet integrated with global ~/.cursor/ scope. | |
| - Notes: Hook semantics not fully documented in official API. | |
| In Cursor via APM: merged hook config at .cursor/hooks.json, with | |
| package-owned scripts under .cursor/hooks/<pkg>/ for event-driven | |
| actions. | |
| - Mechanism: APM merges hook declarations into a single | |
| .cursor/hooks.json file. Per-package hook scripts and helper files | |
| live under .cursor/hooks/<pkg>/. | |
| - Trigger types: TODO: confirm exact Cursor hook event names from | |
| official docs before depending on specific triggers. | |
| - Scope: Repo-local project configuration emitted by APM. | |
| - Notes: Do not model hooks as individual .cursor/hooks/*.json files; | |
| that shape does not match APM's Cursor integration contract. |
| Official docs cited: | ||
| - https://github.com/anomalyco/opencode | ||
| - Playwright MCP snapshot: .playwright-mcp/opencode-agents.md | ||
| - Playwright MCP snapshot: .playwright-mcp/opencode-commands.md | ||
| - Playwright MCP snapshot: .playwright-mcp/opencode-config.md | ||
|
|
There was a problem hiding this comment.
This adapter cites Playwright snapshot files under .playwright-mcp/ (e.g., .playwright-mcp/opencode-agents.md), but those snapshot files are not present in the repository. Either add the referenced snapshot artifacts (if intended) or remove/replace these citations with sources that exist (official docs, or the relevant APM integration code).
| every concept here has an equivalent in every supported harness, | ||
| even if the file name, folder location, or trigger field differs. | ||
|
|
||
| The architect persona designs against THIS file. Per-harness | ||
| adapters in `per-harness/` map the substrate to specific syntax; | ||
| load them only when a primitive must reach beyond the substrate. |
There was a problem hiding this comment.
This section says every concept in the common substrate has an equivalent in every supported harness, but the per-harness adapters in this PR describe some targets as lacking PERSONA SCOPING FILE / CHILD-THREAD SPAWN / TRIGGER ORCHESTRATOR (e.g., Codex). That contradiction makes the substrate ambiguous for the skill's step 7 portability check; either soften the claim (e.g., allow 'native OR external/orchestrated equivalent') or align the adapters to map each substrate concept to a concrete mechanism/workaround per target.
| every concept here has an equivalent in every supported harness, | |
| even if the file name, folder location, or trigger field differs. | |
| The architect persona designs against THIS file. Per-harness | |
| adapters in `per-harness/` map the substrate to specific syntax; | |
| load them only when a primitive must reach beyond the substrate. | |
| every concept here must map in every supported harness to either a | |
| native mechanism or a documented external/orchestrated equivalent, | |
| even if the file name, folder location, trigger field, or execution | |
| path differs. | |
| The architect persona designs against THIS file. Per-harness | |
| adapters in `per-harness/` must map each substrate concept to the | |
| concrete native mechanism or workaround for that target; load them | |
| only when a primitive must reach beyond the substrate. |
| - GitHub Models Integration: Codex CLI auto-configures free access to | ||
| GitHub Models (gpt-4o-mini) via GITHUB_TOKEN; no OpenAI key required. |
There was a problem hiding this comment.
The Codex runtime details here don't match the repo's own Codex setup defaults. scripts/runtime/setup-codex.sh configures Codex for GitHub Models with model = "openai/gpt-4o", but this adapter claims a specific default of gpt-4o-mini. Please either update to the repo's actual default model, or avoid naming a specific model unless it's sourced from current APM configuration/docs.
| - GitHub Models Integration: Codex CLI auto-configures free access to | |
| GitHub Models (gpt-4o-mini) via GITHUB_TOKEN; no OpenAI key required. | |
| - GitHub Models Integration: Codex CLI can be configured to use | |
| GitHub Models via GITHUB_TOKEN; no OpenAI key required. |
| Each diagram block in the handoff packet sits between fenced | ||
| ``` ```mermaid ``` ``` markers. The handoff packet is markdown; |
There was a problem hiding this comment.
This paragraph about Mermaid fencing is likely to render incorrectly (it contains nested triple-backtick sequences like ``` ```mermaid ``` ```). Consider rephrasing it to literally say "use a fenced code block with language 'mermaid'" (or show a single, valid example) so readers/LLMs don't copy a malformed fence.
| Each diagram block in the handoff packet sits between fenced | |
| ``` ```mermaid ``` ``` markers. The handoff packet is markdown; | |
| Each diagram block in the handoff packet must use a fenced code | |
| block with language `mermaid`. The handoff packet is markdown; |
| A markdown file (with frontmatter) loaded as text into a thread at | ||
| the start of execution to bias inference toward a specific lens or | ||
| role. It does NOT execute. It does NOT spawn anything. It is a | ||
| prompt-shaped knowledge artifact. | ||
|
|
||
| Substrate fields (every harness offers these or equivalents): | ||
| - a unique `name` | ||
| - a `description` (plain text the harness shows to the user / model) | ||
| - the body: instructions, principles, anti-patterns |
There was a problem hiding this comment.
The substrate definition for PERSONA SCOPING FILE assumes a Markdown + frontmatter format, but APM's own Codex integration emits agents as .toml (see targets.py). If the substrate is meant to be truly harness-agnostic, consider defining this concept as a 'structured persona config file' rather than specifically Markdown, and let per-harness adapters specify the concrete format.
| A markdown file (with frontmatter) loaded as text into a thread at | |
| the start of execution to bias inference toward a specific lens or | |
| role. It does NOT execute. It does NOT spawn anything. It is a | |
| prompt-shaped knowledge artifact. | |
| Substrate fields (every harness offers these or equivalents): | |
| - a unique `name` | |
| - a `description` (plain text the harness shows to the user / model) | |
| - the body: instructions, principles, anti-patterns | |
| A structured persona config file loaded as text into a thread at | |
| the start of execution to bias inference toward a specific lens or | |
| role. It does NOT execute. It does NOT spawn anything. It is a | |
| prompt-shaped knowledge artifact. The concrete file format is | |
| adapter-defined per harness, for example Markdown plus frontmatter | |
| or TOML. | |
| Substrate fields (every harness offers these or equivalents): | |
| - a unique `name` | |
| - a `description` (plain text the harness shows to the user / model) | |
| - persona content: instructions, principles, anti-patterns |
| ``` | ||
| flowchart LR | ||
| O{Panel orchestrator} | ||
| P((Architect)) | ||
| L((Logging UX)) | ||
| U((DevX UX)) | ||
| Sec((Security)) | ||
| G((Growth)) | ||
| Auth((Auth)) | ||
| A((Arbiter)) | ||
| O --> P | ||
| O --> L | ||
| O --> U | ||
| O --> Sec | ||
| O --> G | ||
| O -. conditional .-> Auth | ||
| O --> A | ||
| classDef new stroke-dasharray: 5 5; | ||
| class A new; | ||
| ``` |
There was a problem hiding this comment.
The flowchart and sequenceDiagram blocks are fenced as plain code blocks, so GitHub will not render them as Mermaid. Since this file is meant to be executed/used as the canonical reference shape, the diagram fences should be tagged with mermaid (and aligned with assets/mermaid-conventions.md).
This issue also appears on line 67 of the same file.
| ## Compliance summary | ||
|
|
||
| | Check | Old design | New design | | ||
| |---|---|---| | ||
| | Reduced Scope (per-lens fresh window) | FAIL | PASS | | ||
| | Orchestrated Composition (independent contracts) | FAIL | PASS | | ||
| | Single-writer interlock on output | PASS | PASS | | ||
| | God module avoidance | FAIL (one thread = many lenses) | PASS | | ||
| | Fan-out where applicable | FAIL | PASS | | ||
|
|
There was a problem hiding this comment.
The markdown table in the compliance summary uses || at the start of each row, which renders as an extra empty column in GitHub-flavored Markdown. Use single leading pipes (|) for a 3-column table so it renders correctly.
… layer) Extends the architect with a 4th durable truth (COMPOSITION IS FIRST-CLASS) and the PRIMITIVE-vs-MODULE disambiguation. Adds a new step 3.5 to the design discipline (composition decision: inline / local sibling / external module) plus a dependency-graph diagram. Mirrors the runtime-affordances layering: substrate (composition-substrate.md, 6 named mechanisms: MODULE, DEPENDENCY, DISTRIBUTION BOUNDARY, TRANSITIVE CLOSURE, VERSION PINNING, PORTABILITY MODE) + adapter (module-system-adapters/apm.md, a thin pointer that delegates to the existing apm-usage skill). The architect persona stays ignorant of today's tool: no apm.yml, no CLI commands, no lockfile syntax. APM-specific knowledge lives exclusively in apm-usage and is loaded only at the coder step, only when the design declared external modules. Open-closed: a future module-system tool is added by dropping a sibling adapter, no edits to the substrate or the persona. This is the canonical 'depend, don't duplicate' example: the adapter is 60 lines that point at apm-usage rather than 600 lines re-documenting APM. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Follow-up commit: composition substrate + module-system adapterApplied the lesson the skill itself teaches: separate durable concepts from today's tool. What changed
Mental modelThe architect now reasons about module graphs without knowing what tool resolves them. APM is just today's instance; This is the canonical 'depend, don't duplicate' example -- the adapter is 60 lines that point at apm-usage rather than 600 lines re-documenting APM. |
Names ATTENTION DEGRADATION explicitly (truth #1 corollary) and adds PLAN BEFORE EXECUTION as the 5th durable truth. The architect now treats plan persistence as a first-class runtime affordance rather than a happy accident of the harness it runs in. Substrate (depend, don't duplicate): - runtime-affordances/common.md: 6th named concept PLAN PERSISTENCE with substrate slots PLAN ARTIFACT / TODO-STATUS / CHECKPOINT / FILES; substrate invariant added that long-distance state belongs outside the prompt. - architecture-patterns.md: P8 Plan-first with persisted plan, declared ORTHOGONAL to P1-P7. Combine P8 with whichever topology fits. Selection-heuristic note explains the orthogonality. - SKILL.md: step 6 retitled (handoff packet IS the plan; persist it). Step 7b instructs the executor to RELOAD the plan at re-grounding boundaries. Process diagram updated to show PERSIST at step 6 boundary and RELOAD at step 7b. Adapters (depend, don't duplicate): - per-harness/copilot.md: section 6 documents ~/.copilot/session-state/<id>/{plan.md,checkpoints/,files/} + per-session SQLite todos/todo_deps via the sql tool. - per-harness/claude-code.md: section 6 documents the TodoWrite tool with file-based fallback for cross-session plans. - per-harness/cursor.md, opencode.md, codex.md: section 6 with honest TODO markers + the substrate-portable fallback (plan.md in workspace, re-read at re-grounding points). Recursive proof: this very session relies on plan.md + checkpoints + SQL todos in Copilot CLI -- the architect was silently free-riding on a runtime affordance it failed to acknowledge. That is now codified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Third commit shipped: plan persistence as durable cure for attention decay. Same durable-vs-tool pattern, third instance:
Recursive proof: this PR was written using PR description updated with mermaid diagrams for the 3-layer model and the persist/reload sequence. |
Redesign apm-primitives-architect: design discipline + runtime-affordance layering
TL;DR
The current
apm-primitives-architectis a style/lint auditor. It has no notion of agentic architecture: no runtime mental model, no threading semantics, no orchestration patterns, no separation-of-concerns discipline. The smoking gun isapm-review-panel: 5+ independent lenses crammed into a single sequential loop, when the textbook answer is fan-out + parent synthesizer.This PR splits the persona into:
.apm/agents/apm-primitives-architect.agent.md) carrying only timeless principles: runtime stack mental model, persona-vs-thread disambiguation, classic SW principles applied to prompts, design discipline steps, anti-patterns.apm-primitives-architectureskill that drives a 7-step process and loads modular assets on demand, including a layered runtime-affordances module (common substrate + per-harness adapters for Copilot, Claude Code, Cursor, OpenCode, Codex).These files are for LLMs to execute, not humans to read. Every byte spent biases inference; every load is a token budget hit. The architecture reflects that.
Why
The problem in one diagram
flowchart LR Today[apm-primitives-architect today<br/>style/lint auditor] -->|reviews| Output[Markdown style:<br/>headings, bullets, line length] Today -.->|cannot reason about| Missing[Threading<br/>SoC<br/>Orchestration<br/>Portability<br/>Token budgets] Missing --> Symptom[apm-review-panel:<br/>6 lenses, single loop,<br/>attention degradation] classDef bad fill:#fdd,stroke:#900 classDef gap fill:#ffd,stroke:#990 class Today bad class Missing,Symptom gapConcretely, the architect today cannot answer:
The conflation that causes most bugs
Agentic design conflates two orthogonal things that share the word "subagent":
flowchart TB subgraph Persona ["PERSONA SCOPING (text loaded into a thread)"] P1[".agent.md file"] --> P2["Biases inference of<br/>the thread that loads it"] P2 --> P3["Same context window"] end subgraph Spawn ["CHILD-THREAD SPAWN (runtime concurrency)"] S1["Parent calls spawn(...)"] --> S2["Fresh context window<br/>isolated work"] S2 --> S3["Returns result to parent"] end Persona -. orthogonal .- Spawn classDef persona fill:#dfd,stroke:#090 classDef spawn fill:#ddf,stroke:#009 class P1,P2,P3 persona class S1,S2,S3 spawnA child thread may load a persona file. A persona file does not spawn anything. Designs that confuse these produce single-loop monoliths with persona swaps disguised as parallelism — exactly what
apm-review-paneldoes today.What
Module shape
flowchart TB Persona[".apm/agents/apm-primitives-architect.agent.md<br/>DURABLE PERSONA<br/>runtime mental model, principles, anti-patterns"] subgraph Skill ["apm-primitives-architecture skill"] SkillMD["SKILL.md<br/>7-step design discipline"] Patterns["assets/architecture-patterns.md<br/>P1-P6 + selection heuristic"] Mermaid["assets/mermaid-conventions.md<br/>diagram-per-step + GitHub gotchas"] Worked["assets/worked-example-review-panel.md<br/>single-loop -> fan-out before/after"] subgraph Affordances ["assets/runtime-affordances/"] Common["common.md<br/>5 substrate concepts"] Rules["portability-rules.md<br/>declaration + open-closed"] subgraph PerHarness ["per-harness/"] Copilot["copilot.md"] Claude["claude-code.md"] Cursor["cursor.md"] OpenCode["opencode.md"] Codex["codex.md"] end Common --> PerHarness Rules --> PerHarness end SkillMD -.lazy load.-> Patterns SkillMD -.lazy load.-> Mermaid SkillMD -.lazy load.-> Worked SkillMD -.lazy load.-> Common end Persona -.invokes when designing.-> SkillMDPersona stays small and durable. Skill loads assets on demand. Per-harness adapters fan out under a stable substrate so adding a new harness is one file (open-closed).
The 7-step design discipline
flowchart LR S1[1. Capture<br/>intent] --> S2[2. Component<br/>diagram] S2 --> S3[3. Thread/<br/>sequence dgm] S3 --> S4[4. SoC<br/>review] S4 --> S5[5. Compliance<br/>check] S5 --> S6[6. Handoff<br/>packet] S6 --> S7[7. Caller:<br/>portability + draft + validate] S2 -.loads.-> Patterns[architecture-patterns.md] S3 -.loads.-> Mermaid[mermaid-conventions.md] S5 -.loads.-> Common[runtime-affordances/common.md] S7 -.loads.-> Adapters[per-harness/*.md] classDef arch fill:#ddf,stroke:#009 classDef code fill:#dfd,stroke:#090 class S1,S2,S3,S4,S5,S6 arch class S7 codeArchitect stays in the diagram + substrate world. The "coder" step pulls in harness-specific adapters only when generating actual primitive files. This mirrors
python-architect->python-architecture-> coder.Worked example: re-architecting apm-review-panel
Today (P1 single-loop):
sequenceDiagram participant Caller participant Panel as apm-review-panel<br/>(single thread, persona swaps) Caller->>Panel: review this PR Panel->>Panel: think as Architect Panel->>Panel: think as DevX Panel->>Panel: think as Security Panel->>Panel: think as CLI Panel->>Panel: think as CEO Panel->>Panel: think as Growth Panel->>Caller: synthesized verdict Note over Panel: One context window,<br/>attention degrades by lens 4-5Proposed (P2 fan-out + synthesizer):
sequenceDiagram participant Caller participant CEO as Parent (CEO orchestrator) participant A as spawn(Architect) participant D as spawn(DevX) participant S as spawn(Security) participant C as spawn(CLI) participant G as spawn(Growth) Caller->>CEO: review this PR par fan-out CEO->>A: review (fresh context) CEO->>D: review (fresh context) CEO->>S: review (fresh context) CEO->>C: review (fresh context) CEO->>G: review (fresh context) end A-->>CEO: finding set D-->>CEO: finding set S-->>CEO: finding set C-->>CEO: finding set G-->>CEO: finding set CEO->>CEO: arbitrate, synthesize CEO->>Caller: verdictEach lens gets a fresh context window with its own persona file and only the artifacts it needs. The CEO is the parent thread, holds orchestration, arbitrates conflicts. (This PR documents the pattern; actually rewriting
apm-review-panelis a follow-up that dogfoods the new skill.)How
Files added/changed
.apm/agents/apm-primitives-architect.agent.md.apm/skills/apm-primitives-architecture/SKILL.md.apm/skills/apm-primitives-architecture/assets/architecture-patterns.md.apm/skills/apm-primitives-architecture/assets/mermaid-conventions.mdclassDiagram :::cssClassshorthand limitation).apm/skills/apm-primitives-architecture/assets/worked-example-review-panel.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/common.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/portability-rules.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/copilot.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/claude-code.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/cursor.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/opencode.md.apm/skills/apm-primitives-architecture/assets/runtime-affordances/per-harness/codex.mdHow adapters were authored
5 explore subagents fanned out in parallel (dogfooding the very pattern this PR proposes). Each got:
common.mdsubstrate, pointer to APM'ssrc/apm_cli/adapters/client/<harness>.py+integration/targets.pyfor ground truth, official doc URLs, and instructions to markTODO: official docs neededrather than invent.TODO markers reported by adapter subagents
These are gaps where official docs are not yet public — flagging for follow-up:
Constraints respected
LC_ALL=C grep— clean..apm/is the source of truth;.github/{skills,agents,instructions}/regenerated byapm install --target copilot(not touched here)..cursor/,.claude/, etc. files added — those belong to compiled output.Update: composition layer (second commit
3c6a0df9)The first round redesigned the architect for runtime affordances (how harnesses spawn threads, load skills, etc.). A second durable concern surfaced: APM itself is the composition substrate for primitives -- skills depend on agents, agents depend on instructions, packages bundle them, and the dependency tree is infinite. The architect was blind to this.
Same lesson, applied a second time: separate the durable concept from today's tool.
What was added
assets/composition-substrate.md(NEW, 140 lines) -- 6 named mechanisms:MODULE,DEPENDENCY,DISTRIBUTION BOUNDARY,TRANSITIVE CLOSURE,VERSION PINNING,PORTABILITY MODE. Anti-patterns:DUPLICATED LEAF,HIDDEN EXTERNAL,UNPINNED CRITICAL DEP,TRANSITIVE BLOAT,BOUNDARY VIOLATION,TOOL LEAK. Promotion rule (rule of three / independent cadence / different owner / pinning-worthy).assets/module-system-adapters/apm.md(NEW, 60 lines) -- a thin pointer that delegates to the existingapm-usageskill atpackages/apm-guide/.apm/skills/apm-usage/. Loaded only at coder step 7b, only when the design declared external modules.architecture-patterns.md-- composed-module pattern (depend, don't duplicate).mermaid-conventions.md-- dependency-graph diagram type for step 3.5.The mental model
flowchart TB subgraph Durable["DURABLE LAYER (architect persona + substrate)"] Truths[4 truths<br/>incl. COMPOSITION IS FIRST-CLASS] RtSub[runtime-affordances/common.md<br/>5 named mechanisms] CompSub[composition-substrate.md<br/>6 named mechanisms] end subgraph Adapters["ADAPTER LAYER (today's tools, swap freely)"] Harness[per-harness/copilot.md<br/>per-harness/claude-code.md<br/>per-harness/cursor.md<br/>per-harness/opencode.md<br/>per-harness/codex.md] ModSys[module-system-adapters/apm.md<br/>--> delegates to apm-usage skill] end subgraph Tool["TOOL KNOWLEDGE (lives elsewhere, depend don't duplicate)"] ApmUsage[apm-usage skill<br/>apm.yml schema, CLI, lockfile,<br/>8 dep types, hybrid mode] end Truths --> RtSub Truths --> CompSub RtSub -.coder loads at 7b.-> Harness CompSub -.coder loads at 7b.-> ModSys ModSys -.points at.-> ApmUsage classDef durable fill:#dfd,stroke:#090 classDef adapter fill:#ffd,stroke:#990 classDef tool fill:#ddf,stroke:#009 class Truths,RtSub,CompSub durable class Harness,ModSys adapter class ApmUsage toolThe architect now reasons in
MODULE/DEPENDENCY/DISTRIBUTION BOUNDARY. It never seesapm.yml. APM-specific syntax (CLI, manifest, lockfile, hybrid mode) lives exclusively inapm-usageand is consulted only at the coder step. A future module-system tool ships as a sibling adapter file -- zero edits to substrate or persona.Dogfooding
The adapter is the canonical example of the principle it teaches:
This is
DEPEND, DON'T DUPLICATE(composition-substrate.md anti-patternDUPLICATED LEAF) applied to the architect's own asset bundle. Ifapm-usageevolves, the adapter doesn't drift -- it just points.Updated process diagram
flowchart LR S1[1. Intent] --> S2[2. Decompose] S2 --> S3[3. Runtime fit] S3 --> S35[3.5 Composition<br/>NEW] S35 --> S4[4. SoC + boundaries] S4 --> S5[5. Anti-patterns] S5 --> S6[6. Handoff packet] S6 --> S7a[7a. Critique] S7a --> S7b[7b. Code<br/>loads adapters per box] S7b --> S8[8. Verify] classDef new fill:#ffd,stroke:#990,stroke-width:2px class S35 newFiles in second commit
.apm/agents/apm-primitives-architect.agent.md.apm/skills/apm-primitives-architecture/SKILL.mdassets/composition-substrate.mdassets/module-system-adapters/apm.mdassets/architecture-patterns.mdassets/mermaid-conventions.mdUpdate: plan persistence layer (third commit
1d4be965)The redesign so far gave the architect runtime affordances and composition. A third durable concern surfaced: LLMs forget. Attention decays with distance from the focus point — every long session silently drops earlier decisions, todos, and constraints. The architect was implicitly relying on whatever harness it ran in to provide a plan store, without naming the affordance or telling the executor to use it.
Same pattern, applied a third time: separate the durable cope from today's tool.
What was added
runtime-affordances/common.md: PLAN PERSISTENCE — names the underlying property (ATTENTION DEGRADATION) and the four slots every modern harness offers (PLAN ARTIFACT, TODO/STATUS, optional CHECKPOINT, optional FILES). Specifies write-once-early and reload-at-re-grounding behavior.architecture-patterns.md: Plan-first with persisted plan — declared explicitly ORTHOGONAL to P1-P7. Combine P8 with whichever topology fits. Includes ASCII sketch of the persist/reload loop, the WHEN clause, the INTERLOCK requirement (without reload, persistence is dead weight), and anti-patterns (post-hoc plan, write-once-never-reload, stuffing the whole plan into every spawn).handoff packet (this IS the plan; persist it)— the packet is what gets persisted to the runtime store before step 7b begins. Step 7b instructs the executor to RELOAD before each module / spawn / failure-recovery. Process diagram updated to show PERSIST at the 6→7b boundary and RELOAD inside 7b.copilot.md—~/.copilot/session-state/<id>/plan.md+checkpoints/+files/+ per-session SQLitetodos/todo_depstables via thesqltool (the harness this very PR was written in).claude-code.md— TodoWrite tool with file-based fallback for cross-session plans.cursor.md,opencode.md,codex.md— honestTODO: official docs neededmarkers + the substrate-portable fallback (plan.mdin workspace, re-read at re-grounding points). User can fill in once docs land.The mental model (now three durable layers, three adapter slots)
flowchart TB subgraph DurableConcerns["DURABLE CONCERNS (named in persona truths)"] T1[Truth 1<br/>context finite + attention decay] T2[Truth 2<br/>context explicit] T3[Truth 3<br/>output probabilistic] T4[Truth 4<br/>composition first-class] T5[Truth 5<br/>plan before execution<br/>NEW] end subgraph DurableSubstrate["DURABLE SUBSTRATE (load at design time)"] RA[runtime-affordances/common.md<br/>6 named mechanisms<br/>incl. PLAN PERSISTENCE] CS[composition-substrate.md<br/>6 named mechanisms] AP[architecture-patterns.md<br/>P1..P7 topologies<br/>P8 plan-first ORTHOGONAL] end subgraph Adapters["ADAPTER LAYER (load only at coder step)"] H[per-harness/<br/>copilot|claude|cursor|<br/>opencode|codex .md<br/>each maps all 6 substrate concepts] M[module-system-adapters/apm.md<br/>delegates to apm-usage skill] end T1 --> RA T5 --> RA T5 --> AP T4 --> CS RA -.7b.-> H CS -.7b.-> M classDef durable fill:#dfd,stroke:#090 classDef adapter fill:#ffd,stroke:#990 classDef new fill:#ffe680,stroke:#990,stroke-width:2px class T1,T2,T3,T4,RA,CS,AP durable class T5 new class H,M adapterThe persist/reload cycle (P8)
sequenceDiagram participant A as Architect (steps 1-6) participant P as Plan store<br/>(harness-provided) participant C as Coder thread (step 7b) participant W as Worker subagent (optional) A->>A: design (steps 1-3.5-4-5) A->>P: PERSIST handoff packet (step 6) Note over A,P: Truth #5: plan before execution A--xC: design ends; coder takes over C->>P: RELOAD plan C->>C: draft module 1 C->>P: update todo: module-1 done C->>P: RELOAD plan C->>W: spawn with task = pointer to plan slice Note over C,W: child gets POINTER, not full plan W-->>C: return result C->>P: RELOAD plan (verify state still matches) C->>P: update todos C->>C: validate (step 8) C->>P: final statusFiles changed in third commit
.apm/agents/apm-primitives-architect.agent.mdassets/runtime-affordances/common.mdassets/architecture-patterns.md.apm/skills/apm-primitives-architecture/SKILL.mdassets/runtime-affordances/per-harness/copilot.mdassets/runtime-affordances/per-harness/claude-code.mdassets/runtime-affordances/per-harness/cursor.mdassets/runtime-affordances/per-harness/opencode.mdassets/runtime-affordances/per-harness/codex.mdRecursive proof (dogfood)
This entire PR was built across multiple turns in GitHub Copilot CLI using
~/.copilot/session-state/<id>/plan.md+checkpoints/+ thesqltool'stodos/todo_depstables. The architect was free-riding on PLAN PERSISTENCE without acknowledging it. Truth #5 + substrate concept 6 + P8 codify what was already happening, so the next architect session — in any harness — can do it deliberately.Trade-offs
How to test
.apm/agents/apm-primitives-architect.agent.mdand verify it carries no harness syntax (no mentions of.cursor/,.claude/, etc.). It should read as durable principles..apm/skills/apm-primitives-architecture/SKILL.mdand verify the 7-step process is present and assets are referenced lazily.assets/runtime-affordances/per-harness/contains exactly 5 files.Unit tests:
uv run pytest tests/unit tests/test_console.py -x— doc-only PR, no Python touched. Pre-existing failure ontest_global_mcp_scope.pyconfirmed unrelated (also fails on main).Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com