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-repofor history extraction - GitHub Actions +
repository_dispatchevent +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(commit02273c9, 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/kvmalready cloned as plain dirs (not yet submodules).
Repo Inventory
5 docs repos to create (all public, all under qiurui144):
| docs repo | replaces wiki-web path | mount in wiki-portal |
|---|---|---|
qiurui144/attune-docs | docs/attune/ (16 files) + docs/getting-started/ + docs/hardware/ + docs/software/ + docs/download.md | docs/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-docs | docs/attune-enterprise/ (7 files, ex-lawcontrol) | docs/attune-enterprise/ |
qiurui144/attune-pluginhub-docs | docs/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@v1inside each docs repo'sdispatch.yml - Secrets stored in each docs repo:
WIKI_APP_ID,WIKI_APP_PRIVATE_KEY
Phase Timeline (4.5 days, 12 commits)
| Phase | Day | Commits | Deliverable |
|---|---|---|---|
| E1 | 5/27 | C1, C2 | 5 docs repos + template + GitHub App registered + installed |
| E2 | 5/28 | C3-C7 | History extraction (5 × git filter-repo) + push to docs repos |
| E3 | 5/29 | C8, C9 | wiki-portal .gitmodules + Docusaurus config + sidebars split + dispatch handler |
| E4 | 5/30 AM | C10, C11 | Delete old Pattern A artifacts (per-repo wiki-dispatch.yml, PAT secrets, old docs/<product>/ direct markdown in wiki-portal) |
| E5 | 5/30 PM | C12 | Monitoring + 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 createor 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-rebrandbranch 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(addsubmodules: recursiveto 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-rebrandpushed with 9 commits ahead of97b6344- Local
npm run buildsucceeds - Trigger a manual dispatch from any docs repo (e.g.,
gh workflow run dispatch.yml --repo qiurui144/attune-docs) and verify wiki-portalwiki-content-updateworkflow appears ingh 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.ymlin either - No
WIKI_PORTAL_DISPATCH_TOKENsecret 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>-docsREADME.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.ymlhas failure-notification stepdocs/superpowers/plans/pattern-e/onboarding.mdexistsDEVELOP.mdreferences Pattern E- KVM test repo verified onboarding flow (then deleted)
cloud.sh verifyreturns 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; noWIKI_PORTAL_DISPATCH_TOKENPAT anywhere - Submodules:
.gitmodulesin wiki-portal references 5 docs repos;git submodule statusshows 5 lines, no-prefixes - Old artifacts removed:
- attune + attune-pro have no
docs/wiki/directory (verify viagh api) - attune + attune-pro have no
.github/workflows/wiki-dispatch.yml - per-repo PATs deleted
- attune + attune-pro have no
- KVM 5-min onboarding test: temporary
test-onboarding-docsrepo 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.ymlsucceeds with GitHub App token - Within 60s, wiki-portal
wiki-content-update.ymlrun starts - Within 5 min, https://wiki.engi-stack.com/attune/ reflects the change
- Push any change to
- Documentation updated:
DEVELOP.mddescribes Pattern E- 5 docs repos' READMEs all updated (no
PROJECTplaceholder remaining) docs/superpowers/plans/pattern-e/onboarding.mdcomplete
R1-R12 Risk Mitigation Map
Each spec risk mapped to mitigation tasks/commits in this plan:
| ID | Risk | Mitigation in plan |
|---|---|---|
| R1 | GITHUB_TOKEN cross-repo dispatch impossible | Resolved: All docs repos use GitHub App via actions/create-github-app-token@v1 (Task 2 dispatch.yml template) |
| R2 | git filter-repo loses commit history | Task 4 Step 2-3: backup wiki-web + tag pre-pattern-e-migration. Each extraction (Tasks 5-9) explicitly verifies with git log --follow |
| R3 | wiki-portal Pattern A layout assumed | Verified current state: no Pattern A submodules deployed in wiki-portal (Task 1 inventory; Phase E3 builds submodule layout from scratch — no rollback needed) |
| R4 | KVM owner refusal | Task 9: kvm-docs is scaffold-only; KVM owner can populate when ready or opt out (only docs/kvm/ submodule needs removal) |
| R5 | Code-docs dual commit cost | Mentioned in onboarding.md (Task 14 Step 2); accepted cost for clean separation |
| R6 | Public docs leak internal info | Each filter-repo task (5, 7, 8) has explicit secret-scan step with kebab-list grep. PR review required for content-changing PRs |
| R7 | qiurui144 org repo count | All 5 docs repos public — public repos free for unlimited count |
| R8 | Submodule pin drift | wiki-content-update.yml (Task 11) auto-pins on every dispatch + commits back to main |
| R9 | PAT 90-day expiry | Resolved: GitHub App used throughout (no PAT). App private key has no expiry; only manual revocation |
| R10 | Dispatch event loss | docs repo dispatch.yml includes workflow_dispatch: — manual re-trigger available. Onboarding doc (Task 14) lists this fallback |
| R11 | 5 plugin instances slow build | Tasks 10 Step 8 measures local build time; if >5 min, defer per-instance optimization to v0.2. Currently estimated 2-3 min |
| R12 | README/index.md conflict | Docusaurus 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)
- https://github.com/settings/apps/new
- 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
- Name:
- Click "Create GitHub App"
- Record displayed App ID (numeric)
- Scroll to "Private keys" → "Generate a private key" → save
.pemfile to a password manager
B. Install on repos (2 min)
- App page → sidebar → "Install App" → choose qiurui144 → "Only select repositories"
- Add:
wiki-portal,attune-docs,attune-pro-docs,attune-enterprise-docs,attune-pluginhub-docs,kvm-docs,docs-template - 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:
- Generate new private key on App page (creates new one alongside old)
- Run section C with new
.pem - Delete old private key on App page
- No 90-day calendar reminder needed (unlike fine-grained PAT)
Time Box Budget
| Phase | Estimate | Cumulative |
|---|---|---|
| E1 | 1 day (5/27) | 1 day |
| E2 | 1 day (5/28) | 2 days |
| E3 | 1 day (5/29) | 3 days |
| E4 | 0.5 day (5/30 AM) | 3.5 days |
| E5 | 0.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 createare 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