diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md
index 040285e5..75709578 100644
--- a/docs/development/current/main/10-Now.md
+++ b/docs/development/current/main/10-Now.md
@@ -2,8 +2,8 @@
## Current Focus
-- Phase: `docs/development/current/main/phases/phase-29ap/README.md` (complete)
-- Next: TBD (choose next phase after Phase 29ap closeout)
+- Phase: `docs/development/current/main/phases/phase-29aq/README.md`
+- Next: Phase 29aq P0 (inventory, docs-first)
## Gate (SSOT)
diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md
index 7cb26f32..90d5045c 100644
--- a/docs/development/current/main/30-Backlog.md
+++ b/docs/development/current/main/30-Backlog.md
@@ -5,7 +5,7 @@ Scope: 「次にやる候補」を短く列挙するメモ。入口は `docs/dev
## Active
-- Next phase TBD: choose between Plan/Composer subset expansion or CorePlan vocabulary expansion
+- Phase 29aq: `docs/development/current/main/phases/phase-29aq/README.md` (Next: P0 inventory)
- JoinIR regression gate SSOT: `docs/development/current/main/phases/phase-29ae/README.md`
- CorePlan hardening (docs-first): `docs/development/current/main/phases/phase-29al/README.md`
diff --git a/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md b/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
index 259d2ef5..1fb301a5 100644
--- a/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
+++ b/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
@@ -33,8 +33,8 @@ Related:
## 1.1 Current (active)
-- Active phase: `docs/development/current/main/phases/phase-29ap/README.md` (complete)
-- Next step: TBD (choose next phase)
+- Active phase: `docs/development/current/main/phases/phase-29aq/README.md`
+- Next step: Phase 29aq P0 (stdlib loop inventory)
## 2. すでに固めた SSOT(再発防止の土台)
diff --git a/docs/development/current/main/phases/phase-29aq/README.md b/docs/development/current/main/phases/phase-29aq/README.md
new file mode 100644
index 00000000..69525634
--- /dev/null
+++ b/docs/development/current/main/phases/phase-29aq/README.md
@@ -0,0 +1,57 @@
+---
+Status: Active
+Scope: stdlib trim/parse loop inventory (docs-first)
+Related:
+- docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
+- docs/development/current/main/phases/phase-29ae/README.md
+- docs/development/current/main/phases/phase-29ap/README.md
+---
+
+# Phase 29aq: stdlib trim/parse loop inventory (docs-first)
+
+Goal: inventory loop shapes in json_native stdlib and map them to conservative
+Plan/Composer subsets (or mark unsupported) before adding new subsets.
+
+## Ok(None) / Freeze boundary (SSOT)
+
+- Ok(None): non-matching shapes (default).
+- Freeze: only when a shape is explicitly gated and contradictory; do not add
+ new Freeze cases in P0.
+
+## Fixture / smoke naming (SSOT)
+
+- Fixtures: `apps/tests/phase29aq____min.hako`
+- Smokes: `tools/smokes/v2/profiles/integration/joinir/phase29aq____vm.sh`
+- Gate: wire into `phase29ae_regression_pack_vm.sh` when a subset is added.
+
+## Inventory (stdlib json_native)
+
+### StringUtils (`apps/lib/json_native/utils/string.hako`)
+
+| Function | Loop summary | Provisional bucket | Notes |
+| --- | --- | --- | --- |
+| `trim_start` | scan until non-whitespace, `break` | Pattern2Break | Subset already exists (Phase 29ap P6) |
+| `trim_end` | reverse scan until non-whitespace, `break` | Pattern2Break | Subset already exists (Phase 29ap P6) |
+| `index_of` | scan, early `return` on match | ScanWithInit | Needs return-in-loop handling |
+| `last_index_of` | reverse scan, early `return` | ScanWithInit | Needs return-in-loop handling |
+| `index_of_string` | scan substrings, early `return` | SplitScan | Candidate subset |
+| `to_upper` | scan + accumulate | ScanWithInit | Candidate subset |
+| `to_lower` | scan + accumulate | Pattern1 subset | Already migrated (Phase 29ap P2) |
+| `join` | array join with `if i > 0` separator | Pattern1 subset | Already migrated (Phase 29ap P3) |
+| `split` | scan + push segments | SplitScan | Candidate subset |
+| `is_integer` | scan digits, early `return false` | Unsupported | Return-heavy; needs design |
+| `parse_integer` | scan digits, `break` on invalid | Pattern2Break | Candidate subset |
+
+### Lexer / Parser (out of scope for P0)
+
+| File | Loop summary | Provisional bucket | Notes |
+| --- | --- | --- | --- |
+| `lexer/scanner.hako` | scan loops with nested loops (string/number) | Unsupported | Multiple nested scans |
+| `lexer/tokenizer.hako` | tokenize loop with `break`/`continue` | Unsupported | Control-flow heavy |
+| `parser/parser.hako` | `loop(true)` object/array parse | Unsupported | Structured parse loop |
+| `utils/escape.hako` | escape/unescape scans | Unsupported | Nested scan/branching |
+| `core/node.hako` | collection iteration loops | Unsupported | Not a parsing scan |
+
+## Next (planned)
+
+- P1: Pick top 3 subset candidates from the table and define fixtures/smokes.