@stravica-ai/digital-operator-pa 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +170 -0
- package/bin/desk +9 -0
- package/bin/distill +2 -0
- package/bin/estate-sync +2 -0
- package/bin/launch +2 -0
- package/bin/memory-sync +2 -0
- package/bin/migrate-inspect +2 -0
- package/bin/pa +2 -0
- package/bin/pa-coordinator-hook +2 -0
- package/bin/pa-init +2 -0
- package/bin/research +2 -0
- package/bin/scheduler +2 -0
- package/bin/secrets +2 -0
- package/bin/slice +2 -0
- package/bin/smoke +9 -0
- package/bin/sync +2 -0
- package/dist/engineering-pa-cli/README.md +205 -0
- package/dist/engineering-pa-cli/bin/estate-sync +2 -0
- package/dist/engineering-pa-cli/bin/launch +2 -0
- package/dist/engineering-pa-cli/bin/pa +2 -0
- package/dist/engineering-pa-cli/bin/pa-coordinator-hook +12 -0
- package/dist/engineering-pa-cli/bin/research +2 -0
- package/dist/engineering-pa-cli/bin/scheduler +2 -0
- package/dist/engineering-pa-cli/bin/secrets +2 -0
- package/dist/engineering-pa-cli/bin/smoke +9 -0
- package/dist/engineering-pa-cli/bin/sync +2 -0
- package/dist/engineering-pa-cli/config/coordinator-allowlist.json +118 -0
- package/dist/engineering-pa-cli/docs/coordinator-hook.md +211 -0
- package/dist/engineering-pa-cli/docs/estate-sync.md +412 -0
- package/dist/engineering-pa-cli/docs/gsc.md +175 -0
- package/dist/engineering-pa-cli/docs/lint-linkedin.md +139 -0
- package/dist/engineering-pa-cli/docs/secrets.md +221 -0
- package/dist/engineering-pa-cli/docs/smoke.md +113 -0
- package/dist/engineering-pa-cli/docs/staging-alias.md +114 -0
- package/dist/engineering-pa-cli/index.mjs +17 -0
- package/dist/engineering-pa-cli/package.json +37 -0
- package/dist/engineering-pa-cli/src/autonomy/cli.mjs +329 -0
- package/dist/engineering-pa-cli/src/autonomy/envelope.mjs +301 -0
- package/dist/engineering-pa-cli/src/coordinator-hook/cli.mjs +140 -0
- package/dist/engineering-pa-cli/src/coordinator-hook/config.mjs +134 -0
- package/dist/engineering-pa-cli/src/coordinator-hook/message.mjs +47 -0
- package/dist/engineering-pa-cli/src/coordinator-hook/policy.mjs +211 -0
- package/dist/engineering-pa-cli/src/coordinator-hook/repo-root.mjs +44 -0
- package/dist/engineering-pa-cli/src/coordinator-hook/self.mjs +30 -0
- package/dist/engineering-pa-cli/src/environment/cli.mjs +287 -0
- package/dist/engineering-pa-cli/src/environment/probes.mjs +302 -0
- package/dist/engineering-pa-cli/src/gsc/auth.mjs +148 -0
- package/dist/engineering-pa-cli/src/gsc/cli.mjs +93 -0
- package/dist/engineering-pa-cli/src/gsc/cloudflare.mjs +318 -0
- package/dist/engineering-pa-cli/src/gsc/commands/add-property.mjs +70 -0
- package/dist/engineering-pa-cli/src/gsc/commands/list-properties.mjs +33 -0
- package/dist/engineering-pa-cli/src/gsc/commands/pull-analytics.mjs +130 -0
- package/dist/engineering-pa-cli/src/gsc/commands/submit-sitemap.mjs +41 -0
- package/dist/engineering-pa-cli/src/gsc/commands/verify-via-cf-dns.mjs +189 -0
- package/dist/engineering-pa-cli/src/knowledge/call-log.mjs +59 -0
- package/dist/engineering-pa-cli/src/knowledge/cli.mjs +242 -0
- package/dist/engineering-pa-cli/src/knowledge/eval.mjs +446 -0
- package/dist/engineering-pa-cli/src/knowledge/formatters.mjs +331 -0
- package/dist/engineering-pa-cli/src/knowledge/graph.mjs +710 -0
- package/dist/engineering-pa-cli/src/launch/README.md +214 -0
- package/dist/engineering-pa-cli/src/launch/cli.mjs +51 -0
- package/dist/engineering-pa-cli/src/launch/commands/launch.mjs +106 -0
- package/dist/engineering-pa-cli/src/launch/identity.mjs +43 -0
- package/dist/engineering-pa-cli/src/launch/planner.mjs +44 -0
- package/dist/engineering-pa-cli/src/launch/repo-root.mjs +53 -0
- package/dist/engineering-pa-cli/src/launch/runner.mjs +147 -0
- package/dist/engineering-pa-cli/src/launch/task-loader.mjs +85 -0
- package/dist/engineering-pa-cli/src/lint/cli.mjs +61 -0
- package/dist/engineering-pa-cli/src/lint/commands/linkedin.mjs +133 -0
- package/dist/engineering-pa-cli/src/lint/detectors.mjs +90 -0
- package/dist/engineering-pa-cli/src/lint/linter.mjs +69 -0
- package/dist/engineering-pa-cli/src/lint/reporter.mjs +32 -0
- package/dist/engineering-pa-cli/src/lint/rules.mjs +132 -0
- package/dist/engineering-pa-cli/src/pa/cli.mjs +369 -0
- package/dist/engineering-pa-cli/src/pa/doc-groups.mjs +164 -0
- package/dist/engineering-pa-cli/src/pa/io.mjs +80 -0
- package/dist/engineering-pa-cli/src/pa/project-cli.mjs +385 -0
- package/dist/engineering-pa-cli/src/pa/projects.mjs +352 -0
- package/dist/engineering-pa-cli/src/pa/repo-root.mjs +64 -0
- package/dist/engineering-pa-cli/src/pa/session.mjs +254 -0
- package/dist/engineering-pa-cli/src/pa/work-cli.mjs +164 -0
- package/dist/engineering-pa-cli/src/pa/work.mjs +196 -0
- package/dist/engineering-pa-cli/src/pa/workstreams.mjs +201 -0
- package/dist/engineering-pa-cli/src/research/README.md +360 -0
- package/dist/engineering-pa-cli/src/research/briefs/extractor.md +103 -0
- package/dist/engineering-pa-cli/src/research/briefs/searcher.md +113 -0
- package/dist/engineering-pa-cli/src/research/briefs/synthesizer.md +124 -0
- package/dist/engineering-pa-cli/src/research/briefs/verifier.md +86 -0
- package/dist/engineering-pa-cli/src/research/cli.mjs +141 -0
- package/dist/engineering-pa-cli/src/research/commands/gates.mjs +176 -0
- package/dist/engineering-pa-cli/src/research/commands/list.mjs +56 -0
- package/dist/engineering-pa-cli/src/research/commands/mark.mjs +97 -0
- package/dist/engineering-pa-cli/src/research/commands/paths.mjs +69 -0
- package/dist/engineering-pa-cli/src/research/commands/prune.mjs +86 -0
- package/dist/engineering-pa-cli/src/research/commands/run.mjs +94 -0
- package/dist/engineering-pa-cli/src/research/commands/show.mjs +43 -0
- package/dist/engineering-pa-cli/src/research/docs/operator-present-flow.md +120 -0
- package/dist/engineering-pa-cli/src/research/format.mjs +59 -0
- package/dist/engineering-pa-cli/src/research/promote.mjs +260 -0
- package/dist/engineering-pa-cli/src/research/schema/finding.schema.json +55 -0
- package/dist/engineering-pa-cli/src/research/schema/gates.schema.json +34 -0
- package/dist/engineering-pa-cli/src/research/schema/manifest.schema.json +59 -0
- package/dist/engineering-pa-cli/src/research/schema/plan.schema.json +41 -0
- package/dist/engineering-pa-cli/src/research/schema/sources.schema.json +31 -0
- package/dist/engineering-pa-cli/src/research/store/findings.mjs +61 -0
- package/dist/engineering-pa-cli/src/research/store/gates.mjs +73 -0
- package/dist/engineering-pa-cli/src/research/store/index.mjs +312 -0
- package/dist/engineering-pa-cli/src/research/store/manifest.mjs +56 -0
- package/dist/engineering-pa-cli/src/research/store/plan.mjs +59 -0
- package/dist/engineering-pa-cli/src/research/store/sources.mjs +44 -0
- package/dist/engineering-pa-cli/src/research/store/validate.mjs +92 -0
- package/dist/engineering-pa-cli/src/research/workflows/research-normal.js +573 -0
- package/dist/engineering-pa-cli/src/scheduler/cli.mjs +197 -0
- package/dist/engineering-pa-cli/src/secrets/cli.mjs +254 -0
- package/dist/engineering-pa-cli/src/secrets/commands/backup-template.mjs +67 -0
- package/dist/engineering-pa-cli/src/secrets/commands/backup.mjs +85 -0
- package/dist/engineering-pa-cli/src/secrets/commands/delete.mjs +58 -0
- package/dist/engineering-pa-cli/src/secrets/commands/find.mjs +36 -0
- package/dist/engineering-pa-cli/src/secrets/commands/get.mjs +49 -0
- package/dist/engineering-pa-cli/src/secrets/commands/init.mjs +69 -0
- package/dist/engineering-pa-cli/src/secrets/commands/list.mjs +37 -0
- package/dist/engineering-pa-cli/src/secrets/commands/rotate.mjs +46 -0
- package/dist/engineering-pa-cli/src/secrets/commands/set.mjs +123 -0
- package/dist/engineering-pa-cli/src/secrets/commands/status.mjs +146 -0
- package/dist/engineering-pa-cli/src/secrets/commands/vaults.mjs +57 -0
- package/dist/engineering-pa-cli/src/secrets/commands/verify.mjs +143 -0
- package/dist/engineering-pa-cli/src/secrets/vault.mjs +766 -0
- package/dist/engineering-pa-cli/src/smoke/checks.mjs +199 -0
- package/dist/engineering-pa-cli/src/smoke/cli.mjs +108 -0
- package/dist/engineering-pa-cli/src/smoke/commands/run.mjs +237 -0
- package/dist/engineering-pa-cli/src/smoke/runner.mjs +191 -0
- package/dist/engineering-pa-cli/src/staging-alias/cli.mjs +91 -0
- package/dist/engineering-pa-cli/src/staging-alias/cloudflare.mjs +380 -0
- package/dist/engineering-pa-cli/src/staging-alias/commands/list.mjs +36 -0
- package/dist/engineering-pa-cli/src/staging-alias/commands/set.mjs +188 -0
- package/dist/engineering-pa-cli/src/staging-alias/commands/status.mjs +113 -0
- package/dist/engineering-pa-cli/src/staging-alias/commands/unset.mjs +95 -0
- package/dist/engineering-pa-cli/src/staging-alias/sites.mjs +105 -0
- package/dist/engineering-pa-cli/src/sync/cli.mjs +151 -0
- package/dist/engineering-pa-cli/src/sync/git.mjs +149 -0
- package/dist/engineering-pa-cli/src/sync/lock.mjs +30 -0
- package/dist/engineering-pa-cli/src/sync/regenerated-artifacts.mjs +114 -0
- package/dist/engineering-pa-cli/src/sync/registry-scope.mjs +260 -0
- package/dist/engineering-pa-cli/src/sync/run.mjs +531 -0
- package/dist/engineering-pa-cli/src/sync/runner.mjs +62 -0
- package/dist/engineering-pa-cli/src/sync/runs-digest.mjs +138 -0
- package/dist/engineering-pa-core/README.md +60 -0
- package/dist/engineering-pa-core/bin/desk +9 -0
- package/dist/engineering-pa-core/bin/distill +2 -0
- package/dist/engineering-pa-core/bin/memory-sync +2 -0
- package/dist/engineering-pa-core/bin/slice +2 -0
- package/dist/engineering-pa-core/docs/autonomy-envelope-tracker.md +111 -0
- package/dist/engineering-pa-core/docs/blueprints/README.md +45 -0
- package/dist/engineering-pa-core/docs/blueprints/docker-services/blueprint.md +168 -0
- package/dist/engineering-pa-core/docs/blueprints/git-identity/blueprint.md +116 -0
- package/dist/engineering-pa-core/docs/blueprints/ideas/custom-workspace-views.md +9 -0
- package/dist/engineering-pa-core/docs/blueprints/ideas/knowledge-domain-patterns.md +15 -0
- package/dist/engineering-pa-core/docs/blueprints/ideas/office-integration.md +11 -0
- package/dist/engineering-pa-core/docs/blueprints/ideas/team-scaling.md +9 -0
- package/dist/engineering-pa-core/docs/blueprints/ideas/work-personal-separation.md +9 -0
- package/dist/engineering-pa-core/docs/blueprints/scheduled-distillation/blueprint.md +129 -0
- package/dist/engineering-pa-core/docs/blueprints/tool-integration/blueprint.md +110 -0
- package/dist/engineering-pa-core/docs/commands/init.md +159 -0
- package/dist/engineering-pa-core/docs/commands/schedule.md +98 -0
- package/dist/engineering-pa-core/docs/commands/upgrade.md +67 -0
- package/dist/engineering-pa-core/docs/entity-location-map.md +93 -0
- package/dist/engineering-pa-core/docs/knowledge-scaffold.md +121 -0
- package/dist/engineering-pa-core/docs/lock.md +155 -0
- package/dist/engineering-pa-core/docs/memory-sync.md +28 -0
- package/dist/engineering-pa-core/docs/pa-operating-model.md +457 -0
- package/dist/engineering-pa-core/docs/scheduling.md +35 -0
- package/dist/engineering-pa-core/docs/standards/README.md +24 -0
- package/dist/engineering-pa-core/docs/standards/briefing-contract.md +161 -0
- package/dist/engineering-pa-core/docs/standards/tooling.md +240 -0
- package/dist/engineering-pa-core/docs/tools/distill.md +230 -0
- package/dist/engineering-pa-core/docs/tools/memory-sync.md +98 -0
- package/dist/engineering-pa-core/docs/tools/scheduler.md +243 -0
- package/dist/engineering-pa-core/docs/tools/slice.md +150 -0
- package/dist/engineering-pa-core/docs/upstream-issue-filing.md +88 -0
- package/dist/engineering-pa-core/docs/working-directory.md +29 -0
- package/dist/engineering-pa-core/docs/workspace-operations.md +46 -0
- package/dist/engineering-pa-core/index.mjs +21 -0
- package/dist/engineering-pa-core/knowledge/README.md +53 -0
- package/dist/engineering-pa-core/knowledge/canonical/.gitkeep +0 -0
- package/dist/engineering-pa-core/knowledge/content-voice/README.md +64 -0
- package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-baseline.md +133 -0
- package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-shape.md +58 -0
- package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-taxonomy.md +33 -0
- package/dist/engineering-pa-core/knowledge/content-voice/content-pipeline-routing.md +58 -0
- package/dist/engineering-pa-core/knowledge/content-voice/new-tell-capture-procedure.md +40 -0
- package/dist/engineering-pa-core/knowledge/content-voice/voice-guide-shape.md +43 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/README.md +34 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/briefing-contract.md +77 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/delegation-modes.md +84 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/dispatch-envelope.md +238 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/task-groups-and-orchestrators.md +62 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/team-improvement-loop.md +48 -0
- package/dist/engineering-pa-core/knowledge/delegation-dispatch/tool-development-policy.md +48 -0
- package/dist/engineering-pa-core/knowledge/engineering-discipline/README.md +33 -0
- package/dist/engineering-pa-core/knowledge/engineering-discipline/blast-radius-and-safety.md +50 -0
- package/dist/engineering-pa-core/knowledge/engineering-discipline/investigate-root-causes.md +48 -0
- package/dist/engineering-pa-core/knowledge/engineering-discipline/role-ladder.md +57 -0
- package/dist/engineering-pa-core/knowledge/engineering-discipline/verify-runtime-behaviour.md +53 -0
- package/dist/engineering-pa-core/knowledge/engineering-discipline/worktree-isolation.md +50 -0
- package/dist/engineering-pa-core/knowledge/knowledge-memory/README.md +33 -0
- package/dist/engineering-pa-core/knowledge/knowledge-memory/claude-md-hygiene.md +47 -0
- package/dist/engineering-pa-core/knowledge/knowledge-memory/journal-and-self-improvement.md +53 -0
- package/dist/engineering-pa-core/knowledge/knowledge-memory/knowledge-retrieval-discipline.md +62 -0
- package/dist/engineering-pa-core/knowledge/knowledge-memory/librarian-synthesis-mandate.md +56 -0
- package/dist/engineering-pa-core/knowledge/knowledge-memory/staging-and-observations.md +58 -0
- package/dist/engineering-pa-core/knowledge/operator-interface/README.md +32 -0
- package/dist/engineering-pa-core/knowledge/operator-interface/communication-style.md +33 -0
- package/dist/engineering-pa-core/knowledge/operator-interface/escalation-and-correction.md +45 -0
- package/dist/engineering-pa-core/knowledge/operator-interface/push-back-discipline.md +42 -0
- package/dist/engineering-pa-core/knowledge/operator-interface/session-boot-and-end.md +56 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/README.md +37 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/desk-cli-reference.md +52 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/environment-awareness.md +91 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/mcp-servers-catalogue.md +52 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/pa-cli-reference.md +55 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/scheduling-and-launchd.md +56 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/tool-discovery-discipline.md +49 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/working-directory-vs-project-root.md +43 -0
- package/dist/engineering-pa-core/knowledge/platform-tooling/workspace-server.md +51 -0
- package/dist/engineering-pa-core/knowledge/raw/.gitkeep +0 -0
- package/dist/engineering-pa-core/knowledge/scaffold/domains.json +5 -0
- package/dist/engineering-pa-core/knowledge/schema/.gitkeep +0 -0
- package/dist/engineering-pa-core/knowledge/work-management/README.md +33 -0
- package/dist/engineering-pa-core/knowledge/work-management/desk-cli.md +84 -0
- package/dist/engineering-pa-core/knowledge/work-management/progress-md.md +48 -0
- package/dist/engineering-pa-core/knowledge/work-management/projects.md +64 -0
- package/dist/engineering-pa-core/knowledge/work-management/spawn-log.md +48 -0
- package/dist/engineering-pa-core/knowledge/work-management/work-items.md +67 -0
- package/dist/engineering-pa-core/package.json +26 -0
- package/dist/engineering-pa-core/roles/agent-ops/definition.md +79 -0
- package/dist/engineering-pa-core/roles/dispatch-briefer/definition.md +195 -0
- package/dist/engineering-pa-core/roles/librarian/definition.md +176 -0
- package/dist/engineering-pa-core/roles/pa/definition.md +93 -0
- package/dist/engineering-pa-core/roles/system-admin/definition.md +106 -0
- package/dist/engineering-pa-core/roles/tool-developer/definition.md +116 -0
- package/dist/engineering-pa-core/roles/writer/definition.md +130 -0
- package/dist/engineering-pa-core/schema/autonomy-envelope.schema.json +61 -0
- package/dist/engineering-pa-core/schema/project.json +114 -0
- package/dist/engineering-pa-core/schema/schedule.json +63 -0
- package/dist/engineering-pa-core/schema/work-item.json +92 -0
- package/dist/engineering-pa-core/src/config/pa-package-name.mjs +30 -0
- package/dist/engineering-pa-core/src/desk/cli.mjs +95 -0
- package/dist/engineering-pa-core/src/desk/commands.mjs +398 -0
- package/dist/engineering-pa-core/src/desk/format.mjs +84 -0
- package/dist/engineering-pa-core/src/desk/repo.mjs +172 -0
- package/dist/engineering-pa-core/src/desk/team-scope.mjs +142 -0
- package/dist/engineering-pa-core/src/distill/cli.mjs +112 -0
- package/dist/engineering-pa-core/src/distill/prereqs.mjs +171 -0
- package/dist/engineering-pa-core/src/distill/prompt.mjs +74 -0
- package/dist/engineering-pa-core/src/distill/run.mjs +230 -0
- package/dist/engineering-pa-core/src/distill/runner.mjs +86 -0
- package/dist/engineering-pa-core/src/distill/staging.mjs +59 -0
- package/dist/engineering-pa-core/src/knowledge/retrieval/backlink-indexer.mjs +154 -0
- package/dist/engineering-pa-core/src/knowledge/retrieval/graph-builder.mjs +186 -0
- package/dist/engineering-pa-core/src/knowledge/retrieval/index-builder.mjs +225 -0
- package/dist/engineering-pa-core/src/knowledge/retrieval/query.mjs +263 -0
- package/dist/engineering-pa-core/src/lock/lock.mjs +202 -0
- package/dist/engineering-pa-core/src/memory-sync/cli-support.mjs +12 -0
- package/dist/engineering-pa-core/src/memory-sync/cli.mjs +56 -0
- package/dist/engineering-pa-core/src/memory-sync/commands/pull.mjs +44 -0
- package/dist/engineering-pa-core/src/memory-sync/commands/push.mjs +46 -0
- package/dist/engineering-pa-core/src/memory-sync/mirror.mjs +114 -0
- package/dist/engineering-pa-core/src/memory-sync/repo.mjs +65 -0
- package/dist/engineering-pa-core/src/scheduler/detect.mjs +111 -0
- package/dist/engineering-pa-core/src/scheduler/host.mjs +38 -0
- package/dist/engineering-pa-core/src/scheduler/index.mjs +13 -0
- package/dist/engineering-pa-core/src/scheduler/install.mjs +854 -0
- package/dist/engineering-pa-core/src/scheduler/list.mjs +168 -0
- package/dist/engineering-pa-core/src/scheduler/remove.mjs +176 -0
- package/dist/engineering-pa-core/src/scheduler/verify.mjs +435 -0
- package/dist/engineering-pa-core/src/session-boot/autonomy-injection.mjs +84 -0
- package/dist/engineering-pa-core/src/slice/cli.mjs +139 -0
- package/dist/engineering-pa-core/src/slice/inputs.mjs +174 -0
- package/dist/engineering-pa-core/src/slice/prompt.mjs +94 -0
- package/dist/engineering-pa-core/src/slice/prompts/dave-boot.md +91 -0
- package/dist/engineering-pa-core/src/slice/run.mjs +334 -0
- package/dist/engineering-pa-core-extensions-atlassian/README.md +31 -0
- package/dist/engineering-pa-core-extensions-atlassian/index.mjs +9 -0
- package/dist/engineering-pa-core-extensions-atlassian/package.json +19 -0
- package/dist/engineering-pa-core-extensions-n8n/README.md +29 -0
- package/dist/engineering-pa-core-extensions-n8n/index.mjs +8 -0
- package/dist/engineering-pa-core-extensions-n8n/package.json +19 -0
- package/dist/engineering-pa-librarian/README.md +38 -0
- package/dist/engineering-pa-librarian/index.mjs +12 -0
- package/dist/engineering-pa-librarian/package.json +19 -0
- package/dist/engineering-pa-migrate-inspect/README.md +131 -0
- package/dist/engineering-pa-migrate-inspect/bin/migrate-inspect +2 -0
- package/dist/engineering-pa-migrate-inspect/package.json +21 -0
- package/dist/engineering-pa-migrate-inspect/src/age-key-migrate.mjs +83 -0
- package/dist/engineering-pa-migrate-inspect/src/cli.mjs +97 -0
- package/dist/engineering-pa-migrate-inspect/src/inspector.mjs +237 -0
- package/dist/engineering-pa-migrate-inspect/src/platforms/linux.mjs +87 -0
- package/dist/engineering-pa-migrate-inspect/src/platforms/macos.mjs +105 -0
- package/dist/engineering-pa-migrate-inspect/src/runner.mjs +87 -0
- package/dist/engineering-pa-runbook/README.md +103 -0
- package/dist/engineering-pa-runbook/package.json +18 -0
- package/dist/engineering-pa-runbook/reference/dex-template.runbook.json +66 -0
- package/dist/engineering-pa-runbook/reference/hq-dave.runbook.json +69 -0
- package/dist/engineering-pa-runbook/reference/smarthome01.runbook.json +92 -0
- package/dist/engineering-pa-runbook/schema/inspection.schema.json +113 -0
- package/dist/engineering-pa-runbook/schema/runbook.schema.json +67 -0
- package/dist/engineering-pa-runbook/src/validator.mjs +167 -0
- package/dist/engineering-pa-scaffold/README.md +164 -0
- package/dist/engineering-pa-scaffold/bin/pa-init +2 -0
- package/dist/engineering-pa-scaffold/index.mjs +42 -0
- package/dist/engineering-pa-scaffold/package.json +22 -0
- package/dist/engineering-pa-scaffold/src/cli.mjs +115 -0
- package/dist/engineering-pa-scaffold/src/commands/init.mjs +169 -0
- package/dist/engineering-pa-scaffold/src/generator.mjs +354 -0
- package/dist/engineering-pa-scaffold/src/prompts.mjs +125 -0
- package/dist/engineering-pa-scaffold/src/runner.mjs +142 -0
- package/dist/engineering-pa-scaffold/templates/CLAUDE.md.template +196 -0
- package/dist/engineering-pa-scaffold/templates/operator-README.md.template +44 -0
- package/dist/engineering-pa-types-engineering/README.md +35 -0
- package/dist/engineering-pa-types-engineering/docs/commands/product-build.md +120 -0
- package/dist/engineering-pa-types-engineering/index.mjs +9 -0
- package/dist/engineering-pa-types-engineering/package.json +19 -0
- package/dist/engineering-pa-types-engineering/roles/product-engineer/definition.md +650 -0
- package/dist/engineering-pa-types-engineering/roles/product-engineer/templates/build-spec.md +82 -0
- package/dist/engineering-pa-types-engineering/roles/product-engineer/templates/preflight-checklist.md +158 -0
- package/dist/engineering-pa-types-engineering/roles/product-engineer/templates/worker-brief.md +130 -0
- package/dist/engineering-pa-workspace/README.md +197 -0
- package/dist/engineering-pa-workspace/app/assets/md.js +187 -0
- package/dist/engineering-pa-workspace/app/assets/modal.js +120 -0
- package/dist/engineering-pa-workspace/app/assets/theme.css +132 -0
- package/dist/engineering-pa-workspace/app/assets/theme.js +159 -0
- package/dist/engineering-pa-workspace/app/banner.js +320 -0
- package/dist/engineering-pa-workspace/app/delegations.html +345 -0
- package/dist/engineering-pa-workspace/app/home.html +1060 -0
- package/dist/engineering-pa-workspace/app/index.html +361 -0
- package/dist/engineering-pa-workspace/app/knowledge-map.html +163 -0
- package/dist/engineering-pa-workspace/app/knowledge.html +304 -0
- package/dist/engineering-pa-workspace/app/nav.json +75 -0
- package/dist/engineering-pa-workspace/app/notes.html +199 -0
- package/dist/engineering-pa-workspace/app/onboarding.html +592 -0
- package/dist/engineering-pa-workspace/app/profile.html +243 -0
- package/dist/engineering-pa-workspace/app/project-detail.html +432 -0
- package/dist/engineering-pa-workspace/app/projects.html +297 -0
- package/dist/engineering-pa-workspace/app/repos.html +598 -0
- package/dist/engineering-pa-workspace/app/schedules.html +486 -0
- package/dist/engineering-pa-workspace/app/secrets.html +164 -0
- package/dist/engineering-pa-workspace/app/staging.html +319 -0
- package/dist/engineering-pa-workspace/app/tasks.html +465 -0
- package/dist/engineering-pa-workspace/app/vendor/chart.umd.min.js +21 -0
- package/dist/engineering-pa-workspace/app/viewer.html +116 -0
- package/dist/engineering-pa-workspace/docs/DAEMON.md +104 -0
- package/dist/engineering-pa-workspace/docs/page-blueprint.md +286 -0
- package/dist/engineering-pa-workspace/docs/status-mon.md +168 -0
- package/dist/engineering-pa-workspace/index.mjs +12 -0
- package/dist/engineering-pa-workspace/nav.json.example +8 -0
- package/dist/engineering-pa-workspace/package.json +27 -0
- package/dist/engineering-pa-workspace/src/api.mjs +2086 -0
- package/dist/engineering-pa-workspace/src/install-daemon.mjs +573 -0
- package/dist/engineering-pa-workspace/src/nav.mjs +190 -0
- package/dist/engineering-pa-workspace/src/secrets-api.mjs +175 -0
- package/dist/engineering-pa-workspace/src/server.mjs +516 -0
- package/dist/engineering-pa-workspace/src/status-mon/poll.mjs +220 -0
- package/dist/engineering-pa-workspace/src/status-mon/poller.mjs +113 -0
- package/dist/engineering-pa-workspace/src/status-mon/run.mjs +133 -0
- package/dist/engineering-pa-workspace/src/supervisor.mjs +264 -0
- package/dist/engineering-pa-workspace/src/ws.mjs +633 -0
- package/index.mjs +60 -0
- package/package.json +58 -0
- package/templates/banned-ai-tells.md +102 -0
- package/templates/purpose.md +105 -0
- package/templates/voice-guide.md +98 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// set.mjs — `pa staging-alias set --site <hostname> --branch <branch>`
|
|
2
|
+
//
|
|
3
|
+
// Wires `staging.<hostname>` to the latest preview version of the source
|
|
4
|
+
// Worker (which Workers Builds populated when the branch was pushed).
|
|
5
|
+
//
|
|
6
|
+
// Steps:
|
|
7
|
+
// 1. Resolve the site entry + load CF creds for the right account.
|
|
8
|
+
// 2. Drill: GET /accounts/{id} and assert `result.name` matches
|
|
9
|
+
// `expectedAccountName`. ABORT if it doesn't.
|
|
10
|
+
// 3. List versions on the source worker, pick the newest (or the one
|
|
11
|
+
// pinned by --version, when provided). Per-branch tagging is not
|
|
12
|
+
// surfaced by CF's API today; the contract is "operator just pushed
|
|
13
|
+
// the named branch, so the latest version is theirs". The CLI
|
|
14
|
+
// surfaces the picked version's metadata so the operator can verify.
|
|
15
|
+
// 4. Compute the workers.dev preview hostname for that version.
|
|
16
|
+
// 5. Resolve the zone id for `<site>` (we use the site's apex zone —
|
|
17
|
+
// `staging.<apex>` is on the same zone).
|
|
18
|
+
// 6. Upload the router worker (`<source>-staging`) with STAGING_TARGET
|
|
19
|
+
// bound to the preview hostname. Compat date pinned by the helper.
|
|
20
|
+
// 7. Bind `staging.<hostname>` to the router worker as a Custom Domain
|
|
21
|
+
// (idempotent — no-op if already correct).
|
|
22
|
+
// 8. Print the final URL.
|
|
23
|
+
//
|
|
24
|
+
// On any step failure after the upload, the command rolls back by
|
|
25
|
+
// removing the binding it created in step 7 (if step 7 succeeded). The
|
|
26
|
+
// router-worker upload itself is left in place because the failure mode
|
|
27
|
+
// it's most often associated with is the Custom-Domain binding, which is
|
|
28
|
+
// the destructive surface — a stranded router worker with no domain bound
|
|
29
|
+
// is harmless. The next `set` call will overwrite it cleanly.
|
|
30
|
+
|
|
31
|
+
import { resolveSite, stagingHostname } from '../sites.mjs';
|
|
32
|
+
import { loadCloudflareCreds } from '../../gsc/cloudflare.mjs';
|
|
33
|
+
import {
|
|
34
|
+
verifyAccount,
|
|
35
|
+
resolveAccountSubdomain,
|
|
36
|
+
resolveZoneId,
|
|
37
|
+
listWorkerVersions,
|
|
38
|
+
previewHostname,
|
|
39
|
+
workerScriptExists,
|
|
40
|
+
uploadRouterWorker,
|
|
41
|
+
bindWorkerCustomDomain,
|
|
42
|
+
unbindWorkerCustomDomain,
|
|
43
|
+
} from '../cloudflare.mjs';
|
|
44
|
+
|
|
45
|
+
export function parseFlags(args) {
|
|
46
|
+
const out = { site: null, branch: null, version: null, yes: false };
|
|
47
|
+
for (let i = 0; i < args.length; i++) {
|
|
48
|
+
const a = args[i];
|
|
49
|
+
if (a === '--site') out.site = args[++i];
|
|
50
|
+
else if (a.startsWith('--site=')) out.site = a.slice('--site='.length);
|
|
51
|
+
else if (a === '--branch') out.branch = args[++i];
|
|
52
|
+
else if (a.startsWith('--branch=')) out.branch = a.slice('--branch='.length);
|
|
53
|
+
else if (a === '--version') out.version = args[++i];
|
|
54
|
+
else if (a.startsWith('--version=')) out.version = a.slice('--version='.length);
|
|
55
|
+
else if (a === '--yes' || a === '-y') out.yes = true;
|
|
56
|
+
else {
|
|
57
|
+
throw Object.assign(new Error(`unexpected argument: ${a}`), { exitCode: 1 });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!out.site) throw Object.assign(new Error('--site is required'), { exitCode: 1 });
|
|
61
|
+
if (!out.branch && !out.version) {
|
|
62
|
+
throw Object.assign(new Error('one of --branch or --version is required'), { exitCode: 1 });
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function runSet(args, overrides = {}) {
|
|
68
|
+
let flags;
|
|
69
|
+
try { flags = parseFlags(args); } catch (e) {
|
|
70
|
+
process.stderr.write(`[staging-alias set] ${e.message}\n`);
|
|
71
|
+
return e.exitCode || 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const out = overrides.stdout || process.stdout;
|
|
75
|
+
const log = (msg) => out.write(`[staging-alias set] ${msg}\n`);
|
|
76
|
+
|
|
77
|
+
let site;
|
|
78
|
+
try { site = resolveSite(flags.site); } catch (e) {
|
|
79
|
+
process.stderr.write(`[staging-alias set] ${e.message}\n`);
|
|
80
|
+
return e.exitCode || 1;
|
|
81
|
+
}
|
|
82
|
+
const staging = stagingHostname(site);
|
|
83
|
+
|
|
84
|
+
// ── Step 1+2: credentials + safety drill. ──
|
|
85
|
+
let creds;
|
|
86
|
+
try {
|
|
87
|
+
creds = await loadCloudflareCreds({ ...overrides, account: site.accountKey });
|
|
88
|
+
} catch (e) {
|
|
89
|
+
process.stderr.write(`[staging-alias set] vault: ${e.message}\n`);
|
|
90
|
+
return e.exitCode || 2;
|
|
91
|
+
}
|
|
92
|
+
log(`using vault keys for account "${site.accountKey}"`);
|
|
93
|
+
|
|
94
|
+
let verified;
|
|
95
|
+
try {
|
|
96
|
+
verified = await verifyAccount(creds, site.expectedAccountName, overrides.fetchImpl);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
process.stderr.write(`[staging-alias set] account drill FAILED: ${e.message}\n`);
|
|
99
|
+
return e.exitCode || 2;
|
|
100
|
+
}
|
|
101
|
+
log(`account verified: "${verified.name}" (${verified.id})`);
|
|
102
|
+
|
|
103
|
+
// ── Step 3: pick version. ──
|
|
104
|
+
let versionId;
|
|
105
|
+
let versionMeta;
|
|
106
|
+
if (flags.version) {
|
|
107
|
+
versionId = flags.version;
|
|
108
|
+
log(`using --version ${versionId} (no version-listing fetch)`);
|
|
109
|
+
} else {
|
|
110
|
+
let versions;
|
|
111
|
+
try {
|
|
112
|
+
versions = await listWorkerVersions(creds, site.sourceWorker, overrides.fetchImpl);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
process.stderr.write(`[staging-alias set] listVersions: ${e.message}\n`);
|
|
115
|
+
return e.exitCode || 2;
|
|
116
|
+
}
|
|
117
|
+
if (versions.length === 0) {
|
|
118
|
+
process.stderr.write(
|
|
119
|
+
`[staging-alias set] worker "${site.sourceWorker}" has no versions yet. ` +
|
|
120
|
+
`Push branch "${flags.branch}" to trigger Workers Builds first.\n`,
|
|
121
|
+
);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
versionMeta = versions[0];
|
|
125
|
+
versionId = versionMeta.id;
|
|
126
|
+
log(`branch "${flags.branch}" -> latest version ${versionId} (number=${versionMeta.number}, created=${versionMeta?.metadata?.created_on})`);
|
|
127
|
+
log('note: CF does not tag versions with branch; verify the version matches your branch push.');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ── Step 4: compute preview hostname. ──
|
|
131
|
+
let subdomain;
|
|
132
|
+
try {
|
|
133
|
+
subdomain = await resolveAccountSubdomain(creds, overrides.fetchImpl);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
process.stderr.write(`[staging-alias set] subdomain: ${e.message}\n`);
|
|
136
|
+
return e.exitCode || 2;
|
|
137
|
+
}
|
|
138
|
+
const targetHost = previewHostname(versionId, site.sourceWorker, subdomain);
|
|
139
|
+
log(`router target: https://${targetHost}/`);
|
|
140
|
+
|
|
141
|
+
// ── Step 5: zone id. ──
|
|
142
|
+
let zone;
|
|
143
|
+
try {
|
|
144
|
+
zone = await resolveZoneId(creds, site.zoneName, overrides.fetchImpl);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
process.stderr.write(`[staging-alias set] resolveZone: ${e.message}\n`);
|
|
147
|
+
return e.exitCode || 2;
|
|
148
|
+
}
|
|
149
|
+
log(`zone: ${zone.zoneName} (${zone.zoneId})`);
|
|
150
|
+
|
|
151
|
+
// ── Step 6: upload router worker. ──
|
|
152
|
+
try {
|
|
153
|
+
await uploadRouterWorker(creds, site.routerWorker, targetHost, overrides.fetchImpl);
|
|
154
|
+
log(`router worker "${site.routerWorker}" uploaded with STAGING_TARGET=${targetHost}`);
|
|
155
|
+
} catch (e) {
|
|
156
|
+
process.stderr.write(`[staging-alias set] uploadRouterWorker: ${e.message}\n`);
|
|
157
|
+
return e.exitCode || 2;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ── Step 7: bind Custom Domain. ──
|
|
161
|
+
let bindResult;
|
|
162
|
+
try {
|
|
163
|
+
bindResult = await bindWorkerCustomDomain(
|
|
164
|
+
creds, staging, site.routerWorker, zone.zoneId, overrides.fetchImpl,
|
|
165
|
+
);
|
|
166
|
+
log(`Custom Domain ${staging} -> ${site.routerWorker}: ${bindResult.action}`);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
// No previous step depends on the binding existing — nothing to roll back.
|
|
169
|
+
process.stderr.write(`[staging-alias set] bindCustomDomain: ${e.message}\n`);
|
|
170
|
+
return e.exitCode || 2;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ── Step 8: print URL. ──
|
|
174
|
+
const url = `https://${staging}/`;
|
|
175
|
+
out.write(JSON.stringify({
|
|
176
|
+
site: site.hostname,
|
|
177
|
+
staging,
|
|
178
|
+
branch: flags.branch || null,
|
|
179
|
+
versionId,
|
|
180
|
+
targetHost,
|
|
181
|
+
routerWorker: site.routerWorker,
|
|
182
|
+
customDomainAction: bindResult.action,
|
|
183
|
+
url,
|
|
184
|
+
}, null, 2) + '\n');
|
|
185
|
+
log(`done. ${url} now serves the chosen preview version.`);
|
|
186
|
+
log('TLS cert provisioning can take up to ~60s on first bind.');
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// status.mjs — `pa staging-alias status --site <hostname>`
|
|
2
|
+
//
|
|
3
|
+
// Read-only probe of the current staging-alias state for one site.
|
|
4
|
+
// Reports:
|
|
5
|
+
// - Whether the router worker exists.
|
|
6
|
+
// - The router's STAGING_TARGET (the workers.dev preview URL).
|
|
7
|
+
// - Whether `staging.<hostname>` is bound to the router as a Custom Domain.
|
|
8
|
+
// - The custom-domain TLS cert id (CF doesn't expose cert state via this
|
|
9
|
+
// endpoint, so we surface presence as a proxy — fuller TLS introspection
|
|
10
|
+
// would need /accounts/{id}/access/certificates lookups, deferred).
|
|
11
|
+
//
|
|
12
|
+
// Does NOT run the account drill — status is read-only. It does verify
|
|
13
|
+
// the account name and surfaces a warning if it doesn't match the
|
|
14
|
+
// expected value, so the operator notices vault-key drift.
|
|
15
|
+
|
|
16
|
+
import { resolveSite, stagingHostname } from '../sites.mjs';
|
|
17
|
+
import { loadCloudflareCreds } from '../../gsc/cloudflare.mjs';
|
|
18
|
+
import {
|
|
19
|
+
cfFetch,
|
|
20
|
+
readRouterTarget,
|
|
21
|
+
findWorkerDomain,
|
|
22
|
+
workerScriptExists,
|
|
23
|
+
} from '../cloudflare.mjs';
|
|
24
|
+
|
|
25
|
+
export function parseFlags(args) {
|
|
26
|
+
const out = { site: null };
|
|
27
|
+
for (let i = 0; i < args.length; i++) {
|
|
28
|
+
const a = args[i];
|
|
29
|
+
if (a === '--site') out.site = args[++i];
|
|
30
|
+
else if (a.startsWith('--site=')) out.site = a.slice('--site='.length);
|
|
31
|
+
else {
|
|
32
|
+
throw Object.assign(new Error(`unexpected argument: ${a}`), { exitCode: 1 });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!out.site) throw Object.assign(new Error('--site is required'), { exitCode: 1 });
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build a structured status report for a single site. Pure-ish (depends on
|
|
41
|
+
* CF API via injected creds/fetchImpl).
|
|
42
|
+
*/
|
|
43
|
+
export async function buildStatus(site, creds, fetchImpl) {
|
|
44
|
+
const staging = stagingHostname(site);
|
|
45
|
+
|
|
46
|
+
// Account-name probe (best-effort).
|
|
47
|
+
let accountName = null;
|
|
48
|
+
let accountWarning = null;
|
|
49
|
+
try {
|
|
50
|
+
const body = await cfFetch(creds.token, `/accounts/${creds.accountId}`, {}, fetchImpl);
|
|
51
|
+
accountName = body && body.result && body.result.name;
|
|
52
|
+
if (accountName && accountName !== site.expectedAccountName) {
|
|
53
|
+
accountWarning = `account name "${accountName}" does not match expected "${site.expectedAccountName}"`;
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
accountWarning = `account probe failed: ${e.message}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const routerExists = await workerScriptExists(creds, site.routerWorker, fetchImpl);
|
|
60
|
+
const target = routerExists
|
|
61
|
+
? await readRouterTarget(creds, site.routerWorker, fetchImpl)
|
|
62
|
+
: null;
|
|
63
|
+
const binding = await findWorkerDomain(creds, staging, fetchImpl);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
site: site.hostname,
|
|
67
|
+
staging,
|
|
68
|
+
accountKey: site.accountKey,
|
|
69
|
+
accountName,
|
|
70
|
+
accountWarning,
|
|
71
|
+
routerWorker: site.routerWorker,
|
|
72
|
+
routerExists,
|
|
73
|
+
routerTarget: target,
|
|
74
|
+
customDomain: binding
|
|
75
|
+
? { hostname: binding.hostname, service: binding.service, id: binding.id, certId: binding.cert_id || null }
|
|
76
|
+
: null,
|
|
77
|
+
url: binding ? `https://${binding.hostname}/` : null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function runStatus(args, overrides = {}) {
|
|
82
|
+
let flags;
|
|
83
|
+
try { flags = parseFlags(args); } catch (e) {
|
|
84
|
+
process.stderr.write(`[staging-alias status] ${e.message}\n`);
|
|
85
|
+
return e.exitCode || 1;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let site;
|
|
89
|
+
try { site = resolveSite(flags.site); } catch (e) {
|
|
90
|
+
process.stderr.write(`[staging-alias status] ${e.message}\n`);
|
|
91
|
+
return e.exitCode || 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let creds;
|
|
95
|
+
try {
|
|
96
|
+
creds = await loadCloudflareCreds({ ...overrides, account: site.accountKey });
|
|
97
|
+
} catch (e) {
|
|
98
|
+
process.stderr.write(`[staging-alias status] vault: ${e.message}\n`);
|
|
99
|
+
return e.exitCode || 2;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let report;
|
|
103
|
+
try {
|
|
104
|
+
report = await buildStatus(site, creds, overrides.fetchImpl);
|
|
105
|
+
} catch (e) {
|
|
106
|
+
process.stderr.write(`[staging-alias status] ${e.message}\n`);
|
|
107
|
+
return e.exitCode || 2;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const out = overrides.stdout || process.stdout;
|
|
111
|
+
out.write(JSON.stringify(report, null, 2) + '\n');
|
|
112
|
+
return report.accountWarning ? 2 : 0;
|
|
113
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// unset.mjs — `pa staging-alias unset --site <hostname>`
|
|
2
|
+
//
|
|
3
|
+
// Removes `staging.<hostname>` cleanly:
|
|
4
|
+
// 1. Resolve site + creds + drill.
|
|
5
|
+
// 2. Unbind Custom Domain `staging.<hostname>` (idempotent).
|
|
6
|
+
// 3. Delete the router worker script (idempotent).
|
|
7
|
+
//
|
|
8
|
+
// We leave the apex DNS / production custom domains untouched — see the
|
|
9
|
+
// boundaries note in the brief.
|
|
10
|
+
|
|
11
|
+
import { resolveSite, stagingHostname } from '../sites.mjs';
|
|
12
|
+
import { loadCloudflareCreds } from '../../gsc/cloudflare.mjs';
|
|
13
|
+
import {
|
|
14
|
+
verifyAccount,
|
|
15
|
+
unbindWorkerCustomDomain,
|
|
16
|
+
deleteWorkerScript,
|
|
17
|
+
} from '../cloudflare.mjs';
|
|
18
|
+
|
|
19
|
+
export function parseFlags(args) {
|
|
20
|
+
const out = { site: null, keepWorker: false };
|
|
21
|
+
for (let i = 0; i < args.length; i++) {
|
|
22
|
+
const a = args[i];
|
|
23
|
+
if (a === '--site') out.site = args[++i];
|
|
24
|
+
else if (a.startsWith('--site=')) out.site = a.slice('--site='.length);
|
|
25
|
+
else if (a === '--keep-worker') out.keepWorker = true;
|
|
26
|
+
else {
|
|
27
|
+
throw Object.assign(new Error(`unexpected argument: ${a}`), { exitCode: 1 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!out.site) throw Object.assign(new Error('--site is required'), { exitCode: 1 });
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function runUnset(args, overrides = {}) {
|
|
35
|
+
let flags;
|
|
36
|
+
try { flags = parseFlags(args); } catch (e) {
|
|
37
|
+
process.stderr.write(`[staging-alias unset] ${e.message}\n`);
|
|
38
|
+
return e.exitCode || 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const out = overrides.stdout || process.stdout;
|
|
42
|
+
const log = (msg) => out.write(`[staging-alias unset] ${msg}\n`);
|
|
43
|
+
|
|
44
|
+
let site;
|
|
45
|
+
try { site = resolveSite(flags.site); } catch (e) {
|
|
46
|
+
process.stderr.write(`[staging-alias unset] ${e.message}\n`);
|
|
47
|
+
return e.exitCode || 1;
|
|
48
|
+
}
|
|
49
|
+
const staging = stagingHostname(site);
|
|
50
|
+
|
|
51
|
+
let creds;
|
|
52
|
+
try {
|
|
53
|
+
creds = await loadCloudflareCreds({ ...overrides, account: site.accountKey });
|
|
54
|
+
} catch (e) {
|
|
55
|
+
process.stderr.write(`[staging-alias unset] vault: ${e.message}\n`);
|
|
56
|
+
return e.exitCode || 2;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let verified;
|
|
60
|
+
try {
|
|
61
|
+
verified = await verifyAccount(creds, site.expectedAccountName, overrides.fetchImpl);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
process.stderr.write(`[staging-alias unset] account drill FAILED: ${e.message}\n`);
|
|
64
|
+
return e.exitCode || 2;
|
|
65
|
+
}
|
|
66
|
+
log(`account verified: "${verified.name}" (${verified.id})`);
|
|
67
|
+
|
|
68
|
+
let unbindResult;
|
|
69
|
+
try {
|
|
70
|
+
unbindResult = await unbindWorkerCustomDomain(creds, staging, overrides.fetchImpl);
|
|
71
|
+
log(`unbind ${staging}: ${unbindResult.action}`);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
process.stderr.write(`[staging-alias unset] unbind: ${e.message}\n`);
|
|
74
|
+
return e.exitCode || 2;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let deleteResult = { action: 'skipped' };
|
|
78
|
+
if (!flags.keepWorker) {
|
|
79
|
+
try {
|
|
80
|
+
deleteResult = await deleteWorkerScript(creds, site.routerWorker, overrides.fetchImpl);
|
|
81
|
+
log(`delete worker "${site.routerWorker}": ${deleteResult.action}`);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
process.stderr.write(`[staging-alias unset] deleteWorker: ${e.message}\n`);
|
|
84
|
+
return e.exitCode || 2;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
out.write(JSON.stringify({
|
|
89
|
+
site: site.hostname,
|
|
90
|
+
staging,
|
|
91
|
+
customDomainAction: unbindResult.action,
|
|
92
|
+
workerAction: deleteResult.action,
|
|
93
|
+
}, null, 2) + '\n');
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// sites.mjs — Data-driven registry of operator-managed Cloudflare-Workers sites.
|
|
2
|
+
//
|
|
3
|
+
// Each entry binds a public hostname to:
|
|
4
|
+
// - the source Worker name (the one whose preview deployments we want to
|
|
5
|
+
// surface at staging.<hostname>),
|
|
6
|
+
// - the CF account whose vault keys hold the API credentials,
|
|
7
|
+
// - the expected CF account display name (used for the safety drill: the
|
|
8
|
+
// CLI reads /accounts/{account_id} before any write and aborts unless
|
|
9
|
+
// `result.name` matches `expectedAccountName`),
|
|
10
|
+
// - the router-worker name (derived by convention as `<source>-staging`).
|
|
11
|
+
//
|
|
12
|
+
// Adding a fourth site is one entry. The lookup is intentionally a flat
|
|
13
|
+
// object rather than a search over `operator/knowledge/systems/web-properties/`
|
|
14
|
+
// — the CLI lives in the platform package and must not depend on the
|
|
15
|
+
// operator-repo layout (per `feedback_role_definition_genericity.md`).
|
|
16
|
+
//
|
|
17
|
+
// `accountKey` is the vault-key suffix (lowercase form passed to
|
|
18
|
+
// `loadCloudflareCreds({ account })`). The CF helper upper-cases it
|
|
19
|
+
// internally to build `CLOUDFLARE_PAGES_API_KEY_<SUFFIX>` + matching
|
|
20
|
+
// account-id key.
|
|
21
|
+
|
|
22
|
+
/** @typedef {{
|
|
23
|
+
* hostname: string,
|
|
24
|
+
* sourceWorker: string,
|
|
25
|
+
* routerWorker: string,
|
|
26
|
+
* accountKey: string,
|
|
27
|
+
* expectedAccountName: string,
|
|
28
|
+
* zoneName: string,
|
|
29
|
+
* notes?: string,
|
|
30
|
+
* }} SiteEntry */
|
|
31
|
+
|
|
32
|
+
/** @type {Record<string, SiteEntry>} */
|
|
33
|
+
export const SITES = Object.freeze({
|
|
34
|
+
'stravica.ai': {
|
|
35
|
+
hostname: 'stravica.ai',
|
|
36
|
+
sourceWorker: 'stravica-ai',
|
|
37
|
+
routerWorker: 'stravica-ai-staging',
|
|
38
|
+
accountKey: 'stravica',
|
|
39
|
+
expectedAccountName: "Barry@stravica.ai's Account",
|
|
40
|
+
zoneName: 'stravica.ai',
|
|
41
|
+
notes: 'Stravica-dedicated CF account (ab9a9e66...d848).',
|
|
42
|
+
},
|
|
43
|
+
'cliveelliott.net': {
|
|
44
|
+
hostname: 'cliveelliott.net',
|
|
45
|
+
sourceWorker: 'cliveelliott',
|
|
46
|
+
routerWorker: 'cliveelliott-staging',
|
|
47
|
+
accountKey: 'clive',
|
|
48
|
+
expectedAccountName: "Thefootonline@outlook.com's Account",
|
|
49
|
+
zoneName: 'cliveelliott.net',
|
|
50
|
+
notes: 'Clive-shared CF account (4c07d09f...5a76), pending transfer to Clive.',
|
|
51
|
+
},
|
|
52
|
+
'besafetraining.co.uk': {
|
|
53
|
+
hostname: 'besafetraining.co.uk',
|
|
54
|
+
sourceWorker: 'besafetraining',
|
|
55
|
+
routerWorker: 'besafetraining-staging',
|
|
56
|
+
accountKey: 'clive',
|
|
57
|
+
expectedAccountName: "Thefootonline@outlook.com's Account",
|
|
58
|
+
zoneName: 'besafetraining.co.uk',
|
|
59
|
+
notes: 'Clive-shared CF account (4c07d09f...5a76), pending transfer to Clive.',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Look up a registered site by hostname (apex only — passing
|
|
65
|
+
* `staging.stravica.ai` is rejected because the CLI itself owns the
|
|
66
|
+
* `staging.` prefix).
|
|
67
|
+
*
|
|
68
|
+
* @param {string} hostname
|
|
69
|
+
* @returns {SiteEntry}
|
|
70
|
+
* @throws {Error} with exitCode=1 when not found.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveSite(hostname) {
|
|
73
|
+
const raw = String(hostname || '').trim().toLowerCase();
|
|
74
|
+
if (!raw) {
|
|
75
|
+
throw Object.assign(new Error('--site: hostname is required'), { exitCode: 1 });
|
|
76
|
+
}
|
|
77
|
+
if (raw.startsWith('staging.')) {
|
|
78
|
+
throw Object.assign(
|
|
79
|
+
new Error(
|
|
80
|
+
`--site "${raw}" looks like a staging hostname. Pass the apex (e.g. ` +
|
|
81
|
+
`--site ${raw.slice('staging.'.length)}).`,
|
|
82
|
+
),
|
|
83
|
+
{ exitCode: 1 },
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
const entry = SITES[raw];
|
|
87
|
+
if (!entry) {
|
|
88
|
+
const known = Object.keys(SITES).join(', ');
|
|
89
|
+
throw Object.assign(
|
|
90
|
+
new Error(`--site "${raw}" is not registered. Known sites: ${known}`),
|
|
91
|
+
{ exitCode: 1 },
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return entry;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Iteration helper for the `list` verb. */
|
|
98
|
+
export function allSites() {
|
|
99
|
+
return Object.values(SITES);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** The staging hostname for a site (always `staging.<apex>`). */
|
|
103
|
+
export function stagingHostname(site) {
|
|
104
|
+
return `staging.${site.hostname}`;
|
|
105
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// estate-sync — CLI.
|
|
2
|
+
//
|
|
3
|
+
// Arg parsing (node:util.parseArgs, strict:true), verb routing,
|
|
4
|
+
// exit-code translation per §5–§6 of the tooling standard.
|
|
5
|
+
//
|
|
6
|
+
// Bin name: `estate-sync`. `sync` is kept as a back-compat alias — same
|
|
7
|
+
// entry point, same behaviour; both bins import this module unchanged.
|
|
8
|
+
//
|
|
9
|
+
// In v2 the operator repo no longer contains `core/tools/`. This tool is
|
|
10
|
+
// installed as part of the @stravica-ai/engineering-pa-cli package and writes
|
|
11
|
+
// its lock + audit log under `<repoRoot>/.cache/estate-sync/` (gitignored
|
|
12
|
+
// per the tooling standard §16). (Renamed from `.cache/sync/` alongside
|
|
13
|
+
// the dave-sync -> estate-sync rewrite; the old directory, if present from
|
|
14
|
+
// a prior install, is simply orphaned — no data loss, nothing git-tracked.)
|
|
15
|
+
|
|
16
|
+
import { appendFile, mkdir, stat } from 'node:fs/promises';
|
|
17
|
+
import { existsSync } from 'node:fs';
|
|
18
|
+
import { dirname, join, resolve } from 'node:path';
|
|
19
|
+
import { parseArgs } from 'node:util';
|
|
20
|
+
|
|
21
|
+
import { runSync } from './run.mjs';
|
|
22
|
+
import { defaultRunner } from './runner.mjs';
|
|
23
|
+
|
|
24
|
+
const USAGE = `estate-sync — single-writer-per-host git sync for ESTATE-NATIVE content.
|
|
25
|
+
|
|
26
|
+
(Also invocable as \`sync\` — kept as a back-compat alias for the pre-rename
|
|
27
|
+
bin name; identical behaviour.)
|
|
28
|
+
|
|
29
|
+
Usage:
|
|
30
|
+
estate-sync run Run a real sync pass (lock, stage, pull --rebase, commit, push)
|
|
31
|
+
estate-sync run --dry-run Print what would happen without modifying state
|
|
32
|
+
estate-sync -h, --help Show this help
|
|
33
|
+
|
|
34
|
+
Exit codes:
|
|
35
|
+
0 ok (including healthy no-ops)
|
|
36
|
+
1 usage error
|
|
37
|
+
2 logical / operational failure (rebase conflict, push rejected after retry)
|
|
38
|
+
3 transport / IO failure (git command itself errored)
|
|
39
|
+
|
|
40
|
+
Behaviour summary:
|
|
41
|
+
- Acquires a PID lock at <repoRoot>/.cache/estate-sync/.lock (stale-after 10 minutes).
|
|
42
|
+
- If working tree is clean and no commits ahead of origin, exits 0
|
|
43
|
+
(status: noop-nothing-to-do).
|
|
44
|
+
- Otherwise: computes a registry-scoped commit scope (when
|
|
45
|
+
<repoRoot>/operator/registry/{devices.json,repos.json} exist — every
|
|
46
|
+
entitled mount's \`to\` subtree + .vault/** are excluded; everything
|
|
47
|
+
else dirty is staged via explicit pathspecs, NEVER a bare
|
|
48
|
+
\`git add -A\`). No registry present -> unscoped \`git add -A\`, loudly
|
|
49
|
+
flagged in both the run's output and the commit body. Then
|
|
50
|
+
\`git fetch && git pull --rebase && git commit && git push\`. One
|
|
51
|
+
push-retry on rejection.
|
|
52
|
+
- Audit-logs every non-dry-run exit to <repoRoot>/.cache/estate-sync/logs/runs.jsonl.
|
|
53
|
+
|
|
54
|
+
Source of truth for behaviour: @stravica-ai/engineering-pa-cli/docs/estate-sync.md
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
async function defaultRepoRoot() {
|
|
58
|
+
const envRoot = process.env.DAVE_REPO_ROOT || process.env.PA_REPO_ROOT;
|
|
59
|
+
if (envRoot) return resolve(envRoot);
|
|
60
|
+
// .git-walk from cwd
|
|
61
|
+
let d = process.cwd();
|
|
62
|
+
while (d && d !== dirname(d)) {
|
|
63
|
+
if (existsSync(join(d, '.git'))) return d;
|
|
64
|
+
d = dirname(d);
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function writeBootstrapAudit({ err, exitCode, stderr }) {
|
|
70
|
+
try {
|
|
71
|
+
const repoRoot = await defaultRepoRoot();
|
|
72
|
+
if (!repoRoot) {
|
|
73
|
+
stderr.write('[estate-sync] warning: no repo root resolved; skipping bootstrap audit\n');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const logDir = join(repoRoot, '.cache/estate-sync/logs');
|
|
77
|
+
const runsLog = join(logDir, 'runs.jsonl');
|
|
78
|
+
await mkdir(logDir, { recursive: true });
|
|
79
|
+
const record = {
|
|
80
|
+
ts: new Date().toISOString().replace(/\.\d+Z$/, 'Z'),
|
|
81
|
+
status: 'fail-cli-bootstrap',
|
|
82
|
+
exitCode,
|
|
83
|
+
durationSec: 0,
|
|
84
|
+
reason: `cli bootstrap failure: ${err?.message || err}`,
|
|
85
|
+
};
|
|
86
|
+
await appendFile(runsLog, JSON.stringify(record) + '\n');
|
|
87
|
+
} catch (auditErr) {
|
|
88
|
+
stderr.write(`[estate-sync] warning: failed to append bootstrap audit record: ${auditErr.message}\n`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function main(
|
|
93
|
+
argv,
|
|
94
|
+
{ stderr = process.stderr, exit = process.exit, audit = writeBootstrapAudit } = {},
|
|
95
|
+
) {
|
|
96
|
+
try {
|
|
97
|
+
return await route(argv);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
const code = err?.syncExitCode ?? 2;
|
|
100
|
+
stderr.write(`[estate-sync] ${err.message || err}\n`);
|
|
101
|
+
await audit({ err, exitCode: code, stderr });
|
|
102
|
+
exit(code);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function route(argv) {
|
|
107
|
+
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
|
|
108
|
+
process.stdout.write(USAGE);
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const verb = argv[0];
|
|
113
|
+
const rest = argv.slice(1);
|
|
114
|
+
|
|
115
|
+
if (verb === 'run') {
|
|
116
|
+
const { values } = parseArgs({
|
|
117
|
+
args: rest,
|
|
118
|
+
options: {
|
|
119
|
+
'dry-run': { type: 'boolean', default: false },
|
|
120
|
+
help: { type: 'boolean', short: 'h', default: false },
|
|
121
|
+
},
|
|
122
|
+
strict: true,
|
|
123
|
+
});
|
|
124
|
+
if (values.help) {
|
|
125
|
+
process.stdout.write(USAGE);
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
const repoRoot = await defaultRepoRoot();
|
|
129
|
+
if (!repoRoot) {
|
|
130
|
+
process.stderr.write('[estate-sync] could not find repo root (no .git ancestor; set DAVE_REPO_ROOT)\n');
|
|
131
|
+
process.exit(2);
|
|
132
|
+
}
|
|
133
|
+
const logDir = join(repoRoot, '.cache/estate-sync/logs');
|
|
134
|
+
await mkdir(logDir, { recursive: true });
|
|
135
|
+
const runsLog = join(logDir, 'runs.jsonl');
|
|
136
|
+
const lockPath = join(repoRoot, '.cache/estate-sync/.lock');
|
|
137
|
+
const code = await runSync({
|
|
138
|
+
repoRoot,
|
|
139
|
+
logDir,
|
|
140
|
+
runsLog,
|
|
141
|
+
lockPath,
|
|
142
|
+
dryRun: values['dry-run'],
|
|
143
|
+
runner: defaultRunner,
|
|
144
|
+
});
|
|
145
|
+
process.exit(code ?? 0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
process.stderr.write(`[estate-sync] unknown command: ${verb}\n`);
|
|
149
|
+
process.stderr.write(USAGE);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|