跳到主要内容

Pattern E v1.0.1 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: Migrate wiki-portal from Pattern A (per-product docs/wiki/ dirs in code repos + cross-repo PAT dispatch) to Pattern E (5 independent public docs repos + submodules + GitHub App dispatch), in 4.5 days across 5 phases / 12 commits, with full rollback at each phase.

Architecture: Each product (attune / attune-pro / attune-enterprise / pluginhub / kvm) gets its own *-docs public GH repo containing the wiki/ content. wiki-portal references all 5 as submodules under docs/<project>/. Cross-repo dispatch from docs repo → wiki-portal uses GitHub App installation tokens (no PAT expiry). Docusaurus uses 5 plugin-content-docs instances, one per submodule, with paths docs/<project>/wiki.

Tech Stack:

  • Docusaurus 3.x + TypeScript config + Node 20
  • Git submodules + git filter-repo for history extraction
  • GitHub Actions + repository_dispatch event + actions/create-github-app-token@v1
  • GitHub App with permissions contents:read + actions:write
  • Secrets via org-level (transitional) → GitHub App (final)

Spec Reference

  • Spec: /data/company/cloud/wiki-web/docs/superpowers/specs/2026-05-25-pattern-e-independent-docs-repo.md (commit 02273c9, 718 lines, 11 sections complete)
  • Branch: chore/wiki-portal-rebrand
  • Current state: Phase A docs/ already deleted in working tree (uncommitted) per commit 97b6344; external/attune, external/attune-enterprise, external/attune-pluginhub, external/kvm already cloned as plain dirs (not yet submodules).

Repo Inventory

5 docs repos to create (all public, all under qiurui144):

docs reporeplaces wiki-web pathmount in wiki-portal
qiurui144/attune-docsdocs/attune/ (16 files) + docs/getting-started/ + docs/hardware/ + docs/software/ + docs/download.mddocs/attune/ (submodule, plugin id attune)
qiurui144/attune-pro-docs(new, empty initially — Pro plugin docs migrated later from attune-pro repo)docs/attune-pro/
qiurui144/attune-enterprise-docsdocs/attune-enterprise/ (7 files, ex-lawcontrol)docs/attune-enterprise/
qiurui144/attune-pluginhub-docsdocs/pluginhub/ (2 files)docs/pluginhub/
qiurui144/kvm-docs(new, KVM user docs — sourced from external/kvm/ if applicable, otherwise empty stub)docs/kvm/

Plus 1 template repo:

  • qiurui144/docs-template — minimum scaffold (README.md, LICENSE, .github/workflows/dispatch.yml, wiki/index.md)

File Structure (target state after migration)

qiurui144/wiki-portal (current cloud/wiki-web)
├── .gitmodules ★ NEW
├── docs/
│ ├── attune/ → submodule → qiurui144/attune-docs (mount wiki/)
│ ├── attune-pro/ → submodule → qiurui144/attune-pro-docs
│ ├── attune-enterprise/ → submodule → qiurui144/attune-enterprise-docs
│ ├── pluginhub/ → submodule → qiurui144/attune-pluginhub-docs
│ └── kvm/ → submodule → qiurui144/kvm-docs
├── sidebars/ ★ NEW (5 files, was 1 sidebars.ts)
│ ├── attune.ts
│ ├── attune-pro.ts
│ ├── attune-enterprise.ts
│ ├── pluginhub.ts
│ └── kvm.ts
├── docusaurus.config.ts ★ MODIFY (5 plugin-content-docs instances)
└── .github/workflows/
├── wiki-deploy.yml ★ MODIFY (add submodules: recursive + on: repository_dispatch)
└── wiki-content-update.yml ★ NEW (case-by-case submodule pin + push back)

qiurui144/attune-docs (and 4 siblings)
├── README.md
├── LICENSE (CC-BY-4.0)
├── .github/workflows/dispatch.yml (uses GitHub App token)
└── wiki/ (Docusaurus reads this)
├── index.md
└── <product-specific content>

Credential Strategy

Per spec §11 R9 + R1: GitHub App is the chosen final form (no PAT expiry). Phase E1 sets up the App. No org-PAT transition.

GitHub App spec:

  • Name: attune-wiki-dispatch
  • Owner: qiurui144 (personal account, future migrate to org)
  • Permissions: Repository contents: Read + Actions: Write
  • Subscribed events: none (only used for outbound API calls)
  • Installed on: 5 docs repos + wiki-portal repo
  • Used via: actions/create-github-app-token@v1 inside each docs repo's dispatch.yml
  • Secrets stored in each docs repo: WIKI_APP_ID, WIKI_APP_PRIVATE_KEY

Phase Timeline (4.5 days, 12 commits)

PhaseDayCommitsDeliverable
E15/27C1, C25 docs repos + template + GitHub App registered + installed
E25/28C3-C7History extraction (5 × git filter-repo) + push to docs repos
E35/29C8, C9wiki-portal .gitmodules + Docusaurus config + sidebars split + dispatch handler
E45/30 AMC10, C11Delete old Pattern A artifacts (per-repo wiki-dispatch.yml, PAT secrets, old docs/<product>/ direct markdown in wiki-portal)
E55/30 PMC12Monitoring + docs-template README + KVM 5-min onboarding verification

Phase E1 — Infrastructure setup (Day 1 = 5/27)

Phase output: 5 empty docs repos + 1 template repo + GitHub App registered & installed on all 6 + secrets stored.

User action gate: All GH repo creation + GitHub App registration is user-driven via GH web UI. AI prepares scripts but does not invoke gh repo create or App creation API per task red lines.

Task 1: Prepare GitHub App registration checklist

Files:

  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/github-app-setup.md

  • Step 1: Write App registration checklist

# attune-wiki-dispatch GitHub App — setup checklist

## 1. Register the App
Navigate to: https://github.com/settings/apps/new

Fill:
- GitHub App name: attune-wiki-dispatch
- Homepage URL: https://wiki.engi-stack.com
- Callback URL: (leave blank)
- Webhook → Active: UNCHECK (we use polling, not webhooks)
- Repository permissions:
- Contents: Read-only
- Actions: Read and write
- Metadata: Read-only (auto-included)
- Organization permissions: none
- User permissions: none
- Subscribe to events: none
- Where can this App be installed: Only on this account

Click "Create GitHub App".

## 2. Generate private key
On the App's page → "Private keys" section → "Generate a private key"
Downloads .pem file. Save to a secure password manager.

Record:
- App ID: (shown at top of App page, e.g., 123456)
- Private key contents: -----BEGIN RSA PRIVATE KEY----- ...

## 3. Install on the 6 repos
On App page → "Install App" sidebar → choose qiurui144 → "Only select repositories":
- qiurui144/wiki-portal
- qiurui144/attune-docs
- qiurui144/attune-pro-docs
- qiurui144/attune-enterprise-docs
- qiurui144/attune-pluginhub-docs
- qiurui144/kvm-docs
- qiurui144/docs-template

Click "Install".

## 4. Store secrets in each docs repo
For each of attune-docs, attune-pro-docs, attune-enterprise-docs, attune-pluginhub-docs, kvm-docs, docs-template:

gh secret set WIKI_APP_ID --repo qiurui144/<repo> --body "<App ID>"
gh secret set WIKI_APP_PRIVATE_KEY --repo qiurui144/<repo> < /path/to/private-key.pem

## 5. Sanity verify
gh api /repos/qiurui144/attune-docs/actions/secrets | jq '.secrets[].name'
Expected: WIKI_APP_ID, WIKI_APP_PRIVATE_KEY
  • Step 2: Commit C1 — checklist + reserve plan directory
cd /data/company/cloud/wiki-web
git add docs/superpowers/plans/2026-05-25-pattern-e-impl.md \
docs/superpowers/plans/pattern-e/github-app-setup.md
git commit -m "plan(pattern-e): implementation plan + GitHub App setup checklist"

Task 2: Prepare docs-template content

Files:

  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/README.md
  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/LICENSE
  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/.github/workflows/dispatch.yml
  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/wiki/index.md

These files live in the wiki-portal repo as a template source. User will manually gh repo create --template from the eventual qiurui144/docs-template repo, which is populated via gh repo create qiurui144/docs-template --public then pushing these files.

  • Step 1: Write template README
# PROJECT Docs

User-facing wiki content for **PROJECT**. Rendered at:
https://wiki.engi-stack.com/PROJECT/

## How to contribute

1. Edit any file under `wiki/`.
2. Open a PR against `main`.
3. After PR merges, `.github/workflows/dispatch.yml` notifies wiki-portal automatically and the site rebuilds within ~5 min.

## License

Content is licensed CC-BY-4.0 (see `LICENSE`).

## Repository structure

- `wiki/` — actual documentation, rendered as Docusaurus pages
- `.github/workflows/dispatch.yml` — notifies wiki-portal on push to main
- `README.md` / `LICENSE` — repo metadata (not rendered as wiki pages)

## Replacement instructions (template usage)

After `gh repo create --template qiurui144/docs-template`:

\`\`\`bash
sed -i 's/PROJECT/<your-project>/g' README.md wiki/index.md
git add . && git commit -m "init: <project> wiki" && git push
\`\`\`

Then ask wiki-portal owner to add submodule + sidebar entry (see wiki-portal/docs/onboarding.md).
  • Step 2: Write template LICENSE (CC-BY-4.0 short form)
Creative Commons Attribution 4.0 International (CC-BY-4.0)

Copyright (c) <YEAR> <COPYRIGHT HOLDER>

Full text: https://creativecommons.org/licenses/by/4.0/legalcode
  • Step 3: Write template dispatch.yml
name: Notify wiki-portal

on:
push:
branches: [main]
workflow_dispatch:

jobs:
notify:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.WIKI_APP_ID }}
private-key: ${{ secrets.WIKI_APP_PRIVATE_KEY }}
owner: qiurui144
repositories: wiki-portal

- name: Dispatch wiki-content-update
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ steps.app-token.outputs.token }}
repository: qiurui144/wiki-portal
event-type: wiki-content-update
client-payload: |
{
"source_repo": "${{ github.repository }}",
"source_sha": "${{ github.sha }}",
"source_ref": "${{ github.ref }}",
"triggered_at": "${{ github.event.head_commit.timestamp }}"
}
  • Step 4: Write template wiki/index.md
---
sidebar_position: 1
---

# PROJECT

Welcome to PROJECT documentation.

Replace this file with your actual landing page.
  • Step 5: Commit C2 — docs-template scaffold
cd /data/company/cloud/wiki-web
git add docs/superpowers/plans/pattern-e/template/
git commit -m "plan(pattern-e): docs-template scaffold (README + LICENSE + dispatch.yml + index.md)"

Task 3: User action — create 5 docs repos + template repo

This is user-action only. AI must NOT invoke gh repo create per task red lines.

  • Step 1: User runs the following commands (after reviewing E1 commits)
# Run these commands manually — do NOT auto-execute
cd /tmp
mkdir docs-template-bootstrap && cd docs-template-bootstrap

# Copy template content from wiki-portal plan directory
cp -r /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/. .
git init -b main
git add .
git commit -m "init: docs-template scaffold"

# Create the template repo on GH
gh repo create qiurui144/docs-template --public --source=. --push --description "Template for project docs repos consumed by wiki-portal"

# Mark as template
gh repo edit qiurui144/docs-template --template

# Create 5 product docs repos from the template
for repo in attune-docs attune-pro-docs attune-enterprise-docs attune-pluginhub-docs kvm-docs; do
gh repo create "qiurui144/$repo" \
--template qiurui144/docs-template \
--public \
--description "User-facing docs for ${repo%-docs}"
done
  • Step 2: User completes GitHub App registration

Follow docs/superpowers/plans/pattern-e/github-app-setup.md steps 1-5.

  • Step 3: Verification
# AI may run these read-only checks (no creation)
gh repo list qiurui144 --limit 50 | grep -E '^(qiurui144/)?(attune-docs|attune-pro-docs|attune-enterprise-docs|attune-pluginhub-docs|kvm-docs|docs-template)\s'
# Expected: 6 lines

# Each should have secrets configured
for r in attune-docs attune-pro-docs attune-enterprise-docs attune-pluginhub-docs kvm-docs; do
echo "=== $r ==="
gh api /repos/qiurui144/$r/actions/secrets --jq '.secrets[].name'
done
# Expected: each prints WIKI_APP_ID and WIKI_APP_PRIVATE_KEY

Phase E1 gate: 6 repos exist, GitHub App installed on all 6 + wiki-portal, secrets present on 5 product docs repos. Do not proceed to E2 until verified.


Phase E2 — History extraction (Day 2 = 5/28)

Phase output: 5 product docs repos populated with content + commit history extracted via git filter-repo from wiki-web.

Task 4: Install git-filter-repo and prepare backup

Files: none (toolchain prep + backup of wiki-web repo)

  • Step 1: Verify git-filter-repo is installed
git filter-repo --version 2>/dev/null || pip install --user git-filter-repo
git filter-repo --version
# Expected: git filter-repo 2.x.x
  • Step 2: Snapshot wiki-web before any filter-repo work
cd /data/company/cloud
cp -a wiki-web wiki-web.pre-pattern-e-backup
echo "wiki-web.pre-pattern-e-backup/" >> /data/company/cloud/.gitignore 2>/dev/null || true
ls -la wiki-web.pre-pattern-e-backup/.git | head -3
# Expected: directory exists with .git/HEAD
  • Step 3: Tag the pre-migration state
cd /data/company/cloud/wiki-web
git tag pre-pattern-e-migration HEAD
git push origin pre-pattern-e-migration
# Allows rollback to known-good state

Task 5: Extract attune-docs content (C3)

Files:

  • Source paths in wiki-web: docs/attune/, docs/getting-started/, docs/hardware/, docs/software/, docs/download.md, docs/index.md

  • Target repo: qiurui144/attune-docs

  • Step 1: Create working clone for filter-repo (filter-repo destroys history; use throwaway clone)

cd /tmp
rm -rf attune-docs-extract
git clone /data/company/cloud/wiki-web attune-docs-extract
cd attune-docs-extract
git remote remove origin # so we don't accidentally push to wiki-web
  • Step 2: Run filter-repo to keep only attune-related paths and move them under wiki/
cd /tmp/attune-docs-extract
git filter-repo \
--path docs/attune/ \
--path docs/getting-started/ \
--path docs/hardware/ \
--path docs/software/ \
--path docs/download.md \
--path docs/index.md \
--path-rename docs/attune/:wiki/ \
--path-rename docs/getting-started/:wiki/getting-started/ \
--path-rename docs/hardware/:wiki/hardware/ \
--path-rename docs/software/:wiki/software/ \
--path-rename docs/download.md:wiki/download.md \
--path-rename docs/index.md:wiki/index.md
  • Step 3: Verify file count and history
find wiki -type f -name "*.md" | sort | head -20
git log --oneline | wc -l
# Expected: ~10-20 markdown files in wiki/, plus commit history
git log --follow wiki/index.md | head
# Expected: history including original docs/attune/index.md commits
  • Step 4: Add README + LICENSE + dispatch.yml from template
cd /tmp/attune-docs-extract
# Copy template files (but adjust PROJECT placeholder)
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/README.md ./
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/LICENSE ./
mkdir -p .github/workflows
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/.github/workflows/dispatch.yml .github/workflows/
sed -i 's/PROJECT/attune/g' README.md
git add README.md LICENSE .github/workflows/dispatch.yml
git commit -m "init: attune-docs scaffold (README + LICENSE + dispatch.yml)"
  • Step 5: Secret scan before push (R6 mitigation)
cd /tmp/attune-docs-extract
# Scan for internal keywords that should not appear in public docs
grep -rn --include="*.md" -E '(INTERNAL|WIP|TODO[:-]|FIXME|XXX-internal|attune-pro-private|<secret>|<password>|<api-key>)' wiki/ || echo "No leaks found"
# If output present: STOP, edit offending files, recommit (amend last "init" commit)
  • Step 6: Push to qiurui144/attune-docs (user action)
# User runs this — AI should not push to repos outside cloud/* per global push restrictions
cd /tmp/attune-docs-extract
git remote add origin https://github.com/qiurui144/attune-docs.git
git branch -M main
git push -u origin main --force-with-lease
# --force-with-lease because the template's initial commit will be replaced by history
  • Step 7: Verify dispatch.yml triggers correctly
# After push, GH Actions should fire one wiki-content-update event
gh run list --repo qiurui144/attune-docs --limit 1
# Expected: 1 run with conclusion "success" (within 30s)
gh run list --repo qiurui144/wiki-portal --workflow wiki-content-update.yml --limit 1
# Note: wiki-portal handler does NOT exist yet — this run will appear in E3.
# At this stage, dispatch.yml will succeed in calling repository_dispatch but
# wiki-portal will silently receive an event without a handler (no error, no run).
  • Step 8: Commit C3 — record extraction in wiki-portal plan dir
cd /data/company/cloud/wiki-web
mkdir -p docs/superpowers/plans/pattern-e/migration-log
cat > docs/superpowers/plans/pattern-e/migration-log/03-attune-docs.md <<'EOF'
# C3: attune-docs extraction log

- Source: wiki-web HEAD (sha: <FILL>)
- Filter paths: docs/attune/, docs/getting-started/, docs/hardware/, docs/software/, docs/download.md, docs/index.md
- Renamed under: wiki/
- Files extracted: <FILL> markdown files
- Commits preserved: <FILL>
- Secret scan: PASS
- Pushed to: qiurui144/attune-docs main @ <FILL sha>
- Dispatch test: PASS (workflow run id <FILL>)
EOF
# User to fill <FILL> after extraction completes
git add docs/superpowers/plans/pattern-e/migration-log/03-attune-docs.md
git commit -m "plan(pattern-e): record C3 attune-docs migration"

Task 6: Extract attune-pro-docs content (C4)

Note: attune-pro currently has docs in the attune-pro private repo (not wiki-web). For Phase E this task creates an empty scaffold in attune-pro-docs; the real migration of attune-pro plugin docs is deferred to v0.2 (post-v1.0.1 release).

Files: template scaffold only

  • Step 1: Verify attune-pro-docs exists and has template content
gh repo view qiurui144/attune-pro-docs --json defaultBranchRef,description
# Expected: defaultBranchRef.name = "main"
  • Step 2: Customize template's README/index.md for attune-pro
cd /tmp
git clone https://github.com/qiurui144/attune-pro-docs.git
cd attune-pro-docs
sed -i 's/PROJECT/attune-pro/g' README.md wiki/index.md
cat > wiki/index.md <<'EOF'
---
sidebar_position: 1
---

# Attune Pro

Pro-tier plugin documentation. Content migration from `attune-pro/docs/wiki/` is planned for v0.2.

This page is a placeholder for the wiki-portal submodule mount path.
EOF
git add README.md wiki/index.md
git commit -m "init: attune-pro-docs landing page (placeholder for v0.2 migration)"
git push
  • Step 3: Commit C4 — record placeholder setup
cd /data/company/cloud/wiki-web
cat > docs/superpowers/plans/pattern-e/migration-log/04-attune-pro-docs.md <<'EOF'
# C4: attune-pro-docs scaffold

- Status: Placeholder only (no history migration)
- Reason: attune-pro is a separate private repo; migration deferred to v0.2
- Pushed to: qiurui144/attune-pro-docs main @ <FILL sha>
EOF
git add docs/superpowers/plans/pattern-e/migration-log/04-attune-pro-docs.md
git commit -m "plan(pattern-e): record C4 attune-pro-docs placeholder"

Task 7: Extract attune-enterprise-docs content (C5)

Files:

  • Source paths in wiki-web: docs/attune-enterprise/ (7 files)

  • Target repo: qiurui144/attune-enterprise-docs

  • Step 1: Working clone + filter-repo

cd /tmp
rm -rf attune-enterprise-docs-extract
git clone /data/company/cloud/wiki-web attune-enterprise-docs-extract
cd attune-enterprise-docs-extract
git remote remove origin

git filter-repo \
--path docs/attune-enterprise/ \
--path-rename docs/attune-enterprise/:wiki/
  • Step 2: Verify file structure
find wiki -type f -name "*.md" | sort
# Expected (per spec §4 + current sidebars.ts):
# wiki/index.md
# wiki/guide/ai-chat.md
# wiki/guide/documents.md
# wiki/guide/feishu-bot.md
# wiki/guide/rpa.md
# wiki/guide/skills.md
# wiki/admin/index.md
  • Step 3: Add template scaffolding files
cd /tmp/attune-enterprise-docs-extract
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/README.md ./
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/LICENSE ./
mkdir -p .github/workflows
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/.github/workflows/dispatch.yml .github/workflows/
sed -i 's/PROJECT/attune-enterprise/g' README.md
git add README.md LICENSE .github/workflows/dispatch.yml
git commit -m "init: attune-enterprise-docs scaffold"
  • Step 4: Secret scan
grep -rn --include="*.md" -E '(INTERNAL|WIP|TODO[:-]|FIXME|<secret>|<password>|<api-key>|feishu.*token|webhook.*secret)' wiki/ || echo "No leaks found"
# Note: feishu-bot.md may legitimately reference webhook concepts.
# Manual review required if any matches.
  • Step 5: User pushes
cd /tmp/attune-enterprise-docs-extract
git remote add origin https://github.com/qiurui144/attune-enterprise-docs.git
git branch -M main
git push -u origin main --force-with-lease
  • Step 6: Commit C5 migration log
cd /data/company/cloud/wiki-web
cat > docs/superpowers/plans/pattern-e/migration-log/05-attune-enterprise-docs.md <<'EOF'
# C5: attune-enterprise-docs extraction log

- Source: wiki-web HEAD (sha: <FILL>)
- Filter paths: docs/attune-enterprise/
- Renamed under: wiki/
- Files extracted: 7 markdown
- Commits preserved: <FILL>
- Secret scan: PASS
- Pushed to: qiurui144/attune-enterprise-docs main @ <FILL>
EOF
git add docs/superpowers/plans/pattern-e/migration-log/05-attune-enterprise-docs.md
git commit -m "plan(pattern-e): record C5 attune-enterprise-docs migration"

Task 8: Extract attune-pluginhub-docs content (C6)

Files:

  • Source paths in wiki-web: docs/pluginhub/ (2 files)

  • Target repo: qiurui144/attune-pluginhub-docs

  • Step 1: Working clone + filter-repo

cd /tmp
rm -rf attune-pluginhub-docs-extract
git clone /data/company/cloud/wiki-web attune-pluginhub-docs-extract
cd attune-pluginhub-docs-extract
git remote remove origin

git filter-repo \
--path docs/pluginhub/ \
--path-rename docs/pluginhub/:wiki/
  • Step 2: Verify
find wiki -type f -name "*.md" | sort
# Expected:
# wiki/index.md
# wiki/attune-integration.md
  • Step 3: Add scaffolding
cd /tmp/attune-pluginhub-docs-extract
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/README.md ./
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/LICENSE ./
mkdir -p .github/workflows
cp /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/template/.github/workflows/dispatch.yml .github/workflows/
sed -i 's/PROJECT/attune-pluginhub/g' README.md
git add README.md LICENSE .github/workflows/dispatch.yml
git commit -m "init: attune-pluginhub-docs scaffold"
  • Step 4: Secret scan
grep -rn --include="*.md" -E '(INTERNAL|WIP|TODO[:-]|FIXME|<secret>|<password>|<api-key>)' wiki/ || echo "No leaks found"
  • Step 5: User pushes
cd /tmp/attune-pluginhub-docs-extract
git remote add origin https://github.com/qiurui144/attune-pluginhub-docs.git
git branch -M main
git push -u origin main --force-with-lease
  • Step 6: Commit C6 migration log
cd /data/company/cloud/wiki-web
cat > docs/superpowers/plans/pattern-e/migration-log/06-attune-pluginhub-docs.md <<'EOF'
# C6: attune-pluginhub-docs extraction log
- Files extracted: 2 (index.md + attune-integration.md)
- Pushed to: qiurui144/attune-pluginhub-docs main @ <FILL>
EOF
git add docs/superpowers/plans/pattern-e/migration-log/06-attune-pluginhub-docs.md
git commit -m "plan(pattern-e): record C6 attune-pluginhub-docs migration"

Task 9: Set up kvm-docs scaffold (C7)

Files:

  • Source: cloud/wiki-web/external/kvm/ plain dir (not in git history of wiki-web; sourced from KVM repo)
  • Target repo: qiurui144/kvm-docs

Note: KVM docs do NOT exist in wiki-web's git history (per current state — external/kvm/ is a working-tree-only clone, not committed). Treat this as scaffold-only; if KVM owner wants real content, they can git filter-repo from the KVM repo itself in v0.2.

  • Step 1: Customize template content
cd /tmp
git clone https://github.com/qiurui144/kvm-docs.git
cd kvm-docs
sed -i 's/PROJECT/KVM/g' README.md wiki/index.md
cat > wiki/index.md <<'EOF'
---
sidebar_position: 1
---

# KVM 一体机

KVM 一体机用户文档。

KVM 项目维护者可通过本仓 PR 添加内容,push 到 main 后 wiki-portal 自动同步。
EOF
git add README.md wiki/index.md
git commit -m "init: kvm-docs landing page"
git push
  • Step 2: Commit C7 migration log
cd /data/company/cloud/wiki-web
cat > docs/superpowers/plans/pattern-e/migration-log/07-kvm-docs.md <<'EOF'
# C7: kvm-docs scaffold

- Status: Scaffold only (no history migration — KVM docs were not in wiki-web git history)
- KVM project owner can populate content via PRs to the new repo
- Pushed to: qiurui144/kvm-docs main @ <FILL>
EOF
git add docs/superpowers/plans/pattern-e/migration-log/07-kvm-docs.md
git commit -m "plan(pattern-e): record C7 kvm-docs scaffold"

Phase E2 gate: All 5 docs repos accessible at https://github.com/qiurui144/<repo> with content. Each has a main branch with wiki/index.md and .github/workflows/dispatch.yml. Manual npm run start not required at this stage (verified in E3).


Phase E3 — wiki-portal restructure (Day 3 = 5/29)

Phase output: wiki-portal .gitmodules references 5 docs repos as submodules, Docusaurus config uses 5 plugin-content-docs instances, sidebars split into 5 files, wiki-content-update.yml handler in place.

All work in this phase happens on the chore/wiki-portal-rebrand branch already checked out.

Task 10: Add submodules + Docusaurus + sidebars (C8)

Files:

  • Create: .gitmodules

  • Modify: docusaurus.config.ts (add 5 plugin-content-docs instances)

  • Create: sidebars/attune.ts, sidebars/attune-pro.ts, sidebars/attune-enterprise.ts, sidebars/pluginhub.ts, sidebars/kvm.ts

  • Delete: sidebars.ts (replaced by 5 sidebars/*.ts files)

  • Step 1: Clean uncommitted state from current working tree

cd /data/company/cloud/wiki-web
git status --short
# Confirm: deleted docs/attune/* + docs/lawcontrol/* + docs/pluginhub/* (per commit 97b6344 already in HEAD)
# untracked external/, .bak files
# Either commit or stash before continuing.
# For this plan we COMMIT the deletions if not already committed:
git diff --stat HEAD
# If no diff, working tree matches HEAD = good.
  • Step 2: Remove the throwaway external/ dir (no longer needed; submodules will replace)
cd /data/company/cloud/wiki-web
echo "external/" >> .gitignore
git add .gitignore
# Don't rm external/ from disk — it's already gitignored; user can manually rm later.
  • Step 3: Add 5 submodules (one command each, separate to allow per-submodule rollback)
cd /data/company/cloud/wiki-web

git submodule add https://github.com/qiurui144/attune-docs.git docs/attune
git submodule add https://github.com/qiurui144/attune-pro-docs.git docs/attune-pro
git submodule add https://github.com/qiurui144/attune-enterprise-docs.git docs/attune-enterprise
git submodule add https://github.com/qiurui144/attune-pluginhub-docs.git docs/pluginhub
git submodule add https://github.com/qiurui144/kvm-docs.git docs/kvm

cat .gitmodules
# Expected: 5 [submodule "docs/<name>"] blocks
  • Step 4: Verify submodule checkout
ls docs/attune/wiki/ | head
ls docs/attune-enterprise/wiki/ | head
# Expected: index.md + subdirs visible
  • Step 5: Rewrite docusaurus.config.ts

Modify the existing config to remove the single-docs preset and add 5 plugin-content-docs instances:

import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';

const config: Config = {
title: 'Wiki Portal',
tagline: 'Multi-product documentation portal',
favicon: 'img/favicon.ico',

url: 'https://wiki.engi-stack.com',
baseUrl: '/',

onBrokenLinks: 'warn',
onBrokenAnchors: 'warn',
onBrokenMarkdownLinks: 'warn',

markdown: {format: 'detect'},

i18n: {
defaultLocale: 'zh',
locales: ['zh', 'en'],
localeConfigs: {
zh: {label: '简体中文'},
en: {label: 'English'},
},
},

presets: [
[
'classic',
{
docs: false, // disable default docs preset; we use 5 plugin instances instead
blog: false,
theme: {customCss: './src/css/custom.css'},
} satisfies Preset.Options,
],
],

plugins: [
[
'@docusaurus/plugin-content-docs',
{
id: 'attune',
path: 'docs/attune/wiki',
routeBasePath: 'attune',
sidebarPath: './sidebars/attune.ts',
},
],
[
'@docusaurus/plugin-content-docs',
{
id: 'attune-pro',
path: 'docs/attune-pro/wiki',
routeBasePath: 'attune-pro',
sidebarPath: './sidebars/attune-pro.ts',
},
],
[
'@docusaurus/plugin-content-docs',
{
id: 'attune-enterprise',
path: 'docs/attune-enterprise/wiki',
routeBasePath: 'attune-enterprise',
sidebarPath: './sidebars/attune-enterprise.ts',
},
],
[
'@docusaurus/plugin-content-docs',
{
id: 'pluginhub',
path: 'docs/pluginhub/wiki',
routeBasePath: 'pluginhub',
sidebarPath: './sidebars/pluginhub.ts',
},
],
[
'@docusaurus/plugin-content-docs',
{
id: 'kvm',
path: 'docs/kvm/wiki',
routeBasePath: 'kvm',
sidebarPath: './sidebars/kvm.ts',
},
],
],

themeConfig: {
navbar: {
title: 'Wiki Portal',
items: [
{to: '/attune', label: 'Attune', position: 'left'},
{to: '/attune-pro', label: 'Attune Pro', position: 'left'},
{to: '/attune-enterprise', label: 'Enterprise', position: 'left'},
{to: '/pluginhub', label: 'PluginHub', position: 'left'},
{to: '/kvm', label: 'KVM', position: 'left'},
{type: 'localeDropdown', position: 'right'},
],
},
footer: {
style: 'dark',
copyright: `© ${new Date().getFullYear()} Wiki Portal.`,
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
} satisfies Preset.ThemeConfig,
};

export default config;

Write this content to docusaurus.config.ts overwriting the existing file.

  • Step 6: Create sidebars/ directory with 5 sidebar files
mkdir -p sidebars

Write sidebars/attune.ts:

import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';

const sidebars: SidebarsConfig = {
attune: [
'index',
'quickstart',
'wizard',
'chat',
{
type: 'category',
label: '数据采集源',
items: [
'sources/index',
'sources/local-files',
'sources/webdav',
'sources/email',
'sources/rss',
],
},
'llm-setup',
'plugins',
'agents',
'architecture',
'privacy',
'benchmarks',
'faq',
{
type: 'category',
label: '硬件文档',
items: [
{
type: 'category',
label: '快速开始',
items: [
'getting-started/index',
'getting-started/install',
'getting-started/first-boot',
],
},
'hardware/specs',
'hardware/interfaces',
{
type: 'category',
label: '软件资源',
items: ['software/images', 'software/flash'],
},
],
},
'download',
],
};

export default sidebars;

Write sidebars/attune-pro.ts:

import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';

const sidebars: SidebarsConfig = {
attunePro: ['index'], // placeholder until v0.2 content migration
};

export default sidebars;

Write sidebars/attune-enterprise.ts:

import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';

const sidebars: SidebarsConfig = {
attuneEnterprise: [
'index',
{
type: 'category',
label: '用户指南',
items: [
'guide/ai-chat',
'guide/documents',
'guide/skills',
'guide/feishu-bot',
'guide/rpa',
],
},
'admin/index',
],
};

export default sidebars;

Write sidebars/pluginhub.ts:

import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';

const sidebars: SidebarsConfig = {
pluginhub: ['index', 'attune-integration'],
};

export default sidebars;

Write sidebars/kvm.ts:

import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';

const sidebars: SidebarsConfig = {
kvm: ['index'], // placeholder until KVM owner populates
};

export default sidebars;
  • Step 7: Delete old monolithic sidebars.ts
cd /data/company/cloud/wiki-web
git rm sidebars.ts
  • Step 8: Local build verification
cd /data/company/cloud/wiki-web
npm ci
npm run build
# Expected: build succeeds, build/ dir created
# Browse build/attune/index.html, build/attune-enterprise/index.html, etc., — should exist
ls build/attune/ | head
ls build/attune-enterprise/ | head
  • Step 9: Commit C8 — wiki-portal Pattern E core changes
cd /data/company/cloud/wiki-web
git add .gitmodules docs/attune docs/attune-pro docs/attune-enterprise docs/pluginhub docs/kvm \
docusaurus.config.ts sidebars/ .gitignore
git rm --cached sidebars.ts 2>/dev/null || true
git status --short
# Expected (excerpt):
# new file: .gitmodules
# new file: docs/attune (submodule gitlink)
# new file: docs/attune-pro (submodule gitlink)
# new file: docs/attune-enterprise (submodule gitlink)
# new file: docs/pluginhub (submodule gitlink)
# new file: docs/kvm (submodule gitlink)
# modified: docusaurus.config.ts
# new file: sidebars/attune.ts (+ 4 siblings)
# deleted: sidebars.ts
git commit -m "feat(wiki): Pattern E — 5 docs submodules + plugin-content-docs config"

Task 11: Add wiki-content-update.yml handler + extend wiki-deploy.yml (C9)

Files:

  • Create: .github/workflows/wiki-content-update.yml

  • Modify: .github/workflows/wiki-deploy.yml (add submodules: recursive to checkout)

  • Step 1: Modify wiki-deploy.yml to fetch submodules

In .github/workflows/wiki-deploy.yml, change the existing Checkout step from:

- name: Checkout
uses: actions/checkout@v4

to:

- name: Checkout (with submodules)
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

(Use Edit tool to replace exactly those 2 lines with 5.)

  • Step 2: Create wiki-content-update.yml
name: wiki-content-update

# Triggered by docs repos via repository_dispatch.
# Each docs repo's dispatch.yml uses a GitHub App token to call:
# POST /repos/qiurui144/wiki-portal/dispatches
# { "event_type": "wiki-content-update", "client_payload": {...} }
on:
repository_dispatch:
types: [wiki-content-update]

concurrency:
group: wiki-deploy
cancel-in-progress: false # serialize to avoid deploy collisions

jobs:
pin-and-deploy:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
steps:
- name: Checkout wiki-portal with submodules
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Determine submodule path from source repo
run: |
SOURCE_REPO="${{ github.event.client_payload.source_repo }}"
case "$SOURCE_REPO" in
*/attune-docs) echo "SUBMODULE_PATH=docs/attune" >> $GITHUB_ENV ;;
*/attune-pro-docs) echo "SUBMODULE_PATH=docs/attune-pro" >> $GITHUB_ENV ;;
*/attune-enterprise-docs) echo "SUBMODULE_PATH=docs/attune-enterprise" >> $GITHUB_ENV ;;
*/attune-pluginhub-docs) echo "SUBMODULE_PATH=docs/pluginhub" >> $GITHUB_ENV ;;
*/kvm-docs) echo "SUBMODULE_PATH=docs/kvm" >> $GITHUB_ENV ;;
*)
echo "ERROR: Unknown source repo: $SOURCE_REPO"
exit 1
;;
esac
echo "Source: $SOURCE_REPO, target submodule: $SUBMODULE_PATH"

- name: Update submodule to latest main
run: |
cd "$SUBMODULE_PATH"
git fetch origin main
git checkout main
git pull --ff-only origin main
cd "$GITHUB_WORKSPACE"
git add "$SUBMODULE_PATH"

- name: Commit submodule pin (if changed)
run: |
git config user.name "wiki-portal-bot"
git config user.email "wiki-portal-bot@engi-stack.com"
if git diff --cached --quiet; then
echo "No submodule pin change; skipping commit"
else
git commit -m "chore(wiki): bump ${SUBMODULE_PATH} to ${{ github.event.client_payload.source_sha }}"
git push origin main
fi

# Build & deploy steps (mirror wiki-deploy.yml)
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci --no-audit --no-fund

- name: Build
run: npm run build

- name: Verify build output
run: |
if [ ! -d "build" ]; then
echo "ERROR: build/ directory not found"
exit 1
fi
if [ ! -f "build/index.html" ]; then
echo "ERROR: build/index.html not found"
exit 1
fi
FILE_COUNT=$(find build -type f | wc -l)
echo "Build output: ${FILE_COUNT} files"
if [ "$FILE_COUNT" -lt 5 ]; then
echo "ERROR: build/ looks empty (< 5 files)"
exit 1
fi

- name: Deploy to production
uses: appleboy/ssh-action@v1.2.0
env:
WIKI_PATH: ${{ secrets.PRODUCTION_WIKI_PATH }}
with:
host: ${{ secrets.PRODUCTION_HOST }}
username: ${{ secrets.PRODUCTION_USER }}
key: ${{ secrets.PRODUCTION_SSH_KEY }}
port: 22
timeout: 300s
envs: WIKI_PATH
script: |
set -e
TARGET_PATH="${WIKI_PATH:-/data/company/cloud/wiki-web}"
cd "$TARGET_PATH"
git pull origin main
git submodule update --init --remote --recursive
docker-compose build --no-cache wiki
docker-compose up -d wiki
sleep 5
STATUS=$(docker inspect --format='{{.State.Status}}' cloud-wiki 2>/dev/null || echo "not-found")
if [ "$STATUS" != "running" ]; then
echo "ERROR: cloud-wiki is not running after deploy"
exit 1
fi
echo "==> Deploy complete."

Write this content to .github/workflows/wiki-content-update.yml.

  • Step 3: Lint workflow files
cd /data/company/cloud/wiki-web
# Basic YAML syntax check
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/wiki-content-update.yml'))" && echo "wiki-content-update.yml OK"
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/wiki-deploy.yml'))" && echo "wiki-deploy.yml OK"
  • Step 4: Commit C9 — dispatch handler
cd /data/company/cloud/wiki-web
git add .github/workflows/wiki-content-update.yml .github/workflows/wiki-deploy.yml
git commit -m "feat(wiki): repository_dispatch handler + submodules in wiki-deploy"
  • Step 5: Push wiki-portal chore/wiki-portal-rebrand branch
cd /data/company/cloud/wiki-web
git push github chore/wiki-portal-rebrand
# Note: cloud/wiki-web push is per global CLAUDE.md push policy (cloud is private/personal)

Phase E3 gate:

  • chore/wiki-portal-rebrand pushed with 9 commits ahead of 97b6344
  • Local npm run build succeeds
  • Trigger a manual dispatch from any docs repo (e.g., gh workflow run dispatch.yml --repo qiurui144/attune-docs) and verify wiki-portal wiki-content-update workflow appears in gh run list --repo qiurui144/wiki-portal

Phase E4 — Decommission Pattern A artifacts (Day 4 AM = 5/30)

Phase output: Remove the old per-product code-repo docs/wiki/ dirs (in attune, attune-pro repos) + old wiki-dispatch.yml workflows + retire fine-grained PAT secrets.

All work here is in external repos (attune, attune-pro), not wiki-web. AI prepares scripts; user executes per global CLAUDE.md push policy.

Task 12: Audit Pattern A residue (C10)

Files:

  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/decommission/audit.md

  • Step 1: Inventory Pattern A artifacts to remove

For each of attune, attune-pro repos, check:

# AI runs these read-only checks (no modification)

for repo in /data/company/project/attune /data/company/project/attune-pro; do
echo "=== $repo ==="
if [ -d "$repo" ]; then
ls "$repo/docs/wiki/" 2>/dev/null | head || echo "(no docs/wiki/)"
ls "$repo/.github/workflows/wiki-dispatch.yml" 2>/dev/null || echo "(no wiki-dispatch.yml)"
cd "$repo" && gh secret list 2>/dev/null | grep -i WIKI || echo "(no WIKI secrets)"
cd - >/dev/null
fi
done
  • Step 2: Write audit document
cd /data/company/cloud/wiki-web
mkdir -p docs/superpowers/plans/pattern-e/decommission
cat > docs/superpowers/plans/pattern-e/decommission/audit.md <<'EOF'
# Pattern A Decommission Audit

Captured: <date>

## attune (private)
- docs/wiki/: <FILL — present? files?>
- .github/workflows/wiki-dispatch.yml: <FILL — present?>
- Secret WIKI_PORTAL_DISPATCH_TOKEN: <FILL — present?>

## attune-pro (private)
- docs/wiki/: <FILL>
- .github/workflows/wiki-dispatch.yml: <FILL>
- Secret WIKI_PORTAL_DISPATCH_TOKEN: <FILL>

## kvm (public)
- (already public; KVM owner controls; no decommission needed if Pattern A was never deployed there)

## Decommission plan
For each repo where docs/wiki/ exists:
1. Verify equivalent content exists in qiurui144/<repo>-docs via cross-check `diff -r docs/wiki/ <(git -C /tmp/<repo>-docs ls-tree --name-only -r main)`
2. Create PR removing docs/wiki/ + .github/workflows/wiki-dispatch.yml
3. PR description: "Pattern E migration: content now lives in qiurui144/<repo>-docs"
4. After PR merge, delete secret WIKI_PORTAL_DISPATCH_TOKEN
EOF
  • Step 3: Commit C10
cd /data/company/cloud/wiki-web
git add docs/superpowers/plans/pattern-e/decommission/audit.md
git commit -m "plan(pattern-e): Pattern A decommission audit"

Task 13: Execute decommission PRs (C11)

Files:

  • In attune repo: delete docs/wiki/ + .github/workflows/wiki-dispatch.yml

  • In attune-pro repo: delete docs/wiki/ + .github/workflows/wiki-dispatch.yml

  • Step 1: For each affected repo, user creates decommission branch + PR

# User runs — AI must not push to attune or attune-pro per task red lines
cd /data/company/project/attune
git checkout -b chore/pattern-e-decommission
if [ -d docs/wiki ]; then git rm -r docs/wiki; fi
if [ -f .github/workflows/wiki-dispatch.yml ]; then git rm .github/workflows/wiki-dispatch.yml; fi
git commit -m "chore: remove Pattern A docs/wiki/ + wiki-dispatch (migrated to qiurui144/attune-docs)"
git push origin chore/pattern-e-decommission
gh pr create --title "chore: Pattern E migration — remove docs/wiki/" \
--body "Pattern A artifacts removed. Content now lives in qiurui144/attune-docs.\n\nSee /data/company/cloud/wiki-web/docs/superpowers/plans/2026-05-25-pattern-e-impl.md for full migration plan."

# Same for attune-pro
cd /data/company/project/attune-pro
git checkout -b chore/pattern-e-decommission
if [ -d docs/wiki ]; then git rm -r docs/wiki; fi
if [ -f .github/workflows/wiki-dispatch.yml ]; then git rm .github/workflows/wiki-dispatch.yml; fi
git commit -m "chore: remove Pattern A docs/wiki/ + wiki-dispatch (migrated to qiurui144/attune-pro-docs)"
git push origin chore/pattern-e-decommission
gh pr create --title "chore: Pattern E migration — remove docs/wiki/"
  • Step 2: After PRs merged, retire per-repo secrets
gh secret delete WIKI_PORTAL_DISPATCH_TOKEN --repo qiurui144/attune
gh secret delete WIKI_PORTAL_DISPATCH_TOKEN --repo qiurui144/attune-pro
# (Only WIKI_APP_ID / WIKI_APP_PRIVATE_KEY remain on docs repos.)
  • Step 3: Commit C11 — record decommission completion
cd /data/company/cloud/wiki-web
cat > docs/superpowers/plans/pattern-e/decommission/completion.md <<'EOF'
# Pattern A Decommission Completion

- attune PR: <FILL URL> merged on <FILL date>
- attune-pro PR: <FILL URL> merged on <FILL date>
- Secrets deleted: WIKI_PORTAL_DISPATCH_TOKEN from attune + attune-pro
- Pattern A no longer present in any code repo
EOF
git add docs/superpowers/plans/pattern-e/decommission/completion.md
git commit -m "plan(pattern-e): record Pattern A decommission completion"

Phase E4 gate:

  • No docs/wiki/ remains in attune or attune-pro
  • No wiki-dispatch.yml in either
  • No WIKI_PORTAL_DISPATCH_TOKEN secret in either
  • Wiki rendering at production URL still healthy

Phase E5 — Monitoring + verification (Day 4 PM = 5/30 evening, 0.5 day)

Phase output: Monitor wiring + KVM onboarding test + documentation updates.

Task 14: Add monitoring + 5-min KVM onboarding test + DEVELOP.md updates (C12)

Files:

  • Modify: /data/company/cloud/wiki-web/DEVELOP.md

  • Create: /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/onboarding.md

  • Modify: each qiurui144/<project>-docs README.md to add deep-link to onboarding doc

  • Step 1: Add monitoring step to wiki-content-update.yml

Append a failure notification step to wiki-content-update.yml (Edit tool):

After the final Deploy to production step, add:

- name: Notify on failure
if: failure()
run: |
echo "::error::wiki-content-update failed for source repo ${{ github.event.client_payload.source_repo }} sha ${{ github.event.client_payload.source_sha }}"
# Future: integrate Slack/email webhook here (v0.2)
  • Step 2: Write the 5-min onboarding doc

Create /data/company/cloud/wiki-web/docs/superpowers/plans/pattern-e/onboarding.md:

# Adding a new product to wiki-portal (5-min onboarding)

This is the standardized flow for adding a new product's docs to wiki-portal under Pattern E.

## Prerequisites
- GitHub App `attune-wiki-dispatch` is installed on the qiurui144 account.
- You have write access to wiki-portal (qiurui144/wiki-portal).
- You can create public repos under qiurui144.

## Steps

### 1. Create the docs repo (30s)
\`\`\`bash
gh repo create qiurui144/<project>-docs \
--template qiurui144/docs-template \
--public \
--description "User-facing docs for <project>"
\`\`\`

### 2. Configure App access (10s)
The GitHub App `attune-wiki-dispatch` must include the new repo in its installation.
Open https://github.com/settings/installations → "attune-wiki-dispatch" → "Configure" →
add <project>-docs to "Only select repositories".

### 3. Store secrets in new docs repo (20s)
\`\`\`bash
gh secret set WIKI_APP_ID --repo qiurui144/<project>-docs --body "<APP_ID>"
gh secret set WIKI_APP_PRIVATE_KEY --repo qiurui144/<project>-docs < /secure/path/to/private-key.pem
\`\`\`

### 4. Customize template content (2 min)
\`\`\`bash
cd /tmp
git clone https://github.com/qiurui144/<project>-docs.git
cd <project>-docs
sed -i 's/PROJECT/<Project Name>/g' README.md wiki/index.md
git add . && git commit -m "init: <project> wiki" && git push
\`\`\`

### 5. Add submodule + plugin + sidebar in wiki-portal (1.5 min)
\`\`\`bash
cd /data/company/cloud/wiki-web
git checkout -b feat/add-<project>-docs
git submodule add https://github.com/qiurui144/<project>-docs.git docs/<project>

# Edit docusaurus.config.ts: add a new plugin-content-docs instance
# Edit sidebars/<project>.ts: write a sidebar (see sidebars/attune.ts as reference)
# Edit .github/workflows/wiki-content-update.yml: add case "*/<project>-docs) ... ;;"

git add .gitmodules docs/<project> docusaurus.config.ts sidebars/<project>.ts .github/workflows/wiki-content-update.yml
git commit -m "feat(wiki): onboard <project> docs"
git push origin feat/add-<project>-docs
gh pr create
\`\`\`

### 6. Verify (1 min)
After PR merge:
- Push a commit to <project>-docs main
- Watch wiki-portal Actions tab — wiki-content-update should fire within 30s
- Browse https://wiki.engi-stack.com/<project>/ — should render

**Total: ~5 min** (excluding ~5 min for wiki-portal CI build).
  • Step 3: Update DEVELOP.md to reference Pattern E architecture

Open DEVELOP.md and add a section near the architecture section:

## Pattern E: independent docs repos (since 2026-05-30)

Documentation content is sourced from 5 independent public docs repos via git submodules:

| Mount path | Submodule source |
|---|---|
| `docs/attune/` | https://github.com/qiurui144/attune-docs |
| `docs/attune-pro/` | https://github.com/qiurui144/attune-pro-docs |
| `docs/attune-enterprise/` | https://github.com/qiurui144/attune-enterprise-docs |
| `docs/pluginhub/` | https://github.com/qiurui144/attune-pluginhub-docs |
| `docs/kvm/` | https://github.com/qiurui144/kvm-docs |

Updates flow:
- Editor pushes to `<project>-docs/main`
- `dispatch.yml` (in docs repo) calls `repository_dispatch` on wiki-portal via GitHub App token
- wiki-portal `wiki-content-update.yml` updates the submodule pin + rebuilds + deploys

For onboarding a new product, see `docs/superpowers/plans/pattern-e/onboarding.md`.
For the original architecture spec, see `docs/superpowers/specs/2026-05-25-pattern-e-independent-docs-repo.md`.

Use Edit tool to insert this section before the "## License" or at end of file.

  • Step 4: KVM 5-min real-world onboarding test
# Use a temporary throwaway repo to verify the 5-min flow end-to-end
# (User executes; AI verifies via gh api read-only)

gh repo create qiurui144/test-onboarding-docs --template qiurui144/docs-template --public --description "TEST — to be deleted"
gh secret set WIKI_APP_ID --repo qiurui144/test-onboarding-docs --body "$WIKI_APP_ID"
gh secret set WIKI_APP_PRIVATE_KEY --repo qiurui144/test-onboarding-docs < /path/to/private-key.pem

# Trigger dispatch by pushing any change
cd /tmp
git clone https://github.com/qiurui144/test-onboarding-docs.git
cd test-onboarding-docs
echo "test" >> wiki/index.md
git commit -am "test onboarding"
git push

# Verify
sleep 30
gh run list --repo qiurui144/test-onboarding-docs --limit 1
# Expected: 1 successful dispatch run

# Note: wiki-portal will NOT yet know about test-onboarding-docs (no submodule for it).
# wiki-content-update.yml's case statement will hit the default ("Unknown source repo")
# and fail — that's expected behavior for the test. Verify the failure case fires.

gh run list --repo qiurui144/wiki-portal --workflow wiki-content-update.yml --limit 1
# Expected: 1 failed run with "Unknown source repo" in logs

# Clean up
gh repo delete qiurui144/test-onboarding-docs --confirm
  • Step 5: cloud.sh verify still passes
cd /data/company/cloud
bash cloud.sh verify
# Expected: 25/0/0 (all green, no regressions from Pattern E changes)
  • Step 6: Commit C12 — final E5
cd /data/company/cloud/wiki-web
git add .github/workflows/wiki-content-update.yml \
docs/superpowers/plans/pattern-e/onboarding.md \
DEVELOP.md
git commit -m "feat(wiki): Pattern E monitoring + onboarding doc + DEVELOP.md update"
git push github chore/wiki-portal-rebrand

Phase E5 gate:

  • wiki-content-update.yml has failure-notification step
  • docs/superpowers/plans/pattern-e/onboarding.md exists
  • DEVELOP.md references Pattern E
  • KVM test repo verified onboarding flow (then deleted)
  • cloud.sh verify returns 25/0/0
  • Branch pushed to origin

GA Acceptance Checklist (v1.0.1)

Tick all before merging chore/wiki-portal-rebrand → main:

  • Repos: 5 product docs repos exist (public) + 1 docs-template + GitHub App installed on all 6 + wiki-portal
  • Secrets: each docs repo has WIKI_APP_ID + WIKI_APP_PRIVATE_KEY; no WIKI_PORTAL_DISPATCH_TOKEN PAT anywhere
  • Submodules: .gitmodules in wiki-portal references 5 docs repos; git submodule status shows 5 lines, no - prefixes
  • Old artifacts removed:
    • attune + attune-pro have no docs/wiki/ directory (verify via gh api)
    • attune + attune-pro have no .github/workflows/wiki-dispatch.yml
    • per-repo PATs deleted
  • KVM 5-min onboarding test: temporary test-onboarding-docs repo successfully fired dispatch (then deleted)
  • cloud.sh verify = 25/0/0 (Phase E5 commit C12)
  • wiki-portal build trigger chain works end-to-end:
    • Push any change to qiurui144/attune-docs/main
    • Within 30s, dispatch.yml succeeds with GitHub App token
    • Within 60s, wiki-portal wiki-content-update.yml run starts
    • Within 5 min, https://wiki.engi-stack.com/attune/ reflects the change
  • Documentation updated:
    • DEVELOP.md describes Pattern E
    • 5 docs repos' READMEs all updated (no PROJECT placeholder remaining)
    • docs/superpowers/plans/pattern-e/onboarding.md complete

R1-R12 Risk Mitigation Map

Each spec risk mapped to mitigation tasks/commits in this plan:

IDRiskMitigation in plan
R1GITHUB_TOKEN cross-repo dispatch impossibleResolved: All docs repos use GitHub App via actions/create-github-app-token@v1 (Task 2 dispatch.yml template)
R2git filter-repo loses commit historyTask 4 Step 2-3: backup wiki-web + tag pre-pattern-e-migration. Each extraction (Tasks 5-9) explicitly verifies with git log --follow
R3wiki-portal Pattern A layout assumedVerified current state: no Pattern A submodules deployed in wiki-portal (Task 1 inventory; Phase E3 builds submodule layout from scratch — no rollback needed)
R4KVM owner refusalTask 9: kvm-docs is scaffold-only; KVM owner can populate when ready or opt out (only docs/kvm/ submodule needs removal)
R5Code-docs dual commit costMentioned in onboarding.md (Task 14 Step 2); accepted cost for clean separation
R6Public docs leak internal infoEach filter-repo task (5, 7, 8) has explicit secret-scan step with kebab-list grep. PR review required for content-changing PRs
R7qiurui144 org repo countAll 5 docs repos public — public repos free for unlimited count
R8Submodule pin driftwiki-content-update.yml (Task 11) auto-pins on every dispatch + commits back to main
R9PAT 90-day expiryResolved: GitHub App used throughout (no PAT). App private key has no expiry; only manual revocation
R10Dispatch event lossdocs repo dispatch.yml includes workflow_dispatch: — manual re-trigger available. Onboarding doc (Task 14) lists this fallback
R115 plugin instances slow buildTasks 10 Step 8 measures local build time; if >5 min, defer per-instance optimization to v0.2. Currently estimated 2-3 min
R12README/index.md conflictDocusaurus reads docs/<project>/wiki/ only (per Task 10 Step 5 config path: 'docs/<project>/wiki'); top-level README + LICENSE excluded

Rollback Procedures

Each phase has a defined rollback. Execute in reverse order if catastrophic failure.

Rollback from E5 → E4

git checkout chore/wiki-portal-rebrand
git revert C12
git push github chore/wiki-portal-rebrand

Rollback from E4 → E3

# In attune + attune-pro: revert decommission PRs (or revert the merge commits)
cd /data/company/project/attune && gh pr list --state merged --search "Pattern E migration" | head
git revert <decommission-merge-sha>
git push origin main

# Restore deleted PAT (if needed for fallback)
# (User regenerates the PAT in GH settings and re-adds the secret)

Rollback from E3 → E2

cd /data/company/cloud/wiki-web
git checkout chore/wiki-portal-rebrand
git reset --hard <C7-sha> # before C8/C9
# Remove submodule references
rm .gitmodules
git rm -rf docs/attune docs/attune-pro docs/attune-enterprise docs/pluginhub docs/kvm
# Restore sidebars.ts from prior commit
git checkout pre-pattern-e-migration -- sidebars.ts docusaurus.config.ts
git checkout pre-pattern-e-migration -- .github/workflows/wiki-deploy.yml
rm .github/workflows/wiki-content-update.yml
git commit -m "revert: rollback Pattern E E3 (submodule + plugins + sidebars)"
git push --force-with-lease github chore/wiki-portal-rebrand

Rollback from E2 → E1

docs repos persist (no harm) but are not yet referenced.

# Each docs repo can be left in place (does nothing without wiki-portal submodule)
# Or delete:
for r in attune-docs attune-pluginhub-docs attune-enterprise-docs; do
gh repo delete qiurui144/$r --confirm
done

Rollback from E1 → 0

# Delete the 5 docs repos + template
for r in attune-docs attune-pro-docs attune-enterprise-docs attune-pluginhub-docs kvm-docs docs-template; do
gh repo delete qiurui144/$r --confirm
done

# Delete GitHub App
# https://github.com/settings/apps/attune-wiki-dispatch → "Delete GitHub App"

Full rollback (anywhere → pre-migration state)

cd /data/company/cloud
rm -rf wiki-web
mv wiki-web.pre-pattern-e-backup wiki-web
cd wiki-web
git tag pre-pattern-e-migration --list # verify still there
# Force-push original state if needed:
git push --force-with-lease github chore/wiki-portal-rebrand

GitHub App User-Action Cheatsheet

Single page for the user to follow during Phase E1.

A. One-time registration (5 min)

  1. https://github.com/settings/apps/new
  2. Form fields:
    • Name: attune-wiki-dispatch
    • Homepage URL: https://wiki.engi-stack.com
    • Callback URL: (blank)
    • Setup URL: (blank)
    • Webhook → Active: UNCHECK
    • Permissions:
      • Repository: Contents = Read
      • Repository: Actions = Read and write
      • Repository: Metadata = Read (auto)
    • Subscribe to events: none
    • Install: Only on this account
  3. Click "Create GitHub App"
  4. Record displayed App ID (numeric)
  5. Scroll to "Private keys" → "Generate a private key" → save .pem file to a password manager

B. Install on repos (2 min)

  1. App page → sidebar → "Install App" → choose qiurui144 → "Only select repositories"
  2. Add: wiki-portal, attune-docs, attune-pro-docs, attune-enterprise-docs, attune-pluginhub-docs, kvm-docs, docs-template
  3. Click "Install"

C. Store secrets in each docs repo (3 min, automatable)

APP_ID="<paste numeric App ID>"
PEM_PATH="<path to downloaded .pem>"

for r in attune-docs attune-pro-docs attune-enterprise-docs attune-pluginhub-docs kvm-docs docs-template; do
gh secret set WIKI_APP_ID --repo qiurui144/$r --body "$APP_ID"
gh secret set WIKI_APP_PRIVATE_KEY --repo qiurui144/$r < "$PEM_PATH"
done

D. Rotation policy

  • App private key: no automatic expiry, but rotate every 12 months as best practice
  • To rotate:
    1. Generate new private key on App page (creates new one alongside old)
    2. Run section C with new .pem
    3. Delete old private key on App page
  • No 90-day calendar reminder needed (unlike fine-grained PAT)

Time Box Budget

PhaseEstimateCumulative
E11 day (5/27)1 day
E21 day (5/28)2 days
E31 day (5/29)3 days
E40.5 day (5/30 AM)3.5 days
E50.5 day (5/30 PM)4 days

Buffer: 0.5 day for unforeseen issues. Total: 4.5 days, completes by EOD 5/30.


Out-of-Scope Confirmations (per task red lines)

This plan does not:

  • ❌ Create any GitHub repo (all gh repo create are user actions)
  • ❌ Push to attune or attune-pro repos (Phase E4 decommission is user-driven)
  • ❌ Modify wiki-portal .gitmodules (Phase E3 commits C8/C9 are prepared but pushed only after user review)
  • ❌ Register or invoke the GitHub App on the user's behalf
  • ❌ Run git filter-repo (all Phase E2 extractions are user actions per push-policy)

This plan does:

  • ✅ Write the 4.5-day step-by-step playbook
  • ✅ Create local commits C1-C12 on chore/wiki-portal-rebrand (wiki-web is in cloud/ — push allowed per global push-policy for personal repos)
  • ✅ Provide all scripts the user runs verbatim
  • ✅ Provide all mitigation + rollback procedures