@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,573 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* install-daemon.mjs — Install the workspace server as a supervised daemon
|
|
5
|
+
*
|
|
6
|
+
* Supervises the workspace server via the host's native service manager so it
|
|
7
|
+
* auto-starts at login and auto-restarts on crash. This is distinct from the
|
|
8
|
+
* scheduler tool (cron/launchd-calendar/systemd-timer/schtasks), which is
|
|
9
|
+
* time-triggered. A daemon is continuous-supervision and needs KeepAlive /
|
|
10
|
+
* Restart=always / RunAtLoad semantics that cron doesn't express.
|
|
11
|
+
*
|
|
12
|
+
* The daemon invokes `node server.mjs --no-timeout --port N --no-open`
|
|
13
|
+
* directly — it deliberately bypasses ws.mjs to avoid double-fork detach,
|
|
14
|
+
* which would make the supervisor think the service died on every start.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* node install-daemon.mjs install [--port N] [--dry-run]
|
|
18
|
+
* node install-daemon.mjs uninstall [--dry-run]
|
|
19
|
+
* node install-daemon.mjs status
|
|
20
|
+
* node install-daemon.mjs --help
|
|
21
|
+
*
|
|
22
|
+
* Exit codes:
|
|
23
|
+
* 0 — OK
|
|
24
|
+
* 1 — Usage error
|
|
25
|
+
* 2 — Platform unsupported or logical failure
|
|
26
|
+
* 3 — Transport / IO failure (launchctl/systemctl call failed)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { execSync } from 'node:child_process';
|
|
30
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, realpathSync } from 'node:fs';
|
|
31
|
+
import { homedir, platform } from 'node:os';
|
|
32
|
+
import { dirname, join, resolve } from 'node:path';
|
|
33
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
34
|
+
|
|
35
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
36
|
+
const __dirname = dirname(__filename);
|
|
37
|
+
|
|
38
|
+
// Resolve the operator repo root. In v2 this package is installed at
|
|
39
|
+
// node_modules/@stravica-ai/engineering-pa-workspace/, so walking up three
|
|
40
|
+
// __dirname levels lands inside node_modules/, not at the operator repo
|
|
41
|
+
// root. Precedence:
|
|
42
|
+
// 1. DAVE_REPO_ROOT or PA_REPO_ROOT env (explicit override)
|
|
43
|
+
// 2. Walk up from process.cwd() looking for .git or pnpm-workspace.yaml
|
|
44
|
+
// 3. Fall back to process.cwd() (best-effort; lets dry-run work in odd
|
|
45
|
+
// checkouts)
|
|
46
|
+
function findRepoRoot(start) {
|
|
47
|
+
let d = start;
|
|
48
|
+
while (d && d !== resolve(d, '..')) {
|
|
49
|
+
if (existsSync(join(d, '.git')) || existsSync(join(d, 'pnpm-workspace.yaml'))) return d;
|
|
50
|
+
d = resolve(d, '..');
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const envRoot = process.env.DAVE_REPO_ROOT || process.env.PA_REPO_ROOT;
|
|
56
|
+
const REPO_ROOT = envRoot ? resolve(envRoot) : (findRepoRoot(process.cwd()) || process.cwd());
|
|
57
|
+
const SERVER_SCRIPT = join(__dirname, 'server.mjs');
|
|
58
|
+
const PREFS_FILE = join(REPO_ROOT, 'operator', 'config', 'preferences.json');
|
|
59
|
+
|
|
60
|
+
const LABEL = 'com.dave.workspace';
|
|
61
|
+
const UNIT_NAME = 'dave-workspace.service';
|
|
62
|
+
|
|
63
|
+
// --- Log paths (platform-specific) --------------------------------------
|
|
64
|
+
|
|
65
|
+
function defaultLogPaths() {
|
|
66
|
+
const plat = platform();
|
|
67
|
+
if (plat === 'darwin') {
|
|
68
|
+
const dir = join(homedir(), 'Library', 'Logs');
|
|
69
|
+
return { dir, out: join(dir, 'dave-workspace.log'), err: join(dir, 'dave-workspace.err.log') };
|
|
70
|
+
}
|
|
71
|
+
if (plat === 'linux') {
|
|
72
|
+
const dir = join(homedir(), '.local', 'state', 'dave');
|
|
73
|
+
return { dir, out: join(dir, 'workspace.log'), err: join(dir, 'workspace.err.log') };
|
|
74
|
+
}
|
|
75
|
+
return { dir: null, out: null, err: null };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// --- Port resolution ----------------------------------------------------
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Resolve the workspace port at install time. Precedence:
|
|
82
|
+
* 1. CLI --port flag
|
|
83
|
+
* 2. operator/config/preferences.json workspacePort
|
|
84
|
+
* 3. default 4200
|
|
85
|
+
* @param {string|undefined} flagPort
|
|
86
|
+
* @returns {number}
|
|
87
|
+
*/
|
|
88
|
+
export function resolvePort(flagPort) {
|
|
89
|
+
if (flagPort !== undefined && flagPort !== null) {
|
|
90
|
+
const parsed = parseInt(String(flagPort), 10);
|
|
91
|
+
if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535) {
|
|
92
|
+
throw Object.assign(new Error(`Invalid port "${flagPort}". Must be 1-65535.`), { exitCode: 1 });
|
|
93
|
+
}
|
|
94
|
+
return parsed;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const prefs = JSON.parse(readFileSync(PREFS_FILE, 'utf-8'));
|
|
98
|
+
if (prefs.workspacePort) return prefs.workspacePort;
|
|
99
|
+
} catch { /* fall through to default */ }
|
|
100
|
+
return 4200;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// --- XML / plist builders -----------------------------------------------
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* XML-escape a string for safe embedding in plist values.
|
|
107
|
+
* @param {string} s
|
|
108
|
+
*/
|
|
109
|
+
function xmlEscape(s) {
|
|
110
|
+
return String(s)
|
|
111
|
+
.replace(/&/g, '&')
|
|
112
|
+
.replace(/</g, '<')
|
|
113
|
+
.replace(/>/g, '>')
|
|
114
|
+
.replace(/"/g, '"');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Build the launchd plist XML for the workspace daemon. Pure function.
|
|
119
|
+
*
|
|
120
|
+
* ProgramArguments invokes server.mjs directly (NOT ws.mjs) because ws.mjs
|
|
121
|
+
* double-forks and detaches — launchd would see the immediate parent exit
|
|
122
|
+
* and interpret it as a crash, triggering a restart loop.
|
|
123
|
+
*
|
|
124
|
+
* KeepAlive is a bare boolean: restart unconditionally on exit. ThrottleInterval
|
|
125
|
+
* caps the restart rate so a persistent crash can't burn CPU in a tight loop.
|
|
126
|
+
*
|
|
127
|
+
* @param {object} opts
|
|
128
|
+
* @param {string} opts.nodePath - Absolute path to node executable
|
|
129
|
+
* @param {string} opts.serverScript - Absolute path to server.mjs
|
|
130
|
+
* @param {string} opts.repoRoot - Absolute repo root for WorkingDirectory
|
|
131
|
+
* @param {number} opts.port - Port to bind
|
|
132
|
+
* @param {string} opts.stdoutPath - Path to stdout log
|
|
133
|
+
* @param {string} opts.stderrPath - Path to stderr log
|
|
134
|
+
* @returns {string}
|
|
135
|
+
*/
|
|
136
|
+
export function buildLaunchdPlist(opts) {
|
|
137
|
+
const { nodePath, serverScript, repoRoot, port, stdoutPath, stderrPath } = opts;
|
|
138
|
+
const programArgs = [
|
|
139
|
+
nodePath,
|
|
140
|
+
serverScript,
|
|
141
|
+
'--no-timeout',
|
|
142
|
+
'--port', String(port),
|
|
143
|
+
'--no-open',
|
|
144
|
+
];
|
|
145
|
+
const argsXml = programArgs.map((p) => ` <string>${xmlEscape(p)}</string>`).join('\n');
|
|
146
|
+
|
|
147
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
148
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
149
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
150
|
+
<plist version="1.0">
|
|
151
|
+
<dict>
|
|
152
|
+
<key>Label</key>
|
|
153
|
+
<string>${LABEL}</string>
|
|
154
|
+
<key>ProgramArguments</key>
|
|
155
|
+
<array>
|
|
156
|
+
${argsXml}
|
|
157
|
+
</array>
|
|
158
|
+
<key>WorkingDirectory</key>
|
|
159
|
+
<string>${xmlEscape(repoRoot)}</string>
|
|
160
|
+
<key>EnvironmentVariables</key>
|
|
161
|
+
<dict>
|
|
162
|
+
<key>DAVE_ROOT</key>
|
|
163
|
+
<string>${xmlEscape(repoRoot)}</string>
|
|
164
|
+
<key>PATH</key>
|
|
165
|
+
<string>${xmlEscape(process.env.PATH || '/usr/local/bin:/usr/bin:/bin')}</string>
|
|
166
|
+
</dict>
|
|
167
|
+
<key>RunAtLoad</key>
|
|
168
|
+
<true/>
|
|
169
|
+
<key>KeepAlive</key>
|
|
170
|
+
<true/>
|
|
171
|
+
<key>ThrottleInterval</key>
|
|
172
|
+
<integer>10</integer>
|
|
173
|
+
<key>StandardOutPath</key>
|
|
174
|
+
<string>${xmlEscape(stdoutPath)}</string>
|
|
175
|
+
<key>StandardErrorPath</key>
|
|
176
|
+
<string>${xmlEscape(stderrPath)}</string>
|
|
177
|
+
<key>ProcessType</key>
|
|
178
|
+
<string>Background</string>
|
|
179
|
+
</dict>
|
|
180
|
+
</plist>
|
|
181
|
+
`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Build the systemd user service unit for the workspace daemon. Pure function.
|
|
186
|
+
*
|
|
187
|
+
* Same rationale as launchd: ExecStart invokes server.mjs directly (not ws.mjs),
|
|
188
|
+
* because ws.mjs detaches and systemd would see Type=simple's main process exit
|
|
189
|
+
* and assume the service died. Restart=always + RestartSec=5 mirrors launchd's
|
|
190
|
+
* KeepAlive+ThrottleInterval.
|
|
191
|
+
*
|
|
192
|
+
* @param {object} opts
|
|
193
|
+
* @param {string} opts.nodePath
|
|
194
|
+
* @param {string} opts.serverScript
|
|
195
|
+
* @param {string} opts.repoRoot
|
|
196
|
+
* @param {number} opts.port
|
|
197
|
+
* @param {string} opts.stdoutPath
|
|
198
|
+
* @param {string} opts.stderrPath
|
|
199
|
+
* @returns {string}
|
|
200
|
+
*/
|
|
201
|
+
export function buildSystemdUnit(opts) {
|
|
202
|
+
const { nodePath, serverScript, repoRoot, port, stdoutPath, stderrPath } = opts;
|
|
203
|
+
return `[Unit]
|
|
204
|
+
Description=Dave workspace server (supervised daemon)
|
|
205
|
+
After=network.target
|
|
206
|
+
|
|
207
|
+
[Service]
|
|
208
|
+
Type=simple
|
|
209
|
+
WorkingDirectory=${repoRoot}
|
|
210
|
+
Environment=DAVE_ROOT=${repoRoot}
|
|
211
|
+
ExecStart=${nodePath} ${serverScript} --no-timeout --port ${port} --no-open
|
|
212
|
+
Restart=always
|
|
213
|
+
RestartSec=5
|
|
214
|
+
StandardOutput=append:${stdoutPath}
|
|
215
|
+
StandardError=append:${stderrPath}
|
|
216
|
+
|
|
217
|
+
[Install]
|
|
218
|
+
WantedBy=default.target
|
|
219
|
+
`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// --- Paths --------------------------------------------------------------
|
|
223
|
+
|
|
224
|
+
function launchdPlistPath() {
|
|
225
|
+
return join(homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function systemdUnitPath() {
|
|
229
|
+
return join(homedir(), '.config', 'systemd', 'user', UNIT_NAME);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// --- Darwin (launchd) ---------------------------------------------------
|
|
233
|
+
|
|
234
|
+
function darwinInstall({ port, dryRun }) {
|
|
235
|
+
const logs = defaultLogPaths();
|
|
236
|
+
const opts = {
|
|
237
|
+
nodePath: process.execPath,
|
|
238
|
+
serverScript: SERVER_SCRIPT,
|
|
239
|
+
repoRoot: REPO_ROOT,
|
|
240
|
+
port,
|
|
241
|
+
stdoutPath: logs.out,
|
|
242
|
+
stderrPath: logs.err,
|
|
243
|
+
};
|
|
244
|
+
const plist = buildLaunchdPlist(opts);
|
|
245
|
+
const plistPath = launchdPlistPath();
|
|
246
|
+
|
|
247
|
+
if (dryRun) {
|
|
248
|
+
console.log(`# Would write plist to: ${plistPath}`);
|
|
249
|
+
console.log(`# Log dir: ${logs.dir}`);
|
|
250
|
+
console.log(`# Would run: launchctl unload -w ${plistPath} (ignoring errors)`);
|
|
251
|
+
console.log(`# Would run: launchctl load -w ${plistPath}`);
|
|
252
|
+
console.log('# --- plist contents ---');
|
|
253
|
+
console.log(plist);
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
mkdirSync(dirname(plistPath), { recursive: true });
|
|
258
|
+
mkdirSync(logs.dir, { recursive: true });
|
|
259
|
+
writeFileSync(plistPath, plist, 'utf8');
|
|
260
|
+
console.log(`Wrote plist: ${plistPath}`);
|
|
261
|
+
|
|
262
|
+
// Unload if present (ignore failure — it may not be loaded)
|
|
263
|
+
try {
|
|
264
|
+
execSync(`launchctl unload -w ${shellQuote(plistPath)}`, { stdio: 'pipe' });
|
|
265
|
+
} catch { /* not previously loaded */ }
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
execSync(`launchctl load -w ${shellQuote(plistPath)}`, { stdio: 'pipe' });
|
|
269
|
+
} catch (err) {
|
|
270
|
+
throw Object.assign(new Error(`launchctl load failed: ${err.message}`), { exitCode: 3 });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
console.log(`Loaded service: ${LABEL}`);
|
|
274
|
+
console.log(`Logs: ${logs.out}`);
|
|
275
|
+
console.log(` ${logs.err}`);
|
|
276
|
+
console.log(`URL: http://127.0.0.1:${port}/`);
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function darwinUninstall({ dryRun }) {
|
|
281
|
+
const plistPath = launchdPlistPath();
|
|
282
|
+
if (dryRun) {
|
|
283
|
+
console.log(`# Would run: launchctl unload -w ${plistPath}`);
|
|
284
|
+
console.log(`# Would remove: ${plistPath}`);
|
|
285
|
+
return 0;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (existsSync(plistPath)) {
|
|
289
|
+
try {
|
|
290
|
+
execSync(`launchctl unload -w ${shellQuote(plistPath)}`, { stdio: 'pipe' });
|
|
291
|
+
} catch { /* not loaded — fine */ }
|
|
292
|
+
try {
|
|
293
|
+
unlinkSync(plistPath);
|
|
294
|
+
console.log(`Removed plist: ${plistPath}`);
|
|
295
|
+
} catch (err) {
|
|
296
|
+
throw Object.assign(new Error(`Could not remove plist: ${err.message}`), { exitCode: 3 });
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
console.log(`No plist found at ${plistPath} — nothing to remove.`);
|
|
300
|
+
}
|
|
301
|
+
console.log(`Unloaded: ${LABEL}`);
|
|
302
|
+
return 0;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function darwinStatus() {
|
|
306
|
+
const plistPath = launchdPlistPath();
|
|
307
|
+
const plistExists = existsSync(plistPath);
|
|
308
|
+
console.log(`Plist: ${plistPath} (${plistExists ? 'present' : 'absent'})`);
|
|
309
|
+
|
|
310
|
+
let listing = '';
|
|
311
|
+
try {
|
|
312
|
+
listing = execSync(`launchctl list ${LABEL}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
313
|
+
} catch {
|
|
314
|
+
console.log(`Service ${LABEL}: not loaded.`);
|
|
315
|
+
return plistExists ? 2 : 0;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// launchctl list <label> returns a plist-ish dict. Extract PID line if any.
|
|
319
|
+
const pidMatch = listing.match(/"PID"\s*=\s*(\d+)/);
|
|
320
|
+
if (pidMatch) {
|
|
321
|
+
console.log(`Service ${LABEL}: running (PID ${pidMatch[1]}).`);
|
|
322
|
+
return 0;
|
|
323
|
+
}
|
|
324
|
+
const exitMatch = listing.match(/"LastExitStatus"\s*=\s*(-?\d+)/);
|
|
325
|
+
console.log(`Service ${LABEL}: loaded but not running${exitMatch ? ` (last exit: ${exitMatch[1]})` : ''}.`);
|
|
326
|
+
return 2;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// --- Linux (systemd --user) --------------------------------------------
|
|
330
|
+
|
|
331
|
+
function linuxInstall({ port, dryRun }) {
|
|
332
|
+
const logs = defaultLogPaths();
|
|
333
|
+
const opts = {
|
|
334
|
+
nodePath: process.execPath,
|
|
335
|
+
serverScript: SERVER_SCRIPT,
|
|
336
|
+
repoRoot: REPO_ROOT,
|
|
337
|
+
port,
|
|
338
|
+
stdoutPath: logs.out,
|
|
339
|
+
stderrPath: logs.err,
|
|
340
|
+
};
|
|
341
|
+
const unit = buildSystemdUnit(opts);
|
|
342
|
+
const unitPath = systemdUnitPath();
|
|
343
|
+
|
|
344
|
+
if (dryRun) {
|
|
345
|
+
console.log(`# Would write unit to: ${unitPath}`);
|
|
346
|
+
console.log(`# Log dir: ${logs.dir}`);
|
|
347
|
+
console.log('# Would run: systemctl --user daemon-reload');
|
|
348
|
+
console.log(`# Would run: systemctl --user enable --now ${UNIT_NAME}`);
|
|
349
|
+
console.log('# --- unit contents ---');
|
|
350
|
+
console.log(unit);
|
|
351
|
+
return 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
mkdirSync(dirname(unitPath), { recursive: true });
|
|
355
|
+
mkdirSync(logs.dir, { recursive: true });
|
|
356
|
+
writeFileSync(unitPath, unit, 'utf8');
|
|
357
|
+
console.log(`Wrote unit: ${unitPath}`);
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
execSync('systemctl --user daemon-reload', { stdio: 'pipe' });
|
|
361
|
+
execSync(`systemctl --user enable --now ${UNIT_NAME}`, { stdio: 'pipe' });
|
|
362
|
+
} catch (err) {
|
|
363
|
+
throw Object.assign(new Error(`systemctl failed: ${err.message}`), { exitCode: 3 });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
console.log(`Enabled + started: ${UNIT_NAME}`);
|
|
367
|
+
console.log(`Logs: ${logs.out}`);
|
|
368
|
+
console.log(` ${logs.err}`);
|
|
369
|
+
console.log(`URL: http://127.0.0.1:${port}/`);
|
|
370
|
+
return 0;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function linuxUninstall({ dryRun }) {
|
|
374
|
+
const unitPath = systemdUnitPath();
|
|
375
|
+
if (dryRun) {
|
|
376
|
+
console.log(`# Would run: systemctl --user disable --now ${UNIT_NAME}`);
|
|
377
|
+
console.log('# Would run: systemctl --user daemon-reload');
|
|
378
|
+
console.log(`# Would remove: ${unitPath}`);
|
|
379
|
+
return 0;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
execSync(`systemctl --user disable --now ${UNIT_NAME}`, { stdio: 'pipe' });
|
|
384
|
+
} catch { /* not installed — fine */ }
|
|
385
|
+
|
|
386
|
+
if (existsSync(unitPath)) {
|
|
387
|
+
try {
|
|
388
|
+
unlinkSync(unitPath);
|
|
389
|
+
console.log(`Removed unit: ${unitPath}`);
|
|
390
|
+
} catch (err) {
|
|
391
|
+
throw Object.assign(new Error(`Could not remove unit: ${err.message}`), { exitCode: 3 });
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
console.log(`No unit file at ${unitPath} — nothing to remove.`);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
execSync('systemctl --user daemon-reload', { stdio: 'pipe' });
|
|
399
|
+
} catch { /* non-fatal */ }
|
|
400
|
+
|
|
401
|
+
console.log(`Disabled: ${UNIT_NAME}`);
|
|
402
|
+
return 0;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function linuxStatus() {
|
|
406
|
+
const unitPath = systemdUnitPath();
|
|
407
|
+
const unitExists = existsSync(unitPath);
|
|
408
|
+
console.log(`Unit: ${unitPath} (${unitExists ? 'present' : 'absent'})`);
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
const active = execSync(`systemctl --user is-active ${UNIT_NAME}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
412
|
+
console.log(`Service ${UNIT_NAME}: ${active}`);
|
|
413
|
+
return active === 'active' ? 0 : 2;
|
|
414
|
+
} catch {
|
|
415
|
+
console.log(`Service ${UNIT_NAME}: not active or not installed.`);
|
|
416
|
+
return unitExists ? 2 : 0;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// --- Windows stub -------------------------------------------------------
|
|
421
|
+
|
|
422
|
+
function windowsNotSupported() {
|
|
423
|
+
console.error('Error: Windows service installation is not yet implemented.');
|
|
424
|
+
console.error('Open an issue on Stravica/dave if you need this, or run the');
|
|
425
|
+
console.error('workspace manually with: pa workspace start (or node node_modules/@stravica-ai/engineering-pa-workspace/src/ws.mjs start)');
|
|
426
|
+
return 2;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// --- Platform dispatcher -------------------------------------------------
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Route to the correct backend for the host platform.
|
|
433
|
+
* Exported so tests can exercise the routing independently of real OS calls.
|
|
434
|
+
* @param {string} plat - platform() return value
|
|
435
|
+
* @returns {string} - 'darwin' | 'linux' | 'win32' | 'unsupported'
|
|
436
|
+
*/
|
|
437
|
+
export function routePlatform(plat) {
|
|
438
|
+
if (plat === 'darwin') return 'darwin';
|
|
439
|
+
if (plat === 'linux') return 'linux';
|
|
440
|
+
if (plat === 'win32') return 'win32';
|
|
441
|
+
return 'unsupported';
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// --- Shell quoting ------------------------------------------------------
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Quote a path for inclusion in a shell command. launchctl/systemctl invocations
|
|
448
|
+
* go through the shell via execSync, so paths with spaces need quoting.
|
|
449
|
+
* @param {string} s
|
|
450
|
+
*/
|
|
451
|
+
function shellQuote(s) {
|
|
452
|
+
if (!/[^A-Za-z0-9_\-./]/.test(s)) return s;
|
|
453
|
+
return `'${String(s).replace(/'/g, `'\\''`)}'`;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// --- CLI ----------------------------------------------------------------
|
|
457
|
+
|
|
458
|
+
const USAGE = `Usage: node install-daemon.mjs <command> [options]
|
|
459
|
+
|
|
460
|
+
Commands:
|
|
461
|
+
install [--port N] [--dry-run] Install + start the workspace daemon
|
|
462
|
+
uninstall [--dry-run] Stop + remove the daemon
|
|
463
|
+
status Show daemon status
|
|
464
|
+
--help, -h Show this help
|
|
465
|
+
|
|
466
|
+
Options:
|
|
467
|
+
--port N Override the port (default: reads operator/config/preferences.json, falls back to 4200)
|
|
468
|
+
--dry-run Print what would happen; do not write files or invoke the service manager
|
|
469
|
+
|
|
470
|
+
Exit codes:
|
|
471
|
+
0 OK
|
|
472
|
+
1 Usage error
|
|
473
|
+
2 Unsupported platform / logical failure
|
|
474
|
+
3 Transport failure (launchctl/systemctl call)
|
|
475
|
+
`;
|
|
476
|
+
|
|
477
|
+
function parseArgs(argv) {
|
|
478
|
+
const out = { command: null, port: undefined, dryRun: false };
|
|
479
|
+
const args = argv.slice();
|
|
480
|
+
while (args.length > 0) {
|
|
481
|
+
const a = args.shift();
|
|
482
|
+
if (a === '--help' || a === '-h') { out.command = 'help'; continue; }
|
|
483
|
+
if (a === '--dry-run') { out.dryRun = true; continue; }
|
|
484
|
+
if (a === '--port') { out.port = args.shift(); continue; }
|
|
485
|
+
if (out.command === null) { out.command = a; continue; }
|
|
486
|
+
throw Object.assign(new Error(`Unexpected argument: ${a}`), { exitCode: 1 });
|
|
487
|
+
}
|
|
488
|
+
return out;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export async function main(argv) {
|
|
492
|
+
let parsed;
|
|
493
|
+
try {
|
|
494
|
+
parsed = parseArgs(argv);
|
|
495
|
+
} catch (err) {
|
|
496
|
+
console.error(`Error: ${err.message}`);
|
|
497
|
+
console.error(USAGE);
|
|
498
|
+
return err.exitCode || 1;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (parsed.command === 'help' || parsed.command === null) {
|
|
502
|
+
console.log(USAGE);
|
|
503
|
+
return parsed.command === null ? 1 : 0;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
let port = null;
|
|
507
|
+
if (parsed.command === 'install') {
|
|
508
|
+
try {
|
|
509
|
+
port = resolvePort(parsed.port);
|
|
510
|
+
} catch (err) {
|
|
511
|
+
console.error(`Error: ${err.message}`);
|
|
512
|
+
return err.exitCode || 1;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
const plat = routePlatform(platform());
|
|
516
|
+
|
|
517
|
+
if (plat === 'unsupported') {
|
|
518
|
+
console.error(`Error: Platform ${platform()} is not supported.`);
|
|
519
|
+
return 2;
|
|
520
|
+
}
|
|
521
|
+
if (plat === 'win32') {
|
|
522
|
+
if (parsed.command === 'install' || parsed.command === 'uninstall' || parsed.command === 'status') {
|
|
523
|
+
return windowsNotSupported();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
switch (parsed.command) {
|
|
528
|
+
case 'install':
|
|
529
|
+
if (plat === 'darwin') return darwinInstall({ port, dryRun: parsed.dryRun });
|
|
530
|
+
if (plat === 'linux') return linuxInstall({ port, dryRun: parsed.dryRun });
|
|
531
|
+
break;
|
|
532
|
+
case 'uninstall':
|
|
533
|
+
if (plat === 'darwin') return darwinUninstall({ dryRun: parsed.dryRun });
|
|
534
|
+
if (plat === 'linux') return linuxUninstall({ dryRun: parsed.dryRun });
|
|
535
|
+
break;
|
|
536
|
+
case 'status':
|
|
537
|
+
if (plat === 'darwin') return darwinStatus();
|
|
538
|
+
if (plat === 'linux') return linuxStatus();
|
|
539
|
+
break;
|
|
540
|
+
default:
|
|
541
|
+
console.error(`Error: Unknown command '${parsed.command}'.`);
|
|
542
|
+
console.error(USAGE);
|
|
543
|
+
return 1;
|
|
544
|
+
}
|
|
545
|
+
return 1;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// --- Entry point --------------------------------------------------------
|
|
549
|
+
//
|
|
550
|
+
// Under pnpm's hoisted layout, `import.meta.url` realpath-resolves through
|
|
551
|
+
// `.pnpm/...` while `process.argv[1]` keeps the symlinked path. A naive
|
|
552
|
+
// equality check would always be false and the CLI would silently no-op.
|
|
553
|
+
// Realpath both sides so the comparison reflects file identity. If argv[1]
|
|
554
|
+
// is unset or unresolvable (e.g. imported by tests), treat as not-main.
|
|
555
|
+
|
|
556
|
+
const isMainModule = (() => {
|
|
557
|
+
if (!process.argv[1]) return false;
|
|
558
|
+
try {
|
|
559
|
+
return import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
|
|
560
|
+
} catch {
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
})();
|
|
564
|
+
|
|
565
|
+
if (isMainModule) {
|
|
566
|
+
try {
|
|
567
|
+
const code = await main(process.argv.slice(2));
|
|
568
|
+
process.exit(code);
|
|
569
|
+
} catch (err) {
|
|
570
|
+
console.error(`Error: ${err.message}`);
|
|
571
|
+
process.exit(err.exitCode || 3);
|
|
572
|
+
}
|
|
573
|
+
}
|