---
phase: 19-methodology-guidance-and-polaris
plan: 02
type: execute
wave: 1
depends_on: []
files_modified:
  - src/ztlctl/templates/self/methodology.md.j2
  - src/ztlctl/services/check.py
  - src/ztlctl/mcp/resources.py
  - tests/services/test_check.py
  - tests/mcp/test_resources.py
autonomous: true
requirements: [METH-01, METH-02, METH-03]

must_haves:
  truths:
    - "Prose-as-title convention is documented in methodology.md.j2 with examples and research-partner tone"
    - "CheckService flags notes with short or generic titles at info severity under CAT_STRUCTURAL"
    - "Garden backlog MCP resource includes title improvement candidates alongside stale seeds and orphans"
  artifacts:
    - path: "src/ztlctl/templates/self/methodology.md.j2"
      provides: "Prose-as-title guidance section"
      contains: "prose-as-title"
    - path: "src/ztlctl/services/check.py"
      provides: "Title quality check in _check_structural_validation"
      contains: "title_quality"
    - path: "src/ztlctl/mcp/resources.py"
      provides: "Title improvement candidates in garden_backlog_impl"
      contains: "title_improvement"
  key_links:
    - from: "src/ztlctl/services/check.py"
      to: "CAT_STRUCTURAL"
      via: "title quality issues appended to structural validation"
      pattern: "title.*quality"
    - from: "src/ztlctl/mcp/resources.py"
      to: "src/ztlctl/services/check.py"
      via: "garden_backlog_impl reads check results for title candidates"
      pattern: "title_improvement"
---

<objective>
Add prose-as-title guidance to the methodology template, implement title quality checking in CheckService, and surface title improvement candidates in the garden backlog MCP resource.

Purpose: Guide users and agents toward descriptive titles that serve as a search index, with advisory (non-blocking) quality signals.
Output: Updated methodology template, title quality check, enhanced garden backlog resource, tests.
</objective>

<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/19-methodology-guidance-and-polaris/19-CONTEXT.md

<interfaces>
<!-- Key types and contracts the executor needs. -->

From src/ztlctl/services/check.py (structural validation pattern, line ~640-710):
```python
CAT_STRUCTURAL = "structural_validation"
SEVERITY_INFO = "info"

def _check_structural_validation(self, conn: Connection) -> list[dict[str, Any]]:
    """Category 4: ID format, status validity, tag format."""
    issues: list[dict[str, Any]] = []
    all_nodes = conn.execute(select(nodes.c.id, nodes.c.type, nodes.c.status)).fetchall()
    # ... ID pattern checks, status validity, tag format ...
    # Each issue: {"category": CAT_STRUCTURAL, "severity": ..., "node_id": ..., "message": ..., "fix_action": None}
```

From src/ztlctl/mcp/resources.py (garden_backlog_impl, line ~152-172):
```python
def garden_backlog_impl(vault: Any) -> dict[str, Any]:
    from ztlctl.services.query import QueryService
    review = QueryService(vault).vault_review(top=10)
    if not review.ok:
        return {"items": [], "count": 0}
    backlog = [*review.data.get("stale_seeds", []), *review.data.get("orphan_notes", [])]
    # deduplicate by id...
    return {"items": items, "count": len(items)}
```

From src/ztlctl/templates/self/methodology.md.j2 (existing template structure):
```jinja2
# Methodology -- {{ vault_name }}
## Core Principles
1. **Atomic notes** -- one idea per note...
{% if tone == "research-partner" %}
## Workflow Guidance
### Creating Notes
1. **Search first** ...
{% endif %}
```

From src/ztlctl/infrastructure/database/schema.py (nodes table has title column):
```python
nodes = Table("nodes", metadata, Column("title", String, nullable=False), ...)
```
</interfaces>
</context>

<tasks>

<task type="auto" tdd="true">
  <name>Task 1: Methodology template prose-as-title section + title quality check</name>
  <files>
    src/ztlctl/templates/self/methodology.md.j2
    src/ztlctl/services/check.py
    tests/services/test_check.py
  </files>
  <read_first>
    src/ztlctl/templates/self/methodology.md.j2
    src/ztlctl/services/check.py
    tests/services/test_check.py
    src/ztlctl/infrastructure/database/schema.py
    plugin/skills/vault-methodology/SKILL.md
  </read_first>
  <behavior>
    - Test: title with 1 word ("Notes") is flagged at info severity under CAT_STRUCTURAL
    - Test: title with 2 words ("My Notes") is flagged at info severity
    - Test: title with 3 words ("Notes on X") is flagged at info severity
    - Test: title matching generic pattern "Untitled" is flagged at info severity
    - Test: title matching generic pattern "New Note" is flagged at info severity
    - Test: title with 4+ descriptive words is NOT flagged
    - Test: title quality issues only appear at min_severity="info", not at default "warning"
    - Test: flagged issues have category CAT_STRUCTURAL and severity SEVERITY_INFO
  </behavior>
  <action>
    1. Update `src/ztlctl/templates/self/methodology.md.j2`:
       - Add a new subsection under the `research-partner` tone block (inside `{% if tone == "research-partner" %}`), after the "Creating Notes" section:
         ```markdown
         ### Prose-as-Title Convention

         Your titles ARE your search index. Write them as complete thoughts, not labels.

         | Instead of | Write |
         |-----------|-------|
         | "Authentication" | "JWT authentication with refresh token rotation" |
         | "Meeting Notes" | "Q1 planning alignment on data pipeline priorities" |
         | "Bug Fix" | "Fix race condition in session close during concurrent reweave" |
         | "Ideas" | "Potential approaches to cross-vault knowledge federation" |

         A good title lets you find the note without opening it. Aim for 4+ words
         that capture the specific insight, decision, or topic.
         ```

    2. Add title quality checking to `src/ztlctl/services/check.py` in `_check_structural_validation`:
       - After the existing tag format warnings block (around line 710), add a new title quality block:
         ```python
         # Title quality advisory (info severity)
         _GENERIC_TITLE_PATTERNS = {"untitled", "new note", "note", "notes", "draft", "temp", "test"}
         for row in all_nodes:
             title = str(row.title or "").strip()
             title_lower = title.lower()
             word_count = len(title.split())
             is_generic = title_lower in _GENERIC_TITLE_PATTERNS or title_lower.startswith("notes on ")
             if word_count <= 3 or is_generic:
                 issues.append(
                     {
                         "category": CAT_STRUCTURAL,
                         "severity": SEVERITY_INFO,
                         "node_id": row.id,
                         "message": (
                             f"Title quality: '{title}' is short or generic — "
                             "consider a prose title that captures the specific insight "
                             "(see methodology.md for examples)"
                         ),
                         "fix_action": None,
                     }
                 )
         ```
       - Note: `_GENERIC_TITLE_PATTERNS` should be a module-level frozenset, not inside the method. Define it near the top of the file alongside the severity/category constants.

    3. Add tests in `tests/services/test_check.py`:
       - Create notes with short/generic titles, run `check(min_severity="info")`, assert title quality issues are present with `CAT_STRUCTURAL` and `SEVERITY_INFO`
       - Create notes with descriptive 4+ word titles, assert no title quality issues
       - Run `check()` (default min_severity="warning"), assert title quality issues are filtered out (info < warning)
  </action>
  <verify>
    <automated>uv run pytest tests/services/test_check.py -x -q -k title</automated>
  </verify>
  <acceptance_criteria>
    - grep "Prose-as-Title" src/ztlctl/templates/self/methodology.md.j2 finds the section
    - grep "your search index" src/ztlctl/templates/self/methodology.md.j2 finds the guidance
    - grep "GENERIC_TITLE_PATTERNS" src/ztlctl/services/check.py finds the pattern set
    - grep "Title quality" src/ztlctl/services/check.py finds the issue message
    - grep "SEVERITY_INFO" src/ztlctl/services/check.py confirms info severity for title issues
    - grep "title" tests/services/test_check.py finds test coverage
  </acceptance_criteria>
  <done>
    - methodology.md.j2 has Prose-as-Title section with table of examples and research-partner tone
    - _check_structural_validation flags titles <= 3 words or matching generic patterns at SEVERITY_INFO
    - Title quality issues only visible at min_severity="info"
    - All title-related tests pass
  </done>
</task>

<task type="auto" tdd="true">
  <name>Task 2: Garden backlog resource with title improvement candidates</name>
  <files>
    src/ztlctl/mcp/resources.py
    tests/mcp/test_resources.py
  </files>
  <read_first>
    src/ztlctl/mcp/resources.py
    tests/mcp/test_resources.py
    src/ztlctl/services/check.py
  </read_first>
  <behavior>
    - Test: garden_backlog_impl returns dict with "title_improvement_candidates" key
    - Test: title improvement candidates contain notes with short/generic titles from check(min_severity="info")
    - Test: existing stale_seeds and orphan_notes items still present in backlog
    - Test: empty vault returns empty title_improvement_candidates list
  </behavior>
  <action>
    1. Modify `garden_backlog_impl` in `src/ztlctl/mcp/resources.py`:
       - After the existing stale_seeds + orphan_notes aggregation, add title improvement candidates:
         ```python
         # Title improvement candidates (from check at info severity)
         from ztlctl.services.check import CheckService, CAT_STRUCTURAL, SEVERITY_INFO
         check_result = CheckService(vault).check(min_severity="info")
         title_candidates = []
         if check_result.ok:
             for issue in check_result.data.get("issues", []):
                 if (
                     issue.get("category") == CAT_STRUCTURAL
                     and issue.get("severity") == SEVERITY_INFO
                     and "Title quality" in str(issue.get("message", ""))
                 ):
                     title_candidates.append({
                         "id": issue.get("node_id"),
                         "message": issue.get("message"),
                     })
         ```
       - Add `"title_improvement_candidates": title_candidates` to the returned dict alongside `"items"` and `"count"`

    2. Add tests in `tests/mcp/test_resources.py`:
       - Create a vault with notes having short titles, call `garden_backlog_impl`, assert `title_improvement_candidates` key exists and contains entries
       - Verify existing backlog items (stale_seeds, orphans) still work
  </action>
  <verify>
    <automated>uv run pytest tests/mcp/test_resources.py -x -q -k backlog</automated>
  </verify>
  <acceptance_criteria>
    - grep "title_improvement_candidates" src/ztlctl/mcp/resources.py finds the new field
    - grep "Title quality" src/ztlctl/mcp/resources.py finds the filtering logic
    - grep "title_improvement" tests/mcp/test_resources.py finds test coverage
  </acceptance_criteria>
  <done>
    - garden_backlog_impl returns title_improvement_candidates alongside stale_seeds and orphans
    - Candidates sourced from CheckService at info severity
    - Tests verify title candidates appear for short/generic titles
  </done>
</task>

</tasks>

<verification>
1. `uv run pytest tests/services/test_check.py tests/mcp/test_resources.py -x -q` — all tests pass
2. `uv run ruff check src/ztlctl/templates/self/methodology.md.j2 src/ztlctl/services/check.py src/ztlctl/mcp/resources.py` — no lint errors
3. `uv run mypy src/ztlctl/services/check.py src/ztlctl/mcp/resources.py` — no type errors
</verification>

<success_criteria>
- methodology.md.j2 contains Prose-as-Title convention with examples
- CheckService flags short/generic titles at info severity under CAT_STRUCTURAL
- Garden backlog resource includes title_improvement_candidates
- Title quality is advisory only (info severity, never blocks creation)
- All tests pass, lint clean, types clean
</success_criteria>

<output>
After completion, create `.planning/phases/19-methodology-guidance-and-polaris/19-02-SUMMARY.md`
</output>
