diff --git a/.github/workflows/docs-lint.yml b/.github/workflows/docs-lint.yml new file mode 100644 index 00000000..7ea0b8c0 --- /dev/null +++ b/.github/workflows/docs-lint.yml @@ -0,0 +1,36 @@ +name: docs-lint + +on: + push: + branches: [main] + paths: + - "**/*.md" + - ".markdownlint.yml" + - ".markdownlintignore" + - ".github/workflows/docs-lint.yml" + - "scripts/docs/docs_lint.sh" + - "docs/standards/lint_scope.txt" + pull_request: + branches: [main] + paths: + - "**/*.md" + - ".markdownlint.yml" + - ".markdownlintignore" + - ".github/workflows/docs-lint.yml" + - "scripts/docs/docs_lint.sh" + - "docs/standards/lint_scope.txt" + +jobs: + markdownlint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Lint markdown + run: bash scripts/docs/docs_lint.sh diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 00000000..8c937817 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,17 @@ +default: true + +MD013: + line_length: 180 + heading_line_length: 180 + code_block_line_length: 220 + +MD024: + allow_different_nesting: true + +MD033: false +MD041: false +MD022: false +MD029: false +MD031: false +MD032: false +MD060: false diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 00000000..8f523aff --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,6 @@ +.worktrees/ +node_modules/ +site/ +rollback_backups/ +docs/consolidation/_node1_runtime_docs/ +**/*.bak_* diff --git a/docs/SESSION_STARTER.md b/docs/SESSION_STARTER.md index 61fa8f01..179fb279 100644 --- a/docs/SESSION_STARTER.md +++ b/docs/SESSION_STARTER.md @@ -46,6 +46,17 @@ bash scripts/docs/services_sync.sh --dry-run bash scripts/docs/services_sync.sh --apply ``` +5. Docs lint and standards: +```bash +bash scripts/docs/docs_lint.sh +``` + +6. Docs backup (explicit run): +```bash +bash scripts/docs/docs_backup.sh --dry-run +bash scripts/docs/docs_backup.sh --apply +``` + ## Runtime-First Facts (must re-check each session) 1. NODE1 branch/SHA: diff --git a/docs/backups/LATEST.txt b/docs/backups/LATEST.txt new file mode 100644 index 00000000..c20cca16 --- /dev/null +++ b/docs/backups/LATEST.txt @@ -0,0 +1 @@ +/Users/apple/github-projects/microdao-daarion/docs/backups/docs_backup_20260216-022549.tar.gz diff --git a/docs/consolidation/INTEGRATIONS_STATUS_LATEST.md b/docs/consolidation/INTEGRATIONS_STATUS_LATEST.md index c0541149..feff16ab 100644 --- a/docs/consolidation/INTEGRATIONS_STATUS_LATEST.md +++ b/docs/consolidation/INTEGRATIONS_STATUS_LATEST.md @@ -1,6 +1,6 @@ # Integrations Bootstrap Status -Generated: 2026-02-16 10:20:19 UTC +Generated: 2026-02-16 10:25:49 UTC Repo: /Users/apple/github-projects/microdao-daarion diff --git a/docs/consolidation/README.md b/docs/consolidation/README.md index 02da6cbc..a5314a76 100644 --- a/docs/consolidation/README.md +++ b/docs/consolidation/README.md @@ -32,5 +32,8 @@ python3 /Users/apple/github-projects/microdao-daarion/scripts/docs/build_docs_hu ```bash bash /Users/apple/github-projects/microdao-daarion/scripts/docs/session_bootstrap.sh +bash /Users/apple/github-projects/microdao-daarion/scripts/docs/services_sync.sh --dry-run +bash /Users/apple/github-projects/microdao-daarion/scripts/docs/services_sync.sh --apply +bash /Users/apple/github-projects/microdao-daarion/scripts/docs/docs_lint.sh bash /Users/apple/github-projects/microdao-daarion/scripts/docs/docs_sync.sh --dry-run ``` diff --git a/docs/consolidation/SOURCES.md b/docs/consolidation/SOURCES.md index 20f219e0..83b63a13 100644 --- a/docs/consolidation/SOURCES.md +++ b/docs/consolidation/SOURCES.md @@ -24,6 +24,8 @@ This file tracks where documentation is collected from for consolidation. ## Automation Scripts - `scripts/docs/session_bootstrap.sh` — refreshes integration status and writes `INTEGRATIONS_STATUS_LATEST.md`. - `scripts/docs/docs_sync.sh` — safe docs sync automation with `--dry-run` by default and explicit `--apply`. +- `scripts/docs/docs_lint.sh` — markdown lint for canonical documentation. +- `scripts/docs/docs_backup.sh` — timestamped docs backup with retention rotation. - `scripts/docs/jupyter_sync.sh` — adapter for Jupyter server API status + notebooks index export. - `scripts/docs/pieces_sync.sh` — adapter for Pieces local runtime/data index + optional API probe. - `scripts/docs/services_sync.sh` — orchestrator for bootstrap + Jupyter + Pieces sync adapters. diff --git a/docs/consolidation/jupyter/JUPYTER_SYNC_LATEST.md b/docs/consolidation/jupyter/JUPYTER_SYNC_LATEST.md index 1ca51b01..0fc449e1 100644 --- a/docs/consolidation/jupyter/JUPYTER_SYNC_LATEST.md +++ b/docs/consolidation/jupyter/JUPYTER_SYNC_LATEST.md @@ -1,6 +1,6 @@ # Jupyter Sync Report -Generated: 2026-02-16 10:20:20 UTC +Generated: 2026-02-16 10:25:50 UTC - jupyter_cmd: not-found - server_count: 0 diff --git a/docs/consolidation/pieces/PIECES_SYNC_LATEST.md b/docs/consolidation/pieces/PIECES_SYNC_LATEST.md index 69326b50..f4d9d0a7 100644 --- a/docs/consolidation/pieces/PIECES_SYNC_LATEST.md +++ b/docs/consolidation/pieces/PIECES_SYNC_LATEST.md @@ -1,6 +1,6 @@ # Pieces Sync Report -Generated: 2026-02-16 10:20:43 UTC +Generated: 2026-02-16 10:25:50 UTC - pieces_extensions_count: 1 - pieces_data_dirs_count: 0 diff --git a/docs/runbooks/DOCS_SERVICES_AUTOMATION_RUNBOOK.md b/docs/runbooks/DOCS_SERVICES_AUTOMATION_RUNBOOK.md index 4f7279dd..464d134d 100644 --- a/docs/runbooks/DOCS_SERVICES_AUTOMATION_RUNBOOK.md +++ b/docs/runbooks/DOCS_SERVICES_AUTOMATION_RUNBOOK.md @@ -43,6 +43,7 @@ Outputs: - `docs/consolidation/jupyter/notebooks_index_latest.csv` - `docs/consolidation/pieces/PIECES_SYNC_LATEST.md` - `docs/consolidation/pieces/pieces_index_latest.csv` +- `docs/backups/LATEST.txt` (latest backup archive reference) ## 3) Review pending docs updates @@ -64,6 +65,24 @@ bash scripts/docs/docs_sync.sh --apply --targets github,gitea - `docs_sync.sh` is dry-run by default. - `--apply` refuses to proceed if staged non-doc files are present. - Only curated doc paths are auto-staged by the script. +- `services_sync.sh --apply` creates docs backup before writing integration artifacts. + +## Standardization and lint + +Local lint: + +```bash +cd /Users/apple/github-projects/microdao-daarion +bash scripts/docs/docs_lint.sh +``` + +CI lint: +- `.github/workflows/docs-lint.yml` +- config: `.markdownlint.yml`, `.markdownlintignore` + +Style and template: +- `docs/standards/DOCS_STYLE_GUIDE.md` +- `docs/standards/DOC_TEMPLATE.md` ## Jupyter and Pieces notes diff --git a/docs/standards/DOCS_STYLE_GUIDE.md b/docs/standards/DOCS_STYLE_GUIDE.md new file mode 100644 index 00000000..7235a672 --- /dev/null +++ b/docs/standards/DOCS_STYLE_GUIDE.md @@ -0,0 +1,61 @@ +# Docs Style Guide + +Date: 2026-02-16 +Purpose: standardized writing and structure for canonical documentation in this repository. + +## Scope + +This guide applies to canonical docs in: +- `docs/` +- `docs/runbooks/` +- `config/*.md` +- root operational docs (`PROJECT-MASTER-INDEX.md`, `NODA1-SAFE-DEPLOY.md`, `NODA1-README.md`) + +Legacy and snapshot docs are excluded from strict linting: +- `docs/consolidation/_node1_runtime_docs/` +- `.worktrees/` +- backup artifacts (`*.bak_*`) + +## Required Structure + +Every new canonical document should start with: +1. H1 title +2. `Date: YYYY-MM-DD` +3. `Purpose: ...` + +Recommended sections: +1. Scope +2. Preconditions +3. Procedure / Steps +4. Verification +5. Rollback / Recovery + +## Writing Rules + +- Use sentence-case headings. +- Keep sections short and operational. +- Prefer explicit paths and commands. +- Mark runtime facts with concrete dates. +- Avoid mixing strategic legacy notes into canonical runbooks. + +## Naming Rules + +- Runbooks: `docs/runbooks/_RUNBOOK.md` +- Decisions: `docs/runbooks/_DECISION_YYYY-MM-DD.md` +- One-off status snapshots: include date in filename. + +## Linting + +Local check: +```bash +bash scripts/docs/docs_lint.sh +``` + +CI check: +- GitHub workflow: `.github/workflows/docs-lint.yml` + +Lint scope source: +- `docs/standards/lint_scope.txt` + +Note: +- Full historical docs migration is phased; lint is enforced on managed canonical scope first. diff --git a/docs/standards/DOC_TEMPLATE.md b/docs/standards/DOC_TEMPLATE.md new file mode 100644 index 00000000..a444e6d5 --- /dev/null +++ b/docs/standards/DOC_TEMPLATE.md @@ -0,0 +1,37 @@ +# + +Date: YYYY-MM-DD +Purpose: one-sentence objective of this document. + +## Scope + +- Systems, repos, services, and files covered. + +## Preconditions + +- Required access +- Required tools +- Required environment + +## Procedure + +1. Step one +2. Step two +3. Step three + +## Verification + +- Command(s): +```bash +# put verification commands here +``` +- Expected result(s) + +## Rollback + +1. Recovery step one +2. Recovery step two + +## References + +- `/absolute/or/repo/path/to/relevant/file` diff --git a/docs/standards/lint_scope.txt b/docs/standards/lint_scope.txt new file mode 100644 index 00000000..abb3f505 --- /dev/null +++ b/docs/standards/lint_scope.txt @@ -0,0 +1,7 @@ +docs/SESSION_STARTER.md +docs/consolidation/README.md +docs/consolidation/SOURCES.md +docs/runbooks/DOCS_SERVICES_AUTOMATION_RUNBOOK.md +docs/standards/DOCS_STYLE_GUIDE.md +docs/standards/DOC_TEMPLATE.md +config/README.md diff --git a/scripts/docs/docs_backup.sh b/scripts/docs/docs_backup.sh new file mode 100755 index 00000000..9c717227 --- /dev/null +++ b/scripts/docs/docs_backup.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +OUT_DIR="$ROOT_DIR/docs/backups" +RETENTION="${DOCS_BACKUP_RETENTION:-20}" +DRY_RUN=1 +APPLY=0 + +usage() { + cat <<'USAGE' +Usage: + bash scripts/docs/docs_backup.sh [--dry-run] [--apply] [--retention N] + +Behavior: + - default mode is --dry-run + - --apply creates docs backup archive and rotates old backups +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=1 + APPLY=0 + shift + ;; + --apply) + APPLY=1 + DRY_RUN=0 + shift + ;; + --retention) + RETENTION="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown arg: $1" >&2 + usage + exit 2 + ;; + esac +done + +STAMP="$(date +%Y%m%d-%H%M%S)" +ARCHIVE="$OUT_DIR/docs_backup_${STAMP}.tar.gz" +LATEST_REF="$OUT_DIR/LATEST.txt" + +backup_targets=( + PROJECT-MASTER-INDEX.md + NODA1-SAFE-DEPLOY.md + docs/SESSION_STARTER.md + docs/runbooks + docs/standards + docs/consolidation/README.md + docs/consolidation/SOURCES.md + docs/consolidation/docs_registry_curated.csv + docs/consolidation/INTEGRATIONS_STATUS_LATEST.md + docs/consolidation/jupyter/JUPYTER_SYNC_LATEST.md + docs/consolidation/jupyter/notebooks_index_latest.csv + docs/consolidation/pieces/PIECES_SYNC_LATEST.md + docs/consolidation/pieces/pieces_index_latest.csv +) + +existing=() +for t in "${backup_targets[@]}"; do + [[ -e "$ROOT_DIR/$t" ]] && existing+=("$t") +done + +if [[ "$DRY_RUN" -eq 1 ]]; then + echo "[dry-run] backup archive: $ARCHIVE" + echo "[dry-run] retention: $RETENTION" + echo "[dry-run] targets:" + printf ' - %s\n' "${existing[@]}" + exit 0 +fi + +mkdir -p "$OUT_DIR" + +tar -czf "$ARCHIVE" -C "$ROOT_DIR" "${existing[@]}" +printf '%s\n' "$ARCHIVE" > "$LATEST_REF" + +mapfile -t backups < <(ls -1t "$OUT_DIR"/docs_backup_*.tar.gz 2>/dev/null || true) +if [[ "${#backups[@]}" -gt "$RETENTION" ]]; then + for old in "${backups[@]:$RETENTION}"; do + rm -f "$old" + done +fi + +echo "Wrote: $ARCHIVE" +echo "Updated: $LATEST_REF" diff --git a/scripts/docs/docs_lint.sh b/scripts/docs/docs_lint.sh new file mode 100755 index 00000000..120f71c7 --- /dev/null +++ b/scripts/docs/docs_lint.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$ROOT_DIR" + +if ! command -v npx >/dev/null 2>&1; then + echo "npx not found; install Node.js to run markdown lint" >&2 + exit 2 +fi + +echo "Running markdown lint on tracked markdown files" + +scope_file="docs/standards/lint_scope.txt" +if [[ ! -f "$scope_file" ]]; then + echo "Missing lint scope file: $scope_file" >&2 + exit 2 +fi + +mapfile -t scope_paths < <(sed '/^\s*$/d; /^\s*#/d' "$scope_file") +files=() +for p in "${scope_paths[@]}"; do + [[ -f "$p" ]] && files+=("$p") +done + +if [[ "${#files[@]}" -eq 0 ]]; then + echo "No markdown files to lint" + exit 0 +fi + +npx -y markdownlint-cli2 --config .markdownlint.yml "${files[@]}" diff --git a/scripts/docs/docs_sync.sh b/scripts/docs/docs_sync.sh index 1dc4df24..fba63df5 100755 --- a/scripts/docs/docs_sync.sh +++ b/scripts/docs/docs_sync.sh @@ -105,8 +105,17 @@ doc_paths=( docs/consolidation/jupyter/notebooks_index_latest.csv docs/consolidation/pieces/PIECES_SYNC_LATEST.md docs/consolidation/pieces/pieces_index_latest.csv + docs/backups/LATEST.txt + docs/standards/DOCS_STYLE_GUIDE.md + docs/standards/DOC_TEMPLATE.md + docs/standards/lint_scope.txt PROJECT-MASTER-INDEX.md + .markdownlint.yml + .markdownlintignore + .github/workflows/docs-lint.yml scripts/docs/session_bootstrap.sh + scripts/docs/docs_backup.sh + scripts/docs/docs_lint.sh scripts/docs/jupyter_sync.sh scripts/docs/pieces_sync.sh scripts/docs/services_sync.sh diff --git a/scripts/docs/services_sync.sh b/scripts/docs/services_sync.sh index 5a3b8f96..310a2f91 100755 --- a/scripts/docs/services_sync.sh +++ b/scripts/docs/services_sync.sh @@ -14,9 +14,10 @@ Usage: bash scripts/docs/services_sync.sh [--dry-run] [--apply] [--probe-ports 39300,39301] Workflow: - 1) integration bootstrap status - 2) jupyter sync adapter - 3) pieces sync adapter + 1) docs backup + 2) integration bootstrap status + 3) jupyter sync adapter + 4) pieces sync adapter USAGE } @@ -49,6 +50,8 @@ while [[ $# -gt 0 ]]; do done if [[ "$DRY_RUN" -eq 1 ]]; then + echo "[dry-run] running: scripts/docs/docs_backup.sh --dry-run" + bash scripts/docs/docs_backup.sh --dry-run echo "[dry-run] running: scripts/docs/session_bootstrap.sh" bash scripts/docs/session_bootstrap.sh echo "[dry-run] running: scripts/docs/jupyter_sync.sh --dry-run" @@ -62,6 +65,7 @@ if [[ "$DRY_RUN" -eq 1 ]]; then exit 0 fi +bash scripts/docs/docs_backup.sh --apply bash scripts/docs/session_bootstrap.sh bash scripts/docs/jupyter_sync.sh --apply if [[ -n "$PROBE_PORTS" ]]; then