Files
chanora/dev-docs/superpowers/plans/2026-06-13-documentation-site.md
T

45 KiB

Documentation Site & ASPICE Traceability Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Create a private Docusaurus doc site with tag-based ASPICE traceability, hosted on Cloudflare Pages with access control, served from a git submodule.

Architecture: The docs repo (chanoraapp/docs) is a standalone Docusaurus project added as a git submodule at docs/ in the code repo. A custom Docusaurus plugin validates requirement ID traceability chains on every build. The code repo retains development-only docs in dev-docs/.

Tech Stack: Docusaurus 3.10 (Meta-maintained), Node.js 20, custom traceability plugin (~100 lines JavaScript), standalone CI validator (Node.js), GitHub Actions, Cloudflare Pages + Access, git submodules

Spec: dev-docs/superpowers/specs/2026-06-13-documentation-site-design.md

Note: This plan was originally written for MkDocs Material. During implementation, MkDocs was replaced with Docusaurus due to MkDocs ecosystem instability (1.x unmaintained, 2.0 breaking). The task descriptions below reference MkDocs but the actual implementation uses Docusaurus 3.10. See the spec for the Docusaurus configuration details.


Task 1: Create Docs Repo and MkDocs Configuration

Files:

  • Create: mkdocs.yml
  • Create: requirements.txt
  • Create: pyproject.toml
  • Create: docs/index.md
  • Create: docs/.meta.yml
  • Create: README.md

Note: This task creates the chanora-docs GitHub repo. The chanora-docs repo must be created on GitHub first (private repo), then cloned locally for these steps.

  • Step 1: Create the private chanora-docs GitHub repo
gh repo create chanora-docs --private --description "Chanora engineering documentation with ASPICE traceability"
  • Step 2: Clone and initialize
git clone git@github.com:EdisonJwa/chanora-docs.git
cd chanora-docs
  • Step 3: Create requirements.txt
mkdocs-material>=9.6.0
mkdocs-git-revision-date-localized-plugin>=1.5.0
  • Step 4: Create pyproject.toml
[project]
name = "chanora-docs"
version = "0.1.0"
description = "Chanora engineering documentation with ASPICE traceability"
requires-python = ">=3.12"
  • Step 5: Create mkdocs.yml with full configuration
site_name: Chanora Engineering Docs
site_description: ASPICE-compliant engineering documentation with automated traceability
site_url: https://docs.chanora.dev

repo_name: EdisonJwa/chanora-docs
repo_url: https://github.com/EdisonJwa/chanora-docs
edit_uri: edit/main/docs/

theme:
  name: material
  language: en
  features:
    - navigation.instant
    - navigation.tracking
    - navigation.tabs
    - navigation.sections
    - navigation.expand
    - navigation.footer
    - search.highlight
    - search.suggest
    - content.code.copy
    - content.tabs.link
  palette:
    - media: "(prefers-color-scheme)"
      toggle:
        icon: material/brightness-auto
        name: Switch to light mode
    - media: "(prefers-color-scheme: light)"
      scheme: default
      primary: deep purple
      accent: purple
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)"
      scheme: slate
      primary: deep purple
      accent: purple
      toggle:
        icon: material/brightness-4
        name: Switch to system preference
  icon:
    repo: fontawesome/brands/github

plugins:
  - search
  - tags:
      tags_allowed:
        - sysrs
        - sysdes
        - srs
        - sad
        - sdd
        - swe.1
        - swe.2
        - swe.3
        - swe.4
        - swe.5
        - swe.6
        - sys.4
        - requirements
        - architecture
        - verification
        - governance
        - security
        - privacy
        - legal
        - release
        - references
        - ui-ux
        - localization
        - baseline
        - draft
        - candidate
        - deferred
      tags_file: tags.md
  - git-revision-date-localized:
      type: iso_date
      enable_creation_date: true
  - traceability:
      strict: true
      coverage_file: true
      dashboard: true

nav:
  - Home: index.md
  - Requirements:
      - System Requirements (SysRS): requirements/sysrs.md
      - System Design (SysDes): requirements/sysdes.md
      - Software Requirements (SRS): requirements/srs.md
  - Architecture & Design:
      - Software Architecture (SWE.2 / SAD): architecture/sad.md
      - Detailed Design (SWE.3 / SDD): architecture/sdd.md
      - File Transfer Design: architecture/file-transfer-design.md
      - File Transfer Research: architecture/file-transfer-research.md
      - File Transfer Implementation Plan: architecture/file-transfer-implementation-plan.md
      - Desktop PTT Architecture: architecture/desktop-ptt-architecture.md
  - Verification:
      - System Level:
          - SYS.4 System Integration: verification/sys4-system-integration-verification-plan.md
      - Software Integration:
          - SWE.5 Software Integration: verification/swe5-software-integration-verification-plan.md
      - Unit Level:
          - SWE.4 Unit Verification: verification/swe4-unit-verification-plan.md
      - Software Qualification:
          - SWE.6 Software Verification: verification/swe6-software-verification-plan.md
      - Master Plan: verification/verification-master-plan.md
  - Governance:
      - Document Index: governance/document-index.md
      - Traceability Matrix: governance/traceability-matrix.md
      - Decision Register: governance/product-decision-register.md
      - Baseline Approval Record: governance/baseline-approval-record.md
      - Baseline Candidate Validation: governance/baseline-candidate-validation-report.md
      - Document Review Report: governance/document-review-report.md
      - Document Naming Convention: governance/document-naming-convention.md
      - Decision Impact Assessment: governance/decision-impact-assessment.md
      - Git Commit Message Convention: governance/git-commit-message-convention.md
      - Repo Format Validation: governance/repo-format-validation-report.md
      - Path Migration Map: governance/path-migration-map.md
      - Maintainability Review: governance/maintainability-review-2026-06-08.md
  - Security & Privacy:
      - Security Guidelines: security/security-privacy-legal-guideline.md
      - Threat Model: security/threat-model.md
      - Secure Storage Audit: security/secure-storage-audit-report.md
      - Diagnostic Redaction Audit: security/diagnostic-redaction-audit-report.md
      - Dependency & Supply Chain: security/dependency-and-supply-chain-report.md
      - License Inventory: security/license-inventory.md
      - Flutter License Inventory: security/flutter-license-inventory.md
      - Privacy Policy: privacy/privacy-policy.md
      - Legal Review: legal/trademark-and-attribution-review.md
  - Release:
      - Platform Release Policy: release/platform-release-policy.md
      - Release Readiness (Go/No-Go): release/release-readiness-go-nogo-record.md
      - DV Waiver Register: release/dv-waiver-register.md
  - References:
      - External References: references/external-references.md
      - ASPICE SWE.2/SWE.3 Note: references/aspice-swe2-swe3-integration-note.md
      - TeamSpeak Protocol Reference (EN): references/yatqa-en.md
      - TeamSpeak Protocol Reference (DE): references/yatqa-de.md
      - TeaSpeak Overview: references/teaspeak-overview.md
      - ReSpeak Overview: references/respeak-overview.md
  - UI/UX:
      - Material 3 Guideline: ui-ux/material3-guideline.md
      - Design Tokens: ui-ux/material3-design-tokens.md
      - Component Catalog: ui-ux/material3-component-catalog.md
      - Adaptive Layout Guide: ui-ux/adaptive-layout-platform-guide.md
  - Localization:
      - Localization Architecture: i18n/localization-architecture.md

markdown_extensions:
  - admonition
  - pymdownx.details
  - pymdownx.superfences
  - pymdownx.tabbed:
      alternate_style: true
  - pymdownx.highlight:
      anchor_linenums: true
  - pymdownx.inlinehilite
  - pymdownx.snippets
  - attr_list
  - md_in_html
  - tables
  - toc:
      permalink: true
  • Step 6: Create docs/.meta.yml (global defaults)
status: draft
  • Step 7: Create docs/index.md (landing page)
# Chanora Engineering Documentation

**ASPICE-compliant engineering documentation with automated traceability**

---

## Lifecycle Chain

```text
SysRS → SysDes → SRS → SAD (SWE.2) → SDD (SWE.3) → Verification
                                          ↓              ↓
                                      SWE.4 (unit)   SWE.4/5/6/SYS.4

Quick Navigation

Baseline Status

Document Status
SysRS Baseline
SysDes Baseline
SRS Baseline
SAD Baseline candidate
SDD Baseline candidate
Verification plans Baseline candidate
Release readiness No-Go

View all tags →


- [ ] **Step 8: Create `README.md`**

```markdown
# Chanora Engineering Docs

ASPICE-compliant engineering documentation site for Chanora.

## Local Development

```bash
pip install -r requirements.txt
mkdocs serve

Build

mkdocs build --strict

Traceability Validation

python scripts/validate_traceability.py docs/

Deployment

Deploys automatically to Cloudflare Pages on push to main.


- [ ] **Step 9: Create directory structure for docs**

```bash
mkdir -p docs/{requirements,architecture,verification,governance,security,privacy,legal,release,references,ui-ux,i18n}
mkdir -p plugins/traceability
mkdir -p scripts
mkdir -p .github/workflows
  • Step 10: Commit
git add -A
git commit -m "chore: initialize MkDocs Material project with configuration and landing page"

Task 2: Build Custom Traceability Plugin

Files:

  • Create: plugins/traceability/__init__.py

  • Create: plugins/traceability/traceability.py

  • Create: tests/test_traceability.py

  • Step 1: Create plugin package init

# plugins/traceability/__init__.py
from .traceability import TraceabilityPlugin

def make_plugin(config, **kwargs):
    return TraceabilityPlugin(config)
  • Step 2: Write the traceability plugin
# plugins/traceability/traceability.py
"""MkDocs plugin for ASPICE requirement traceability validation."""

import json
import re
from collections import defaultdict
from pathlib import Path

from mkdocs.plugins import BasePlugin
from mkdocs.structure.pages import Page

REQUIREMENT_ID_PATTERNS = {
    "sysrs": re.compile(r"SysRS-\d+"),
    "sysdes": re.compile(r"SysDes-\d+"),
    "srs": re.compile(r"SRS-\d+"),
    "sdd_mod": re.compile(r"SDD-MOD-\d+"),
    "dec": re.compile(r"DEC-\d+"),
}

CHAINS = [
    ("sysrs", "sysdes"),
    ("sysdes", "srs"),
    ("srs", "sad"),
    ("srs", "sdd"),
    ("sad", "swe5"),
    ("sdd", "swe4"),
    ("srs", "swe6"),
    ("sysdes", "sys4"),
]


class TraceabilityPlugin(BasePlugin):
    config_scheme = (
        ("strict", {"type": bool, "default": True}),
        ("coverage_file", {"type": bool, "default": True}),
        ("dashboard", {"type": bool, "default": True}),
    )

    def __init__(self, config):
        super().__init__(config)
        self.defined_ids: dict[str, set[str]] = defaultdict(set)
        self.referenced_ids: dict[str, set[str]] = defaultdict(set)
        self.page_ids: dict[str, set[str]] = defaultdict(set)
        self.page_src: dict[str, str] = {}

    def on_page_markdown(self, markdown: str, page: Page, config, files):
        src_path = page.file.src_path
        self.page_src[src_path] = src_path

        for pattern_name, pattern in REQUIREMENT_ID_PATTERNS.items():
            found = set(pattern.findall(markdown))
            if found:
                self.page_ids[src_path].update(found)

        tags = page.meta.get("tags", [])
        for tag in tags:
            if isinstance(tag, str) and any(
                tag.startswith(prefix)
                for prefix in ["SysRS-", "SysDes-", "SRS-", "SDD-MOD-", "DEC-"]
            ):
                self.defined_ids[tag].add(src_path)

        for pattern_name, pattern in REQUIREMENT_ID_PATTERNS.items():
            for match in pattern.findall(markdown):
                self.referenced_ids[match].add(src_path)

        return markdown

    def on_post_build(self, config):
        orphans = []
        for req_id, pages in self.referenced_ids.items():
            if req_id not in self.defined_ids:
                orphans.append((req_id, sorted(pages)))

        coverage = {}
        for upstream, downstream in CHAINS:
            upstream_ids = set()
            for req_id, pages in self.defined_ids.items():
                if req_id.upper().startswith(upstream.upper()):
                    upstream_ids.add(req_id)

            downstream_refs = set()
            for req_id, pages in self.referenced_ids.items():
                for page in pages:
                    if downstream in page.lower():
                        downstream_refs.add(req_id)

            if upstream_ids:
                covered = upstream_ids & downstream_refs
                coverage[f"{upstream} -> {downstream}"] = {
                    "total": len(upstream_ids),
                    "covered": len(covered),
                    "percentage": round(100 * len(covered) / len(upstream_ids), 1)
                    if upstream_ids
                    else 0,
                    "orphaned": sorted(upstream_ids - covered),
                }

        report = {
            "chains": coverage,
            "orphaned_references": [
                {"id": rid, "referenced_in": sorted(pages)}
                for rid, pages in orphans
            ],
        }

        if self.config["coverage_file"]:
            output_dir = Path(config["site_dir"])
            with open(output_dir / "traceability-coverage.json", "w") as f:
                json.dump(report, f, indent=2)

        self._print_summary(report)

        if self.config["strict"] and (orphans or any(
            c.get("orphaned") for c in coverage.values()
        )):
            import sys
            print(
                "\nERROR: Traceability validation failed. "
                "Set strict: false to allow broken chains.",
                file=sys.stderr,
            )
            sys.exit(1)

    def _print_summary(self, report):
        print("\n" + "=" * 60)
        print("ASPICE Traceability Summary")
        print("=" * 60)
        for chain, data in report["chains"].items():
            status = "PASS" if not data["orphaned"] else "WARN"
            print(
                f"  [{status}] {chain}: "
                f"{data['covered']}/{data['total']} "
                f"({data['percentage']}%)"
            )
        if report["orphaned_references"]:
            print(f"\n  Orphaned references: {len(report['orphaned_references'])}")
            for orphan in report["orphaned_references"][:10]:
                print(f"    - {orphan['id']} in {', '.join(orphan['referenced_in'])}")
            if len(report["orphaned_references"]) > 10:
                print(
                    f"    ... and {len(report['orphaned_references']) - 10} more"
                )
        print("=" * 60 + "\n")
  • Step 3: Write plugin test
# tests/test_traceability.py
"""Tests for the traceability MkDocs plugin."""

import json
import tempfile
from pathlib import Path
from unittest.mock import MagicMock

import pytest

from traceability import TraceabilityPlugin, REQUIREMENT_ID_PATTERNS


def test_pattern_matches_sysrs():
    pattern = REQUIREMENT_ID_PATTERNS["sysrs"]
    assert pattern.findall("This traces to SysRS-233 and SysRS-234") == [
        "SysRS-233",
        "SysRS-234",
    ]


def test_pattern_matches_srs():
    pattern = REQUIREMENT_ID_PATTERNS["srs"]
    assert pattern.findall("Covers SRS-045 through SRS-053") == [
        "SRS-045",
        "SRS-053",
    ]


def test_pattern_matches_sdd_mod():
    pattern = REQUIREMENT_ID_PATTERNS["sdd_mod"]
    assert pattern.findall("Module SDD-MOD-009 handles this") == ["SDD-MOD-009"]


def test_no_false_positives():
    pattern = REQUIREMENT_ID_PATTERNS["sysrs"]
    assert pattern.findall("No requirements here") == []
    assert pattern.findall("sysrs-123 lowercase should not match") == []


def test_plugin_stores_defined_ids():
    config = {"strict": False, "coverage_file": False, "dashboard": False}
    plugin = TraceabilityPlugin(config)

    page = MagicMock()
    page.meta = {"tags": ["SysRS-233", "swe.1", "baseline"]}
    page.file.src_path = "requirements/sysrs.md"

    plugin.on_page_markdown("content", page, {}, None)
    assert "SysRS-233" in plugin.defined_ids


def test_plugin_stores_referenced_ids():
    config = {"strict": False, "coverage_file": False, "dashboard": False}
    plugin = TraceabilityPlugin(config)

    page = MagicMock()
    page.meta = {"tags": ["swe.4"]}
    page.file.src_path = "verification/swe4-unit-verification-plan.md"

    plugin.on_page_markdown(
        "Verifies SDD-MOD-001, SDD-MOD-002, and SDD-MOD-003",
        page,
        {},
        None,
    )
    assert "SDD-MOD-001" in plugin.referenced_ids
    assert "SDD-MOD-002" in plugin.referenced_ids
    assert "SDD-MOD-003" in plugin.referenced_ids
  • Step 4: Create directory structure and run tests
mkdir -p tests
pip install -r requirements.txt
cd plugins/traceability && python -m pytest ../../tests/test_traceability.py -v

Expected: 5 tests pass (some may fail if mkdocs is not installed in test environment — adjust imports as needed).

  • Step 5: Commit
git add plugins/ tests/
git commit -m "feat: add traceability plugin with requirement ID scanning and validation"

Task 3: Build Standalone CI Validator

Files:

  • Create: scripts/validate_traceability.py

  • Step 1: Write the standalone validator

#!/usr/bin/env python3
"""Standalone ASPICE traceability validator for CI.

Usage:
    python scripts/validate_traceability.py docs/

Exit codes:
    0 - All chains valid
    1 - Broken chains found
"""

import re
import sys
from collections import defaultdict
from pathlib import Path

REQUIREMENT_ID_PATTERNS = {
    "sysrs": re.compile(r"SysRS-\d+"),
    "sysdes": re.compile(r"SysDes-\d+"),
    "srs": re.compile(r"SRS-\d+"),
    "sdd_mod": re.compile(r"SDD-MOD-\d+"),
    "dec": re.compile(r"DEC-\d+"),
}

CHAINS = [
    ("sysrs", "sysdes"),
    ("sysdes", "srs"),
    ("srs", "sad"),
    ("srs", "sdd"),
    ("sad", "swe5"),
    ("sdd", "swe4"),
    ("srs", "swe6"),
    ("sysdes", "sys4"),
]


def extract_front_matter(content: str) -> dict:
    """Extract YAML front matter from markdown content."""
    if content.startswith("---"):
        end = content.find("---", 3)
        if end != -1:
            return {"raw": content[3:end]}
    return {}


def scan_docs(docs_dir: Path) -> dict:
    """Scan all markdown files for requirement IDs."""
    defined_ids: dict[str, set[str]] = defaultdict(set)
    referenced_ids: dict[str, set[str]] = defaultdict(set)

    for md_file in docs_dir.rglob("*.md"):
        content = md_file.read_text(encoding="utf-8")
        rel_path = str(md_file.relative_to(docs_dir))

        # Extract tags from front matter
        fm = extract_front_matter(content)
        if "raw" in fm:
            for line in fm["raw"].split("\n"):
                if "tags:" in line:
                    for tag in re.findall(r"\b(?:SysRS|SysDes|SRS|SDD-MOD|DEC)-\d+", line):
                        defined_ids[tag].add(rel_path)

        # Find all requirement ID references in content
        for pattern_name, pattern in REQUIREMENT_ID_PATTERNS.items():
            for match in pattern.findall(content):
                referenced_ids[match].add(rel_path)

    return {"defined": defined_ids, "referenced": referenced_ids}


def validate(data: dict) -> list[dict]:
    """Validate traceability chains."""
    issues = []

    # Check for orphaned references
    for req_id, pages in data["referenced"].items():
        if req_id not in data["defined"]:
            issues.append({
                "type": "orphaned_reference",
                "id": req_id,
                "referenced_in": sorted(pages),
            })

    return issues


def print_report(issues: list[dict], data: dict) -> None:
    """Print validation report."""
    print("=" * 60)
    print("ASPICE Traceability Validation")
    print("=" * 60)

    if not issues:
        print("  [PASS] All requirement references have definitions")
    else:
        orphaned = [i for i in issues if i["type"] == "orphaned_reference"]
        if orphaned:
            print(f"\n  [FAIL] {len(orphaned)} orphaned reference(s):")
            for issue in orphaned[:20]:
                print(f"    - {issue['id']} referenced in {', '.join(issue['referenced_in'])}")
            if len(orphaned) > 20:
                print(f"    ... and {len(orphaned) - 20} more")

    print("=" * 60)


def main():
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <docs-directory>", file=sys.stderr)
        sys.exit(1)

    docs_dir = Path(sys.argv[1])
    if not docs_dir.is_dir():
        print(f"Error: {docs_dir} is not a directory", file=sys.stderr)
        sys.exit(1)

    data = scan_docs(docs_dir)
    issues = validate(data)
    print_report(issues, data)

    sys.exit(1 if issues else 0)


if __name__ == "__main__":
    main()
  • Step 2: Make script executable
chmod +x scripts/validate_traceability.py
  • Step 3: Create docs/.meta.yml and a test file to validate the script
mkdir -p docs/test
echo -e '---\ntags: [swe.1, SysRS-999]\n---\n\nTest doc referencing SysRS-999.' > docs/test/validation-test.md
python scripts/validate_traceability.py docs/

Expected: Exit code 0 (SysRS-999 is defined and referenced in the same file, no orphans).

  • Step 4: Remove test file and commit
rm -rf docs/test
git add scripts/
git commit -m "feat: add standalone traceability validator for CI"

Task 4: Set Up CI/CD Pipeline

Files:

  • Create: .github/workflows/deploy.yml

  • Create: wrangler.toml

  • Step 1: Create GitHub Actions workflow

name: Build and Deploy Docs

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
          cache: pip

      - run: pip install -r requirements.txt

      - name: Validate traceability chains
        run: python scripts/validate_traceability.py docs/

      - name: Build doc site
        run: mkdocs build --strict

      - if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        uses: cloudflare/wrangler-action@v3
        with:
          command: pages deploy site --project-name=chanora-docs
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
  • Step 2: Create Wrangler configuration
name = "chanora-docs"
compatibility_date = "2026-06-13"

[site]
bucket = "./site"
  • Step 3: Commit
git add .github/ wrangler.toml
git commit -m "ci: add GitHub Actions workflow for build, validate, and Cloudflare Pages deploy"

Task 5: Migrate ASPICE Docs to Docs Repo

Files:

  • Copy all ASPICE docs from chanora/docs/ to chanora-docs/docs/
  • Add YAML front matter to each migrated file

Note: This task runs in the chanora-docs repo. The source files are in the main chanora repo at chanora/docs/.

  • Step 1: Copy requirements docs
# From chanora-docs repo root:
# Copy canonical files (these ARE the docs, not path records)
cp ../chanora/docs/sysrs.md docs/requirements/sysrs.md
cp ../chanora/docs/sysdes.md docs/requirements/sysdes.md
cp ../chanora/docs/srs.md docs/requirements/srs.md
# Note: The path records (docs/requirements/sysrs.md, docs/requirements/srs.md,
# docs/architecture/sysdes.md in the original repo) are stubs pointing to canonical
# files. We don't need them in the docs repo since the canonical files are now here.
  • Step 2: Copy architecture docs
cp ../chanora/docs/architecture/sad.md docs/architecture/sad.md
cp ../chanora/docs/architecture/sdd.md docs/architecture/sdd.md
cp ../chanora/docs/architecture/file-transfer-design.md docs/architecture/
cp ../chanora/docs/architecture/file-transfer-research.md docs/architecture/
cp ../chanora/docs/architecture/file-transfer-implementation-plan.md docs/architecture/
cp ../chanora/docs/architecture/desktop-ptt-architecture.md docs/architecture/
# Note: docs/architecture/sysdes.md in the original repo is a path record
# pointing to docs/sysdes.md. Not needed — the canonical sysdes.md is in
# docs/requirements/sysdes.md in the docs repo.
  • Step 3: Copy verification docs
cp ../chanora/docs/verification/*.md docs/verification/
  • Step 4: Copy governance docs
cp ../chanora/docs/governance/*.md docs/governance/
  • Step 5: Copy security, privacy, legal docs
cp ../chanora/docs/security/*.md docs/security/
cp ../chanora/docs/privacy/*.md docs/privacy/
cp ../chanora/docs/legal/*.md docs/legal/
  • Step 6: Copy release docs (policy, go-nogo, waiver only — NOT ios-build.md)
cp ../chanora/docs/release/platform-release-policy.md docs/release/
cp ../chanora/docs/release/release-readiness-go-nogo-record.md docs/release/
cp ../chanora/docs/release/dv-waiver-register.md docs/release/
  • Step 7: Copy references + flatten external refs
cp ../chanora/docs/references/*.md docs/references/
cp ../chanora/docs/offline-knowledge/external/yatqa-en.md docs/references/
cp ../chanora/docs/offline-knowledge/external/yatqa-de.md docs/references/
cp ../chanora/docs/offline-knowledge/external/teaspeak-overview.md docs/references/
cp ../chanora/docs/offline-knowledge/external/respeak-overview.md docs/references/
  • Step 8: Copy UI/UX, i18n, material3-guideline
cp ../chanora/docs/ui-ux/*.md docs/ui-ux/
cp ../chanora/docs/i18n/*.md docs/i18n/
# Note: docs/material3-guideline.md in the original repo is a path record
# pointing to docs/ui-ux/material3-guideline.md. Not needed — the canonical
# file is already copied above.
  • Step 9: Create section .meta.yml files
echo -e 'tags:\n  - requirements\nstatus: baseline' > docs/requirements/.meta.yml
echo -e 'tags:\n  - architecture\n  - design\nstatus: candidate' > docs/architecture/.meta.yml
echo -e 'tags:\n  - verification\nstatus: candidate' > docs/verification/.meta.yml
echo -e 'tags:\n  - governance\nstatus: baseline' > docs/governance/.meta.yml
echo -e 'tags:\n  - security\nstatus: candidate' > docs/security/.meta.yml
echo -e 'tags:\n  - privacy\nstatus: candidate' > docs/privacy/.meta.yml
echo -e 'tags:\n  - legal\nstatus: candidate' > docs/legal/.meta.yml
echo -e 'tags:\n  - release\nstatus: candidate' > docs/release/.meta.yml
echo -e 'tags:\n  - references\nstatus: baseline' > docs/references/.meta.yml
echo -e 'tags:\n  - ui-ux\nstatus: candidate' > docs/ui-ux/.meta.yml
echo -e 'tags:\n  - localization\nstatus: candidate' > docs/i18n/.meta.yml
  • Step 10: Commit all migrated files
git add docs/
git commit -m "docs: migrate all ASPICE docs from chanora repo with section meta files"

Task 6: Add Front Matter to Key ASPICE Documents

Files:

  • Modify: docs/requirements/sysrs.md

  • Modify: docs/requirements/sysdes.md

  • Modify: docs/requirements/srs.md

  • Modify: docs/architecture/sad.md

  • Modify: docs/architecture/sdd.md

  • Modify: docs/verification/*.md

  • Modify: docs/governance/traceability-matrix.md

  • Step 1: Add front matter to docs/requirements/sysrs.md

Insert at the very top of the file (before the existing # Chanora SysRS heading):

---
tags: [sysrs, requirements, swe.1, baseline]
upstream: []
downstream: [sysdes, srs]
lifecycle: SysRS
status: baseline
---
  • Step 2: Add front matter to docs/requirements/sysdes.md
---
tags: [sysdes, requirements, swe.1, baseline]
upstream: [sysrs]
downstream: [srs, sys4]
lifecycle: SysDes
status: baseline
---
  • Step 3: Add front matter to docs/requirements/srs.md
---
tags: [srs, requirements, swe.1, baseline]
upstream: [sysdes, sysrs]
downstream: [sad, sdd, swe6]
lifecycle: SRS
status: baseline
---
  • Step 4: Add front matter to docs/architecture/sad.md
---
tags: [sad, architecture, swe.2, candidate]
upstream: [srs]
downstream: [sdd, swe5]
lifecycle: SWE.2
status: candidate
---
  • Step 5: Add front matter to docs/architecture/sdd.md
---
tags: [sdd, architecture, swe.3, candidate]
upstream: [sad, srs]
downstream: [swe4]
lifecycle: SWE.3
status: candidate
---
  • Step 6: Add front matter to each verification plan

docs/verification/verification-master-plan.md:

---
tags: [verification, baseline]
upstream: [sysrs, sysdes, srs, sad, sdd]
downstream: []
lifecycle: SWE.4-SWE.6
status: candidate
---

docs/verification/swe4-unit-verification-plan.md:

---
tags: [swe.4, verification, candidate]
upstream: [sdd]
downstream: []
lifecycle: SWE.3 → SWE.4
status: candidate
---

docs/verification/swe5-software-integration-verification-plan.md:

---
tags: [swe.5, verification, candidate]
upstream: [sad]
downstream: []
lifecycle: SWE.2 → SWE.5
status: candidate
---

docs/verification/swe6-software-verification-plan.md:

---
tags: [swe.6, verification, candidate]
upstream: [srs]
downstream: []
lifecycle: SRS → SWE.6
status: candidate
---

docs/verification/sys4-system-integration-verification-plan.md:

---
tags: [sys.4, verification, candidate]
upstream: [sysdes, sysrs]
downstream: []
lifecycle: SysDes → SYS.4
status: candidate
---
  • Step 7: Add front matter to docs/governance/traceability-matrix.md
---
tags: [governance, baseline]
upstream: [sysrs, sysdes, srs, sad, sdd]
downstream: []
lifecycle: traceability
status: candidate
---
  • Step 8: Commit
git add docs/
git commit -m "docs: add ASPICE lifecycle front matter to key documents"

Task 7: Create Tags Index Page and Validate Build

Files:

  • Create: docs/tags.md

  • Step 1: Create docs/tags.md

# Tag Index

Browse all documentation by tag. Click any tag to see all pages that carry it.

<!-- material/tags -->
  • Step 2: Install dependencies and build locally
pip install -r requirements.txt
mkdocs build --strict

Expected: Build succeeds, site/ directory contains rendered HTML, site/traceability-coverage.json exists.

  • Step 3: Run standalone validator
python scripts/validate_traceability.py docs/

Expected: Exit code 0 if all referenced IDs have definitions. Any broken chains will be reported.

  • Step 4: Check the generated coverage file
cat site/traceability-coverage.json

Expected: JSON with chain coverage percentages and orphan list (if any).

  • Step 5: Commit
git add docs/tags.md
git commit -m "docs: add tags index page for traceability browsing"
  • Step 6: Push to GitHub
git push origin main

Task 8: Restructure Code Repo — Create dev-docs/

Files:

  • Create: dev-docs/superpowers/specs/ (directory)
  • Create: dev-docs/superpowers/plans/_archived/ (directory)
  • Create: dev-docs/offline-knowledge/reviews/ (directory)
  • Create: dev-docs/release/ (directory)

Note: This task runs in the main chanora code repo.

  • Step 1: Create dev-docs directory structure
mkdir -p dev-docs/superpowers/plans/_archived
mkdir -p dev-docs/superpowers/specs
mkdir -p dev-docs/offline-knowledge/reviews
mkdir -p dev-docs/release
  • Step 2: Move superpowers specs
mv docs/superpowers/specs/* dev-docs/superpowers/specs/
  • Step 3: Move active plans
mv docs/superpowers/plans/2026-05-28-server-resolution-prefetch.md dev-docs/superpowers/plans/
mv docs/superpowers/plans/2026-05-28-chanora-server-prefetch-crate.md dev-docs/superpowers/plans/
mv docs/superpowers/plans/2026-06-06-chat-panel-switching.md dev-docs/superpowers/plans/
mv docs/superpowers/plans/2026-06-08-core-internal-split.md dev-docs/superpowers/plans/
mv docs/superpowers/plans/2026-06-08-maintainability-continuation.md dev-docs/superpowers/plans/
  • Step 4: Move completed plans to archive
mv docs/superpowers/plans/2026-05-29-finish-dv-document-tree.md dev-docs/superpowers/plans/_archived/
mv docs/superpowers/plans/2026-05-29-dv-evidence-pack.md dev-docs/superpowers/plans/_archived/
mv docs/superpowers/plans/2026-05-29-swe2-swe3-baselines.md dev-docs/superpowers/plans/_archived/
mv docs/superpowers/plans/2026-05-29-state-sync-ui-settings-validation.md dev-docs/superpowers/plans/_archived/
  • Step 5: Move offline-knowledge (minus external/)
mv docs/offline-knowledge/coverage-analysis.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/doc-quality-analysis.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/link-coverage-report.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/docs-code-mismatch.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/docs-link-not-covered.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/docs-out-of-date.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/function-inventory.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/README.md dev-docs/offline-knowledge/
mv docs/offline-knowledge/reviews/* dev-docs/offline-knowledge/reviews/
  • Step 6: Move implementation status and ios-build
mv docs/implementation-status-2026-05-28.md dev-docs/
mv docs/release/ios-build.md dev-docs/release/
  • Step 7: Remove now-empty directories
rm -rf docs/superpowers
rm -rf docs/offline-knowledge
rm -f docs/implementation-status-2026-05-28.md
  • Step 8: Commit
git add -A
git commit -m "refactor: move development docs to dev-docs/ directory"

Task 9: Add Git Submodule and Remove Original Docs

Files:

  • Modify: .gitmodules (created by git submodule add)
  • Remove: docs/ directory contents (replaced by submodule)

Note: This task runs in the main chanora code repo.

  • Step 1: Remove original docs/ contents (keeping the directory)
# Back up any remaining files first
ls docs/
# Remove everything except what was already moved
rm -rf docs/architecture docs/governance docs/i18n docs/implementation-status-2026-05-28.md docs/legal docs/material3-guideline.md docs/offline-knowledge docs/privacy docs/references docs/release docs/requirements docs/security docs/srs.md docs/superpowers docs/sysdes.md docs/sysrs.md docs/ui-ux docs/verification
  • Step 2: Verify docs/ is empty
ls -la docs/

Expected: Empty directory (or only hidden files like .gitkeep).

  • Step 3: Add chanora-docs as submodule
git submodule add git@github.com:EdisonJwa/chanora-docs.git docs

Expected: Creates .gitmodules file and docs/ directory with submodule content.

  • Step 4: Verify submodule is working
ls docs/

Expected: Contents of the chanora-docs repo (mkdocs.yml, docs/, plugins/, etc.).

  • Step 5: Commit
git add .gitmodules docs
git commit -m "chore: add chanora-docs as git submodule at docs/"

Task 10: Write AGENTS.md and Update Cross-References

Files:

  • Create: AGENTS.md
  • Modify: README.md (update doc path references)
  • Create: dev-docs/impl-mapping.md

Note: This task runs in the main chanora code repo.

  • Step 1: Write AGENTS.md
# AGENTS.md — Chanora Project Conventions

## Project Overview

Chanora is a cross-platform voice client (Flutter + Rust) targeting TeamSpeak-compatible servers. The project follows ASPICE engineering processes with full traceability from system requirements through verification.

## Repository Structure

chanora/ ← Code repo (this one) ├── docs/ → chanora-docs ← Git submodule: ASPICE docs, doc site source ├── dev-docs/ ← Local-only development docs │ ├── superpowers/ ← AI agent specs and plans │ │ ├── specs/ ← Feature/design specs (active) │ │ └── plans/ ← Implementation plans (active) │ │ └── _archived/ ← Completed plans │ ├── offline-knowledge/ ← Doc maintenance tools, link coverage │ ├── implementation-status-* ← Code state snapshots │ └── release/ios-build.md ← Operational build instructions ├── apps/chanora_flutter/ ← Flutter application ├── core/chanora_core/ ← Rust core API + orchestration ├── crates/ ← Rust crates (protocol, audio, state, etc.) └── dev-docs/impl-mapping.md ← SAD component → source file mapping


## Documentation Two-Repo Model

**`docs/` is a git submodule** pointing to the separate `chanora-docs` repository. It is NOT a local directory you can freely create files in.

### What lives where

| Content | Location | Reason |
|---|---|---|
| SysRS, SysDes, SRS, SAD, SDD | `docs/` (submodule) | ASPICE baselines, served on doc site |
| Verification plans (SWE.4/5/6, SYS.4) | `docs/` (submodule) | ASPICE verification evidence |
| Governance, traceability, decision register | `docs/` (submodule) | ASPICE governance |
| Security, privacy, legal | `docs/` (submodule) | Stakeholder-facing |
| UI/UX guidelines, i18n architecture | `docs/` (submodule) | Design references |
| Feature specs and implementation plans | `dev-docs/superpowers/` | Code-coupled, agent working files |
| Link coverage, doc quality analysis | `dev-docs/offline-knowledge/` | Maintenance tools |
| Implementation status snapshots | `dev-docs/` | Code state tracking |
| Source file path references | `dev-docs/impl-mapping.md` | Developer convenience, not ASPICE |

### Rules for agents

1. **Never create or edit files in `docs/`** without understanding it's a submodule. Changes there require committing in the `chanora-docs` repo first, then updating the submodule pointer in this repo.

2. **ASPICE documents do not contain code file paths.** ASPICE traces requirement IDs (e.g., `SysRS-233`, `SRS-045`, `SDD-MOD-009`), not source file paths. If you need to map a component to its source, use or update `dev-docs/impl-mapping.md`.

3. **Specs and plans go in `dev-docs/superpowers/`.** Follow the naming convention: `YYYY-MM-DD-<topic>-design.md` for specs, `YYYY-MM-DD-<topic>.md` for plans.

4. **Completed plans move to `_archived/`.** Once a plan is fully implemented and verified, move it to `dev-docs/superpowers/plans/_archived/`.

## ASPICE Traceability Chain

```text
SysRS → SysDes → SRS → SAD (SWE.2) → SDD (SWE.3) → Verification
                                           ↓              ↓
                                       SWE.4 (unit)    SWE.4/5/6/SYS.4
  • Requirement IDs are the traceability mechanism, not file paths.
  • Every downstream document must reference upstream IDs it traces from.
  • Verification plans map to their upstream design/requirements level:
    • SYS.4 ← SysDes, SysRS
    • SWE.5 ← SAD (SWE.2)
    • SWE.4 ← SDD (SWE.3)
    • SWE.6 ← SRS

Code Architecture

Component Location Responsibility
Flutter app shell apps/chanora_flutter/ UI, Material 3, navigation, localization
Rust core core/chanora_core/ Session orchestration, bridge events
Protocol adapter crates/chanora_protocol/ TeamSpeak protocol via tsclientlib
State sync crates/chanora_state/ Snapshots, deltas, reducers
Audio subsystem crates/chanora_audio/ Capture, DSP, Opus, PTT
Storage crates/chanora_storage/ Bookmarks, identity, encryption
Diagnostics crates/chanora_diagnostics/ Redaction, logs, export
Resolver crates/chanora_resolver/ SRV/TSDNS/DNS resolution
Prefetch crates/chanora_prefetch/ Resolution warming, TTL cache
Bridge crates/chanora_bridge/ Flutter/Rust typed DTO boundary
Cache crates/chanora_cache/ Avatar/icon blob cache

Coding Conventions

  • Rust: Follow workspace Cargo.toml structure. Run cargo check, cargo clippy, cargo test before committing.
  • Flutter: Run flutter analyze, flutter test before committing.
  • No code comments unless explicitly requested.
  • Git commits: Follow convention in docs/governance/git-commit-message-convention.md (accessible via submodule).
  • Bridge boundary: Flutter must not directly depend on protocol-library internals. All cross-boundary communication goes through chanora_bridge typed DTOs.

Verification Commands

cargo check && cargo clippy && cargo test
cd apps/chanora_flutter && flutter analyze && flutter test

Important References

  • Traceability matrix: docs/governance/traceability-matrix.md
  • Decision register: docs/governance/product-decision-register.md
  • Security guidelines: docs/security/security-privacy-legal-guideline.md
  • Release readiness: docs/release/release-readiness-go-nogo-record.md

- [ ] **Step 2: Create `dev-docs/impl-mapping.md`**

```markdown
# SAD Component → Source File Mapping

**Purpose:** Developer convenience mapping from ASPICE architecture components to source file locations. This is NOT an ASPICE document — it's a lookup for developers.

## Component Mapping

| SAD Component | Source Location |
|---|---|
| Flutter app shell | `apps/chanora_flutter/lib/main.dart`, services, widgets |
| Flutter service layer | `apps/chanora_flutter/lib/services/` |
| Flutter widget layer | `apps/chanora_flutter/lib/widgets/` |
| Bridge layer | `crates/chanora_bridge/src/api.rs`, `apps/chanora_flutter/lib/src/rust/` |
| Rust core | `core/chanora_core/src/lib.rs`, `events.rs`, `network_diagnostics.rs`, `ptt.rs` |
| Protocol adapter | `crates/chanora_protocol/src/` |
| State sync | `crates/chanora_state/src/lib.rs`, `channel_join.rs` |
| Audio subsystem | `crates/chanora_audio/src/` |
| Storage | `crates/chanora_storage/src/lib.rs` |
| Diagnostics | `crates/chanora_diagnostics/src/lib.rs` |
| Resolution and prefetch | `crates/chanora_resolver/src/lib.rs`, `crates/chanora_prefetch/src/lib.rs`, `prefetch_debouncer.dart` |
| Build and release hooks | `.github/workflows/`, `tools/`, platform project files |

## SDD Module Mapping

| SDD Module | Source Location |
|---|---|
| SDD-MOD-001 Flutter app bootstrap | `apps/chanora_flutter/lib/services/app_bootstrap.dart`, `main.dart` |
| SDD-MOD-002 Connect UI | `apps/chanora_flutter/lib/widgets/connect_widgets.dart` |
| SDD-MOD-003 Snapshot and channel UI | `snapshot_view.dart`, `snapshot_state_mapper.dart`, `channel_spacer.dart` |
| SDD-MOD-004 Chat UI | `chat_views.dart`, `bbcode_text.dart` |
| SDD-MOD-005 Voice UI | `voice_bar.dart`, `voice_compact.dart`, `voice_settings*.dart`, `voice_level_meter.dart`, `ptt_capability_badge.dart` |
| SDD-MOD-006 Platform services | `android_permissions_service.dart`, `ios_permissions_service.dart`, `audio_lifecycle_service.dart`, `back_intent_*`, `link_trust_service.dart` |
| SDD-MOD-007 Bridge API | `crates/chanora_bridge/src/api.rs`, generated Dart/Rust bridge files |
| SDD-MOD-008 Rust core supervisor | `core/chanora_core/src/lib.rs`, `events.rs`, `network_diagnostics.rs`, `ptt.rs` |
| SDD-MOD-009 Protocol adapter | `crates/chanora_protocol/src/` |
| SDD-MOD-010 State sync | `crates/chanora_state/src/lib.rs`, `channel_join.rs` |
| SDD-MOD-011 Audio subsystem | `crates/chanora_audio/src/` |
| SDD-MOD-012 Storage | `crates/chanora_storage/src/lib.rs` |
| SDD-MOD-013 Diagnostics | `crates/chanora_diagnostics/src/lib.rs` |
| SDD-MOD-014 Resolution and prefetch | `crates/chanora_resolver/src/lib.rs`, `crates/chanora_prefetch/src/lib.rs`, `prefetch_debouncer.dart` |
| SDD-MOD-015 Build and release hooks | `.github/workflows/`, `tools/`, platform project files |
  • Step 3: Update README.md doc path references

Replace any remaining references to old docs/ paths (like docs/superpowers/) with dev-docs/superpowers/. Use grep to find all references:

grep -n "docs/superpowers\|docs/implementation-status\|docs/offline-knowledge" README.md

Update any found references to point to dev-docs/.

  • Step 4: Commit
git add AGENTS.md dev-docs/impl-mapping.md README.md
git commit -m "docs: add AGENTS.md and impl-mapping.md, update README references"

Task 11: Update .gitignore and Verify Final State

Files:

  • Modify: .gitignore

  • Step 1: Verify submodule status

git submodule status

Expected: Shows chanora-docs commit hash.

  • Step 2: Verify docs/ contains submodule content
ls docs/mkdocs.yml

Expected: File exists.

  • Step 3: Verify dev-docs/ structure
find dev-docs -type f -name '*.md' | sort

Expected: All local-only docs present.

  • Step 4: Verify no stale docs/ files remain outside submodule
git status

Expected: No untracked files in docs/ outside the submodule pointer.

  • Step 5: Final commit if needed
git add -A
git commit -m "chore: finalize documentation repo restructure"