---
name: analyze-project-architecture
description: LLM-based architectural analysis that transforms raw project data into meaningful structure
user-invocable: false
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
---

# Analyze Project Architecture Skill

## Enforcement Rules

### Script Execution
1. Run scripts EXACTLY as documented - no improvisation
2. All scripts use: `python3 .plan/execute-script.py {notation} ...`

### Workflow Behavior
1. Complete all steps in sequence
2. After each module enrichment → proceed to next module
3. Only stop when all modules are enriched

### Prohibited Actions
- Skipping modules without enrichment
- Leaving `responsibility` or `key_packages` empty
- Omitting `--reasoning` parameters (traceability is required)
- Summarizing what you're about to do instead of doing it

---

## What This Skill Provides

**Discovery**: Run extension API to collect raw module data

**Enrichment**: LLM analyzes documentation and code to add semantic understanding

**Persistence**: Store enriched data for solution-outline consumption

---

## Scripts

| Script | Notation | Purpose |
|--------|----------|---------|
| architecture | `plan-marshall:analyze-project-architecture:architecture` | Main CLI for all operations |

### Command Groups

| Group | API | Purpose |
|-------|-----|---------|
| `discover`, `init` | [manage-api](standards/manage-api.md) | Setup commands |
| `derived`, `derived-module` | [manage-api](standards/manage-api.md) | Read raw discovered data |
| `enrich *` | [manage-api](standards/manage-api.md) | Write enrichment data |
| `info`, `module`, `modules`, `commands`, `resolve` | [client-api](standards/client-api.md) | Consumer queries |

---

## Step 1: Discover Modules

Run extension API discovery:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture discover --force
```

**Output**: `.plan/project-architecture/derived-data.json`

Always overwrites existing data to ensure fresh discovery.

---

## Step 1.5: Review Build Profiles (Maven Only)

**Condition**: Only if any module has `build_systems` containing `maven`.

Check derived-data.json for NO-MATCH-FOUND profiles in `modules.*.metadata.profiles`.

**If Maven modules exist AND unmatched profiles found**:

Load skill `pm-dev-java:manage-maven-profiles` and follow its workflow to:
1. Ask user about each unmatched profile (Ignore/Skip/Map)
2. Apply configuration via `run_config` commands
3. Re-run discovery to apply changes

**If no Maven modules OR no unmatched profiles** → Skip to Step 2.

---

## Step 2: Initialize Enrichment File

Check if `llm-enriched.json` already exists:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture init --check
```

**If file exists**, ask user:

```yaml
AskUserQuestion:
  question: "llm-enriched.json already exists. What do you want to do?"
  header: "Enrichment"
  options:
    - label: "Skip"
      description: "Keep existing enrichments, continue to next step"
    - label: "Replace"
      description: "Discard existing enrichments, start fresh"
  multiSelect: false
```

**Based on user choice**:

| Choice | Command |
|--------|---------|
| Skip | Proceed to Step 3 |
| Replace | `architecture init --force` |

**If file does not exist**:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture init
```

This creates empty enrichment structure for each module found in derived-data.json.

---

## Step 3: Load Discovered Data

Load the raw discovered data in TOON format:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture derived
```

**Output (TOON)**:
```toon
project:
  name: {project-name}
  root: {project-root}

modules[N]{name,path,build_systems,readme,description}:
module-a,module-a,maven,module-a/README.adoc,Description from pom
module-b,module-b,maven,,
module-c,module-c,maven+npm,module-c/README.md,
```

The output shows raw extension API discovery results:
- Module names and paths
- Build systems (joined with `+` for hybrid)
- README paths (if detected)
- Descriptions (from build files, if available)

Read referenced READMEs for modules that have them:
```bash
Read {readme path from derived output}
```

---

## Step 4: Enrich Project Description

Based on the README and module descriptions, write a 1-2 sentence project description.

**Always provide reasoning** to document the source:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich project --description "{extracted project description}" \
  --reasoning "{source: README.md introduction | inferred from module names | pom.xml description}"
```

**Reasoning examples**:
- "From README.md first paragraph"
- "Inferred from module structure and pom.xml descriptions"
- "Aggregated from child module responsibilities"

---

## Step 5: Get Module List

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture modules
```

**Output (TOON)**:
```toon
modules[N]:
  - module-a
  - module-b
  - ...
```

---

## Step 6: Enrich Each Module

**For each module in the list**, execute Steps 6a-6e:

### Step 6a: Read Module Documentation

Get raw discovered data for the module:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture derived-module --name {module-name}
```

**Output (TOON)**:
```toon
module:
  name: {module-name}
  path: {module-path}
  build_systems: maven

paths:
  readme: {module}/README.adoc
  sources[N]:
    - src/main/java
  tests[N]:
    - src/test/java

metadata:
  description: {from build file if available}
  packaging: jar

packages[N]{name,path,package_info}:
com.example.core,src/main/java/com/example/core,src/main/java/com/example/core/package-info.java
com.example.util,src/main/java/com/example/util,

dependencies[N]:
  - groupId:artifactId:scope
```

Read the referenced documentation:
```bash
Read {paths.readme}
Read {package_info path}  # for packages with package_info
```

If no documentation available, sample 2-3 source files from packages.

### Step 6b: Determine Module Purpose

Analyze to determine `purpose` value:

| Signal | Purpose Value |
|--------|---------------|
| packaging=jar, no runtime deps | `library` |
| Quarkus extension annotations | `extension` |
| Build-time processor, deployment | `deployment` |
| Main class, application entry | `runtime` |
| packaging=pom at root | `parent` |
| Only test files | `integration-tests` |
| JMH benchmarks | `benchmark` |

### Step 6c: Write Module Responsibility

Write 1-3 sentences describing what the module does.

**Good examples**:
- "Validates JWT tokens from multiple identity providers using a pipeline approach"
- "Provides Quarkus CDI integration for the core validation library"
- "Coordinates build configuration for all child modules"

**Bad examples** (avoid):
- "Core module" (too vague)
- "Main package for processing" (says nothing)

**Always provide reasoning** for traceability:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich module --name {module-name} \
  --responsibility "{1-3 sentence description}" \
  --responsibility-reasoning "{source: README overview | package-info.java | inferred from class names}" \
  --purpose {purpose-value} \
  --purpose-reasoning "{signal: packaging=jar with no main class | Quarkus extension annotations}"
```

**Reasoning examples**:
- Responsibility: "From module README.adoc overview section"
- Responsibility: "Inferred from package-info.java and primary class names"
- Purpose: "packaging=jar, no runtime dependencies, no main class"
- Purpose: "Contains @BuildStep annotations indicating Quarkus deployment module"

### Step 6d: Identify Key Packages

Select 2-4 architecturally significant packages per module.

For each key package, write 1-2 sentence description:

**Good examples**:
- "Provides the token validation pipeline with pluggable validators"
- "Contains domain models for tokens, claims, and validation results"

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich package --module {module-name} \
  --package {full.package.name} \
  --description "{1-2 sentence description}"
```

Repeat for each key package (2-4 packages).

### Step 6d-2: Identify Key Dependencies

From the derived-module output (Step 6a), analyze the `dependencies` list to identify architecturally significant dependencies.

**Selection criteria** - Include dependencies that:
- Define the module's core technology (frameworks, runtime libraries)
- Provide essential APIs the module builds upon
- Define the runtime contract (provided-scope dependencies like `quarkus-core`, `servlet-api`)
- Are unique to this module's purpose (not ubiquitous across all modules)

**Exclude from key dependencies**:
- Ubiquitous utilities (commons-lang, guava, slf4j) unless central to module purpose
- Pure code-generation tools (lombok) that don't define architecture
- Standard test frameworks (junit, mockito) - implied by testing profile
- Transitive dependencies not directly used

**Include despite scope**:
- Provided-scope framework APIs (these define the runtime contract)
- Test-scope if architecturally distinctive (testcontainers, wiremock, arquillian)
- Compile-scope annotation libraries that define contracts (jspecify, checker-qual)

**For multi-module projects**, also identify `internal_dependencies`:
- Other modules in this project that this module depends on
- Look for dependencies with same groupId as the project

**Good examples**:
- `io.quarkus:quarkus-core` (provided) - Defines runtime framework contract
- `jakarta.servlet-api` (provided) - Defines servlet container contract
- `org.eclipse.microprofile.jwt:microprofile-jwt-auth-api` - Core API this module implements
- `org.jspecify:jspecify` - Defines null-safety contract
- `org.testcontainers:testcontainers` (test) - Architecturally distinctive testing approach

**Bad examples** (exclude):
- `org.junit.jupiter:junit-jupiter-api` - Standard test framework, implied by profile
- `org.projectlombok:lombok` - Code generation tool, doesn't define architecture
- `org.slf4j:slf4j-api` - Ubiquitous logging facade
- `org.apache.commons:commons-lang3` - Generic utility, not distinctive

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich dependencies --module {module-name} \
  --key "{comma-separated list of groupId:artifactId}" \
  --internal "{comma-separated list of internal module names}" \
  --reasoning "{why these dependencies are architecturally significant}"
```

**Example**:
```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich dependencies --module oauth-sheriff-core \
  --key "io.quarkus:quarkus-core,org.eclipse.microprofile.jwt:microprofile-jwt-auth-api" \
  --reasoning "Quarkus runtime and MicroProfile JWT API define the module's integration contract"
```

For single-module projects or leaf modules with no internal dependencies, omit `--internal`.

### Step 6e: Determine Skills by Profile

Assign skills organized by execution profile (implementation, unit-testing, integration-testing, benchmark-testing, documentation).

**Step 6e.1: List Available Domains**

Get all configured skill domains:

```bash
python3 .plan/execute-script.py plan-marshall:manage-plan-marshall-config:plan-marshall-config \
  skill-domains list
```

**Output (TOON)**:
```toon
status: success
domains:
  - system
  - java
  - javascript
  - plan-marshall-plugin-dev
count: 4
```

**Step 6e.2: Determine Applicable Domain**

Based on the module analysis from Steps 6a-6d, determine which domain applies.

**Signals to consider** (from derived-module output and documentation):
- Source file extensions (`.java`, `.kt`, `.js`, `.ts`)
- Dependencies (groupId/artifactId patterns, npm packages)
- Framework annotations in code
- Build file configurations
- Module description and purpose

**Examples of domain applicability**:

| Signal | Domain |
|--------|--------|
| Java sources, javax/jakarta imports | `java` |
| Kotlin sources, kotlin-stdlib | `java` (or future `kotlin`) |
| JavaScript/TypeScript sources | `javascript` |
| plugin.json, marketplace structure | `plan-marshall-plugin-dev` |
| Quarkus dependencies | `java` + CUI-specific if CUI deps present |
| `doc/` or `docs/` with `.adoc` files | `documentation` (as additional profile) |

**Step 6e.3: Get Skills by Profile**

For the applicable domain, get the pre-assembled skills by profile:

```bash
python3 .plan/execute-script.py plan-marshall:manage-plan-marshall-config:plan-marshall-config \
  get-skills-by-profile --domain {domain-key}
```

**Output (TOON)**:
```toon
status: success
domain: java
skills_by_profile:
  implementation:
    - pm-dev-java:java-core
    - pm-dev-java:java-null-safety
    - pm-dev-java:java-lombok
    - pm-dev-java:java-cdi
    - pm-dev-java:java-maintenance
  unit-testing:
    - pm-dev-java:java-core
    - pm-dev-java:java-null-safety
    - pm-dev-java:java-lombok
    - pm-dev-java:junit-core
    - pm-dev-java:junit-integration
  integration-testing:
    - pm-dev-java:java-core
    - pm-dev-java:java-null-safety
    - pm-dev-java:java-lombok
    - pm-dev-java:junit-core
    - pm-dev-java:junit-integration
  benchmark-testing:
    - pm-dev-java:java-core
    - pm-dev-java:java-null-safety
    - pm-dev-java:java-lombok
    - pm-dev-java:junit-core
    - pm-dev-java:junit-integration
```

**Step 6e.4: Filter Skills Based on Module Signals**

Optionally filter the skills based on module signals:

| Module Signal | Action |
|---------------|--------|
| No CDI annotations | Remove `java-cdi` from implementation |
| No Lombok annotations | Remove `java-lombok` from all profiles |
| No integration tests (*IT.java) | Remove integration-testing profile entirely |
| No benchmarks (*Benchmark.java) | Remove benchmark-testing profile entirely |

**Step 6e.4b: Add Documentation Profile (Cross-Domain)**

If module has AsciiDoc documentation, add `documentation` profile from `documentation` domain:

**Detection**: Check if module has `doc/` or `docs/` directory with `.adoc` files.

```bash
# Check for AsciiDoc docs in module
ls {module-path}/doc/*.adoc 2>/dev/null || ls {module-path}/docs/*.adoc 2>/dev/null
```

**If `.adoc` files found**:

1. Get documentation skills:
```bash
python3 .plan/execute-script.py plan-marshall:manage-plan-marshall-config:plan-marshall-config \
  get-skills-by-profile --domain documentation
```

2. Add `documentation` profile to the module's `skills_by_profile`:
```json
{
  "implementation": [...],
  "module_testing": [...],
  "documentation": ["pm-documents:ref-documentation", "pm-documents:manage-adr", ...]
}
```

**Key principle**: Documentation is a separate task type (like testing), not a variant of implementation. A module can have both `implementation` AND `documentation` profiles.

**Step 6e.5: Apply Skills by Profile**

**Include reasoning** about filtering decisions:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich skills-by-profile --module {module-name} \
  --skills-json '{"implementation": ["pm-dev-java:java-core", "pm-dev-java:java-cdi"], "module_testing": ["pm-dev-java:java-core", "pm-dev-java:junit-core"]}' \
  --reasoning "{filtering applied: removed java-lombok (no @Data annotations found), kept java-cdi (CDI beans present)}"
```

**Reasoning examples**:
- "Base java domain, no filtering applied"
- "Removed java-cdi (no CDI annotations), removed integration_testing (no *IT.java files)"
- "Added cui-testing-http based on MockWebServer test dependency"
- "Added documentation profile (module has doc/*.adoc files)"

The `skills_by_profile` structure flows to:
1. **solution-outline**: Copies to deliverable as `skills-implementation`, `skills-testing`, etc.
2. **task-plan**: Uses pre-resolved skills when creating tasks (no runtime lookup)

---

## Step 7: Verify Enrichment

After all modules are enriched, verify completeness:

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture info
```

Check that:
- [ ] Every module has non-empty `responsibility`
- [ ] Every module has valid `purpose`
- [ ] Every module has 2-4 `key_packages` with descriptions
- [ ] Every module has `key_dependencies` identified (unless module has no compile-scope deps)
- [ ] Every module has `skills_by_profile` with at least `implementation` and `unit-testing` profiles

If any module is incomplete → return to Step 6 for that module.

---

## Step 8: Output Summary

Display completion summary:

```
Architecture analysis complete.

Project: {project name}
Modules enriched: {count}

Files created:
  - .plan/project-architecture/derived-data.json
  - .plan/project-architecture/llm-enriched.json

Next steps:
  - Solution outline will use this data for placement decisions
  - Run 'architecture.py module --name X' to query module details
```

---

## Error Handling

### Extension API Not Available

```
Error: Extension API not found.

Resolution:
1. Verify domain bundles installed (pm-dev-java, pm-dev-frontend)
2. Run /marshall-steward to configure project
3. Re-run this skill
```

### No Modules Discovered

```
Error: No modules found in project.

Resolution:
1. Verify project has build files (pom.xml, package.json, build.gradle)
2. Check that domain bundle matches project type
3. Re-run discovery
```

### Documentation Not Found

If module has no README or package-info:
1. Analyze source code directly
2. Check parent module for context
3. Note in responsibility: "Inferred from source analysis"

---

## Deferred Loading

For detailed specifications, load on demand:

| Reference | When to Load |
|-----------|--------------|
| [manage-api.md](standards/manage-api.md) | Manage commands (setup, read raw, enrich) |
| [client-api.md](standards/client-api.md) | Client commands (merged data for consumers) |
| [architecture-persistence.md](standards/architecture-persistence.md) | Field schemas and formats |
| [architecture-workflow.md](standards/architecture-workflow.md) | Workflow phase details |
| [documentation-sources.md](standards/documentation-sources.md) | Reading strategy details |
| `pm-dev-java:manage-maven-profiles` | Maven profile classification (Step 1.5) |

---

## Integration

This skill is invoked by:
- **marshall-steward wizard** Step 6b (after discovery)
- **Direct activation** when regenerating project structure

Output is consumed by:
- **solution-outline** Step 0 (module placement)
- **task-plan** (command resolution)

---

## Post-Implementation Enrichment

During verification phase or after implementation, capture learnings:

### Add Implementation Tip

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich tip --module {module-name} --tip "Use @ApplicationScoped for singleton services"
```

### Add Learned Insight

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich insight --module {module-name} --insight "Heavy validation happens in boundary layer"
```

### Add Best Practice

```bash
python3 .plan/execute-script.py plan-marshall:analyze-project-architecture:architecture \
  enrich best-practice --module {module-name} --practice "Always validate tokens before extracting claims"
```

These accumulate over time and are included in module output for future reference.
