# Urban Noise Tree Barrier Planning Agent Skill

> A Claude skill from dungnotnull/urban-noise-tree-barrier-planning-agent-skill.

- **Type:** Skill
- **Install:** `agentstack add skill-dungnotnull-urban-noise-tree-barrier-planning-agent-skill-urban-noise-tree-barrier-planning-agent-skill`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [dungnotnull](https://agentstack.voostack.com/s/dungnotnull)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [dungnotnull](https://github.com/dungnotnull)
- **Source:** https://github.com/dungnotnull/urban-noise-tree-barrier-planning-agent-skill

## Install

```sh
agentstack add skill-dungnotnull-urban-noise-tree-barrier-planning-agent-skill-urban-noise-tree-barrier-planning-agent-skill
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# SKILL.md — Skill Registry

`urban-noise-tree-barrier-planning` is built on a **modular skill-registry**
pattern. This document is the canonical reference for how skills are
*registered*, *resolved*, *executed*, and *validated*, including the input/output
JSON Schemas, the tool layer, the lifecycle hooks, and the chain-of-thought
router.

The registry is implemented in `src/urban_noise_barrier/registry.py`
(`SkillRegistry`, `SkillSpec`, `SkillResult`) and orchestrated by
`src/urban_noise_barrier/engine.py` (`Engine`).

---

## 1. Concepts

| Concept | Class | File | Purpose |
|---------|-------|------|---------|
| Skill | `SkillSpec` | `registry.py` | A unit of work: name, stage, handler, schemas, gates, fallback |
| Skill registry | `SkillRegistry` | `registry.py` | Register / resolve / execute / validate skills |
| Tool | `Tool` | `tools/__init__.py` | A deterministic function with JSON Schema I/O |
| Tool registry | `ToolRegistry` | `tools/__init__.py` | Register / invoke tools |
| Hook bus | `HookBus` | `hooks.py` | Lifecycle event publish/subscribe |
| Router | `Router` | `router.py` | CoT intent → ordered skill list |
| Context | `ContextManager` | `context.py` | Token-budgeted artifact store |
| Config | `Config` | `config.py` | Layered type-safe configuration |
| Engine | `Engine` | `engine.py` | Wires everything + runs the pipeline |

---

## 2. Register

A skill is registered as a `SkillSpec` dataclass:

```python
SkillSpec(
    name="sub-core-analysis",                 # unique, matches skills/*.md frontmatter
    description="Noise map, barrier, species, vegetation, co-benefits, scenarios.",
    stage="analysis",                          # intake|evidence|analysis|knowledge|synthesis|gate|routing
    handler=_handler_core_analysis,            # callable(inputs: dict, ctx: Engine) -> dict
    inputs_schema={"type": "object"},          # JSON Schema (optional)
    outputs_schema=CoreAnalysis.json_schema,   # JSON Schema (optional)
    gates=["G1", "G2", "G3", "G4"],            # quality-gate ids this skill satisfies
    fallback=_fallback_core_analysis,          # optional recovery handler
    markdown_path="skills/sub-core-analysis.md",
    retry_max=2,
    tags=["core"],
)
```

`SkillRegistry.register(spec)` validates the spec (non-empty name, callable
handler with `(inputs, ctx)` signature, dict schemas) and refuses duplicates.

Registered skills (default pipeline):

| name | stage | gates | fallback |
|------|-------|-------|----------|
| `sub-router` | routing | — | — (deterministic) |
| `sub-gather-requirements` | intake | U4 | — |
| `sub-evidence-collector` | evidence | U1, U3 | empty degraded bundle (level 3) |
| `sub-core-analysis` | analysis | G1–G4 | — |
| `sub-knowledge-updater` | knowledge | U1 | Weak-coverage empty result |
| `sub-advisor` | synthesis | U2, U6 | — |
| `sub-quality-gate` | gate | U5 | — |

---

## 3. Resolve

Resolution is name-based and stage-aware:

* `registry.get(name)` → `SkillSpec` (raises `SkillError` if missing).
* `registry.by_stage(stage)` → all skills in a stage (registration order).
* `registry.names()` → ordered list of registered skill names.

The **router** (`Router.route`) resolves a request into an ordered skill list
(`Route.skills`). The engine executes `Route.skills` in order, so the router
is the single source of truth for "which skills run".

---

## 4. Execute

`SkillRegistry.execute(name, inputs, ctx)`:

1. **emit** `skill.pre` hook.
2. **validate inputs** against `inputs_schema` (JSON Schema via `jsonschema`
   if installed, else the built-in subset validator).
3. **call** `handler(inputs, ctx)` with retry (up to `retry_max`); recoverable
   `SkillError`s retry, non-recoverable ones propagate.
4. on exhaustion, **fall back** to `spec.fallback` if present.
5. **validate outputs** against `outputs_schema`.
6. **emit** `skill.post` hook.
7. return a `SkillResult` (outputs, degradation_level, used_fallback, retries,
   gates_passed, notes, error).

The `Engine.run(request, analysis_inputs)` wires this together: route →
execute each skill in order → thread outputs through `ContextManager` → run
`sub-quality-gate` → assemble `AnalysisReport`.

---

## 5. Validate

Validation happens at four layers:

1. **Spec validation** — at registration (`SkillSpec.validate_spec`).
2. **Schema validation** — inputs + outputs against JSON Schema. Canonical
   schemas are exported to `assets/schemas/*.json` via
   `scripts/export_schemas.py`.
3. **Gate validation** — `sub-quality-gate` runs U1–U6 + G1–G4 against the
   assembled report and returns `{gates, all_passed, failed, strict}`.
4. **Project validation** — `scripts/validate_project.py` checks the file
   contract, frontmatter, runtime construction, config, and knowledge brain.

### Input/Output JSON Schemas (canonical)

Schemas are defined as class attributes on the models in
`src/urban_noise_barrier/schemas.py` and exported to `assets/schemas/`.

Example — `Requirements` (input/output of `sub-gather-requirements`):

```json
{
  "type": "object",
  "required": ["object"],
  "properties": {
    "object": {"type": "string", "minLength": 1},
    "scope": {"type": "string"},
    "timeframe": {"type": "string"},
    "available_inputs": {"type": "array", "items": {"type": "string"}},
    "target_audience": {"type": "string"},
    "language": {"type": "string", "enum": ["en", "vi"]},
    "analysis_type": {"type": "string"}
  }
}
```

Example — `AdvisorConclusion` (output of `sub-advisor`):

```json
{
  "type": "object",
  "required": ["verdict", "scenarios", "key_risks", "evidence_chain", "remediation", "disclosure"],
  "properties": {
    "verdict": {"type": "string", "enum": ["Effective Barrier Plan",
      "Conditional (species)", "Insufficient Attenuation", "Inconclusive"]},
    "scenarios": {"type": "object"},
    "key_risks": {"type": "array", "minItems": 1},
    "evidence_chain": {"type": "array"},
    "remediation": {"type": "array"},
    "disclosure": {"type": "string", "minLength": 1}
  }
}
```

Full set: `Requirements`, `EvidenceBundle`, `NoiseMap`, `BarrierDesign`,
`SpeciesSelection`, `VegetationAttenuation`, `CoBenefits`, `CoreAnalysis`,
`KnowledgeEvidence`, `AdvisorConclusion`, `AnalysisReport`.

---

## 6. Tools

Tools are the deterministic computation layer invoked by skill handlers.

| Tool name | Input schema (key fields) | Output schema (key fields) | Method |
|-----------|---------------------------|----------------------------|--------|
| `acoustics.noise_map` | speed_kmh, vehicle_flow_per_h, receptors[], barrier? | source_level_db, receptors[] (received_level_db), barrier (insertion_loss_db) | CNOSSOS subset + Maekawa |
| `vegetation.attenuation` | belt_width_m, canopy_density, db_per_30m? | attenuation_db, method | empirical saturation curve |
| `species.select` | site{hardiness_zone, min_height_m, tolerances…}, top_k | candidates[], selected[] (with score+rationale) | weighted tolerance + zone match |
| `airquality.cobenefits` | belt_area_m2, tree_count, lai? | pm_deposition_kg_per_year, co2_sequestration_kg_per_year, cooling_kwh_saved_per_year | i-Tree-style deposition |
| `evidence.collect` | current_data[], authoritative_docs[], … | normalized buckets, degradation_level, limitation_flag | tier assignment + gate |
| `knowledge.query` | keywords[], top_k? | citations[] (tier+relevance), gaps[], coverage | brain parse + score |

Tools are registered via `default_tool_registry()` and invoked through
`ToolRegistry.invoke(name, inputs, ctx)`. Each tool validates its own I/O
against JSON Schema.

---

## 7. Hooks

The `HookBus` (`src/urban_noise_barrier/hooks.py`) emits lifecycle events:

| Event | When |
|-------|------|
| `engine.start` / `engine.end` | engine run boundaries |
| `skill.pre` / `skill.post` / `skill.error` | per-skill lifecycle |
| `tool.pre` / `tool.post` / `tool.error` | per-tool lifecycle |
| `gate.pre` / `gate.post` / `gate.failed` | quality-gate lifecycle |
| `degradation` | degradation level raised |
| `context.compaction` | context manager compacted artifacts |
| `knowledge.append` | brain entry appended |
| `state.sync` | state snapshot requested |

Built-in hooks: `logging_hook` (structured log per event), `metrics_hook`
(per-event counters), `state_sync_hook` (snapshot persistence). Custom hooks
register via `bus.register(event, callback)`.

---

## 8. Router (chain-of-thought)

`Router.route(request, requirements)` returns a `Route`:

```json
{
  "intent": "full_analysis",
  "skills": ["sub-gather-requirements", "sub-evidence-collector",
             "sub-core-analysis", "sub-knowledge-updater",
             "sub-advisor", "sub-quality-gate"],
  "flags": {"require_scenarios": true},
  "reasoning": [{"step": "intent-classification", "observation": "...", "decision": "..."}],
  "degradation_level": 0
}
```

Routing is deterministic and fully testable. The LLM-facing CoT prompt
(`router_cot`) is in `references/prompt_templates.md`.

---

## 9. Extending the Registry

To add a new skill:

1. Write `skills/sub-.md` with frontmatter `name` + `description` and the
   required sections (Role & Persona, Workflow, Tools, Output Format, Quality
   Gates).
2. Implement a handler `(inputs, ctx) -> dict` in `engine.py`.
3. Register a `SkillSpec` in `Engine._register_skills`.
4. Add the skill to the router pipeline(s) if it should be routable.
5. Export/generate any new JSON Schemas via `scripts/export_schemas.py`.
6. Add a test under `tests/`.

To add a new tool:

1. Subclass `Tool` in `src/urban_noise_barrier/tools/.py`, set class
   attributes `name`, `description`, `input_schema`, `output_schema`, and
   implement `execute`.
2. Register it in `default_tool_registry()`.
3. Add a test under `tests/`.

---

## 10. File map

```
skills/main.md                  # orchestrator + router + gates (this contract)
skills/sub-*.md                 # one markdown doc per registered skill
src/urban_noise_barrier/        # Python implementation
  engine.py registry.py router.py hooks.py config.py
  context.py schemas.py errors.py logging_setup.py cli.py
  tools/{acoustics,vegetation,species,air_quality,evidence,knowledge}.py
assets/schemas/*.json           # canonical JSON Schemas (exported)
config/default.yaml             # layered configuration
references/                     # domain methods, prompts, species DB, sources
scripts/                        # setup, seed, ingest, run, validate, export
tests/                          # pytest unit + scenario tests
SECOND-KNOWLEDGE-BRAIN.md       # living knowledge base
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [dungnotnull](https://github.com/dungnotnull)
- **Source:** [dungnotnull/urban-noise-tree-barrier-planning-agent-skill](https://github.com/dungnotnull/urban-noise-tree-barrier-planning-agent-skill)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-dungnotnull-urban-noise-tree-barrier-planning-agent-skill-urban-noise-tree-barrier-planning-agent-skill
- Seller: https://agentstack.voostack.com/s/dungnotnull
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
