{"id":51224859,"url":"https://github.com/saagpatel/notion-operating-system","last_synced_at":"2026-06-28T10:03:30.763Z","repository":{"id":351317476,"uuid":"1195003262","full_name":"saagpatel/notion-operating-system","owner":"saagpatel","description":"Local CLI that turns Notion into a governed project OS — publish Markdown, sync portfolios, generate reviews from code","archived":false,"fork":false,"pushed_at":"2026-06-27T05:03:22.000Z","size":39279,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-27T06:19:20.427Z","etag":null,"topics":["automation","cli","markdown","notion","productivity","project-management","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saagpatel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":"docs/governance-incident-followup-runbook.md","roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-29T04:48:10.000Z","updated_at":"2026-06-27T04:58:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"9851461c-316a-4523-b808-11e9da6fceea","html_url":"https://github.com/saagpatel/notion-operating-system","commit_stats":null,"previous_names":["saagpatel/notion-operating-system"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/saagpatel/notion-operating-system","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fnotion-operating-system","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fnotion-operating-system/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fnotion-operating-system/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fnotion-operating-system/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saagpatel","download_url":"https://codeload.github.com/saagpatel/notion-operating-system/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fnotion-operating-system/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34884278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","cli","markdown","notion","productivity","project-management","typescript"],"created_at":"2026-06-28T10:03:30.254Z","updated_at":"2026-06-28T10:03:30.751Z","avatar_url":"https://github.com/saagpatel.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Notion Operating System\n\nA local automation layer that turns Notion into a real project and portfolio control system.\n\nThe system connects three surfaces: **Notion** (databases, dashboards, weekly reviews), **GitHub** (open PRs, workflow runs, issue/comment actuation), and **Vercel** (redeploy, rollback, promote). All automation is config-driven, auditable, and dry-run-first.\n\n## What It Does\n\n- Publishes local Markdown files into the right Notion pages and databases\n- Maintains a project control tower with derived PM signals (Operating Queue, Review Date, Evidence Freshness)\n- Syncs GitHub repo activity as external signals that inform project recommendations\n- Executes governed GitHub mutations (issues, labels, assignees, PR comments) through a dry-run → approval → live pipeline\n- Executes governed Vercel recovery actions (redeploy, rollback, promote) through the same pipeline\n- Generates weekly review packets, command-center pages, and governance health snapshots\n- Stores all rules, policies, and config in code so the setup is portable and versionable\n\n## First Operator Checkpoint\n\nBefore anything else, run the health report to see the current governance posture:\n\n```bash\nnpm run governance:health-report\n```\n\nThis shows live action-request coverage, execution status, dry-run staleness, and any attention items — without touching Notion or GitHub.\n\n## Install\n\nUse the install path that matches how much control you want:\n\n- **GitHub ref install**: install directly from a tagged GitHub ref\n- **GitHub release tarball install**: most locked-down verified artifact\n- **local repo development**: working on the repo itself, source-first workflow\n\n```bash\n# GitHub ref install\nnpm install github:saagpatel/notion-operating-system#v0.2.0\n\n# GitHub release tarball install\nnpm install https://github.com/saagpatel/notion-operating-system/releases/download/v0.2.0/notion-operating-system-0.2.0.tgz\n\n# local repo development\nnpm ci\n```\n\n## First Run (New Machine)\n\n```bash\nnpm ci\ncp .env.example .env\n# fill in NOTION_TOKEN (required), GITHUB_TOKEN (for signal sync),\n# GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY_PEM (for governed GitHub writes)\nnpm run doctor\nnpm run verify\n```\n\nThen start with a dry-run publish:\n\n```bash\nnpm run publish:notion -- --destination weekly_reviews --file ./notes/weekly.md\n```\n\nAdd `--live` only when you are satisfied with the dry-run output.\n\n## Main Workflows\n\n### 1. Refresh the control tower\n\n```bash\n# Preview what would change\nnpm run portfolio-audit:control-tower-sync\n\n# Write derived PM signals and refresh the command-center page\nnpm run portfolio-audit:control-tower-sync -- --live\n```\n\n### 2. Publish content into Notion\n\n```bash\n# Dry run (default)\nnpm run publish:notion -- --destination weekly_reviews --file path/to/review.md\n\n# Live write\nnpm run publish:notion -- --destination weekly_reviews --file path/to/review.md --live\n```\n\n### 3. Review stale active projects\n\n```bash\nnpm run control-tower:stale-active-rescue\n```\n\nThe stale-active rescue command is safe by default. Use `--limit \u003ccount\u003e` to\nscope a dry run, add `--live` to apply the planned row updates, and add\n`--missing-repos-only` when you only want to move missing local-repo mappings\ninto a decision posture.\n\nThis is read-only. It groups stale `Active Build` projects by the most useful first repair reason and returns the next operator move before anyone changes project status.\n\n### 4. Review the decision queue and repo mappings\n\n```bash\nnpm run control-tower:repo-mapping-audit\n```\n\nThe repo-mapping audit is read-only by default. It joins `Needs Decision`\nrows, local repo path evidence under `/Users/d/Projects`, and GitHub\nexternal-source coverage so mapping cleanup does not depend on stale chat\nmemory. Add `--live-normalize-local-paths` only after the dry run shows\ndeterministic Local Path fixes.\n\n### 5. Recover overdue portfolio reviews\n\n```bash\nnpm run control-tower:review-recovery\n```\n\nReview recovery is dry-run by default. Use `--limit \u003ccount\u003e` to scope a batch,\nadd `--include-metadata-gaps` when you also want to patch missing Next Move or\nLast Active rows, and add `--live` only after the dry-run plan matches the\nintended portfolio cleanup.\n\n### 6. Generate the weekly review packet\n\n```bash\nnpm run portfolio-audit:review-packet -- --live\n```\n\nRun this **before** any command that patches the \"latest weekly\" managed section (signals, recommendations, action-request sync). If the current week's page does not exist yet, those commands land on the wrong weekly page.\n\n### 7. Sync GitHub signals\n\n```bash\n# Recompute from existing Notion rows (no GitHub fetch)\nnpm run portfolio-audit:external-signal-sync\n\n# Fetch fresh data from GitHub\nnpm run portfolio-audit:external-signal-sync -- --provider github --live\n```\n\n### 8. Governed GitHub actions (dry-run → approval → live)\n\nGitHub mutations follow a strict three-step pipeline. Never skip steps.\n\n**Step 1 — Dry run** (validates, checks policy, computes what would change):\n```bash\nnpm run portfolio-audit:action-dry-run -- --request \u003caction-request-page-id\u003e\n```\n\n**Step 2 — Approval**: In Notion, set the action request row to `Status = Approved`, fill in `Approver` and `Decided At`.\n\n**Step 3 — Live execution**:\n```bash\nnpm run portfolio-audit:action-runner -- --mode live --request \u003caction-request-page-id\u003e\n```\n\nAfter execution, sync governance summaries:\n```bash\nnpm run portfolio-audit:action-request-sync -- --live\n```\n\nSupported actions: `github.create_issue`, `github.update_issue`, `github.set_issue_labels`, `github.set_issue_assignees`, `github.add_issue_comment`, `github.comment_pull_request`.\n\n### 9. Governed Vercel actions\n\nSame three-step pipeline as GitHub. Supported actions: `vercel.redeploy`, `vercel.rollback`, `vercel.promote`.\n\nRequires `VERCEL_TOKEN` in your `.env`. The live gate also requires a successful dry run within the last 24 hours.\n\n### 10. Weekly live sequence (correct order)\n\nUse the guarded orchestrator for a full weekly pass:\n\n```bash\nnpm run maintenance:weekly-refresh -- --today \"$(date +%F)\" --signal-source-limit 5 --signal-max-events-per-source 5 --summary-first\nnpm run maintenance:weekly-refresh -- --today \"$(date +%F)\" --signal-source-limit 5 --signal-max-events-per-source 5 --live --confirm-full-live --summary-first\n```\n\nFor repair work, run a single lane instead of the full weekly live pass:\n\n```bash\nnpm run maintenance:weekly-refresh -- --today \"$(date +%F)\" --only intelligence-sync --step-timeout-minutes 5 --max-step-attempts 2 --summary-first\nnpm run maintenance:weekly-refresh -- --today \"$(date +%F)\" --only external-signals --max-project-pages 10 --project-offset 0 --summary-first\n```\n\n`--fast` also applies a conservative `--project-concurrency 2` for project brief write loops. Lower it to `1` if Notion starts rate-limiting; raise batch size before raising concurrency.\n\nThe older manual sequence remains useful when you need to run one command directly:\n\n```bash\nnpm run portfolio-audit:control-tower-sync -- --live          # 1. derive PM signals\nnpm run portfolio-audit:review-packet -- --live               # 2. create/refresh weekly page\nnpm run portfolio-audit:external-signal-sync -- --provider github --live  # 3. sync GitHub signals\nnpm run portfolio-audit:recommendation-run -- --type weekly --live        # 4. run recommendations\nnpm run portfolio-audit:action-request-sync -- --live         # 5. sync governance summaries\n```\n\n## Common Commands\n\n| Command | What it does |\n|---|---|\n| `npm run governance:health-report` | Governance health snapshot (no writes) |\n| `npm run maintenance:weekly-refresh -- --summary-first` | Weekly maintenance preflight with compact troubleshooting output |\n| `npm run destinations:check` | List configured Notion destination aliases |\n| `npm run destinations:resolve` | Resolve and persist Notion IDs for all destinations |\n| `npm run portfolio-audit:control-tower-sync` | Refresh derived PM signals (dry-run) |\n| `npm run control-tower:review-recovery` | Recover overdue review rows and small review metadata gaps; dry-run by default |\n| `npm run control-tower:stale-active-rescue` | Stale Active Build project rescue report and scoped updater; dry-run by default, live only with `--live` |\n| `npm run control-tower:repo-mapping-audit` | Read-only decision queue and repo/source mapping cleanup packet |\n| `npm run bridge-db:sync -- --shipped-only` | Sync only bridge-db `SHIPPED` rows into Build Log; omit the filter to process both queues |\n| `npm run control-tower:schema-report` | Analyze property usage before schema cleanup or deletion |\n| `npm run portfolio-audit:review-packet` | Generate weekly review packet (dry-run) |\n| `npm run portfolio-audit:external-signal-sync -- --provider github --live` | Sync GitHub signals (live) |\n| `npm run portfolio-audit:recommendation-run -- --type weekly` | Weekly recommendations (dry-run) |\n| `npm run portfolio-audit:action-request-sync -- --live` | Sync governance summaries |\n| `npm run portfolio-audit:action-dry-run -- --request \u003cid\u003e` | Dry-run a governed action |\n| `npm run portfolio-audit:action-runner -- --mode live --request \u003cid\u003e` | Execute an approved action |\n| `npm run portfolio-audit:operational-rollout` | Operational rollout plan |\n| `npm run typecheck` | TypeScript type checking |\n| `npm test` | Run Vitest tests |\n| `npm run verify` | Full local release gate (typecheck + test + build + smoke) |\n| `npm run verify:fresh-clone` | Fresh-machine confidence check |\n| `npm run doctor` | Verify local setup |\n\n## Key Config Files\n\n| File | Contains |\n|---|---|\n| `config/destinations.json` | Notion destination aliases and resolved IDs |\n| `config/local-portfolio-control-tower.json` | Control tower rules, review cadence, runner limits, live gating |\n| `config/local-portfolio-governance-policies.json` | Action policies for governed external mutations |\n| `config/local-portfolio-actuation-targets.json` | GitHub/Vercel allowlist with per-target permissions |\n| `config/local-portfolio-views.json` | Saved view definitions |\n\n## Safety Defaults\n\n- **Dry-run first.** Every command defaults to dry-run unless `--live` is explicitly passed.\n- **Governed writes only.** GitHub and Vercel mutations require: approved action request, non-expired request, active target, and a successful dry run (max 24 hours old).\n- **No hardcoded tokens.** All tokens come from environment variables.\n- **Additive posture.** Labels and assignees are additive-only — removal requires a new desired-state request.\n- **Compensation is manual.** There is no automated compensation runner. Corrections are operator-driven.\n\n## Environment Variables\n\n| Variable | Required | Purpose |\n|---|---|---|\n| `NOTION_TOKEN` | Yes | Notion integration token |\n| `GITHUB_TOKEN` | For signal sync | GitHub PAT for polling PRs and workflow runs |\n| `GITHUB_APP_ID` | For governed GitHub writes | GitHub App ID |\n| `GITHUB_APP_PRIVATE_KEY_PEM` | For governed GitHub writes | GitHub App private key |\n| `GITHUB_APP_WEBHOOK_SECRET` | For webhook verification | Shared secret for delivery validation |\n| `VERCEL_TOKEN` | For governed Vercel writes | Vercel API token |\n| `NOTION_LOG_DIR` | Optional | Log directory (default: `./logs`) |\n| `NOTION_DESTINATIONS_PATH` | Optional | Destinations config path (default: `./config/destinations.json`) |\n\n## Sandbox Profile Discipline\n\nUse a `sandbox` profile as the default proving ground before live changes that touch control-tower, signals, governance, rollout, or profile flows.\n\n```bash\nnpm run sandbox:smoke\nnotion-os --profile sandbox doctor\n```\n\nThe sandbox profile isolates tokens and Notion targets from your primary profile. The sandbox doctor fails if the sandbox token matches the primary token or if any sandbox target overlaps primary targets.\n\nSee [docs/sandbox-rehearsal-runbook.md](docs/sandbox-rehearsal-runbook.md) for the full rehearsal path.\n\n## Project Docs\n\n- [First-run onboarding](docs/first-run.md)\n- [Architecture overview](docs/architecture-overview.md)\n- [GitHub governed actions runbook](docs/github-governed-actions-runbook.md)\n- [Governance sync failure troubleshooting](docs/governance-sync-failure-troubleshooting.md)\n- [Governance incident follow-up runbook](docs/governance-incident-followup-runbook.md)\n- [Maintenance playbook](docs/maintenance-playbook.md)\n- [Sandbox rehearsal runbook](docs/sandbox-rehearsal-runbook.md) — proving path before risky live writes\n- [Release process](docs/release-process.md)\n- [Roadmap](docs/notion-roadmap.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fnotion-operating-system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaagpatel%2Fnotion-operating-system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fnotion-operating-system/lists"}