@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,516 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dave Workspace -- persistent dev server.
|
|
5
|
+
*
|
|
6
|
+
* Serves the dave repo as static HTML pages plus a JSON API.
|
|
7
|
+
* Auto-shuts down after 2 hours of idle time.
|
|
8
|
+
*
|
|
9
|
+
* Live-reload / SSE was removed pending a workspace rebuild — see PR
|
|
10
|
+
* "Remove live-reload SSE mechanism (temporary — pending workspace rebuild)".
|
|
11
|
+
* Manual browser refresh (Cmd+R / Ctrl+R) is the current model.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node server.mjs Start on default port (4200)
|
|
15
|
+
* node server.mjs --port 5555 Use specific port
|
|
16
|
+
* node server.mjs --no-open Don't auto-open browser
|
|
17
|
+
* node server.mjs --timeout 60 Idle timeout in minutes (default: 120)
|
|
18
|
+
* node server.mjs --no-timeout Disable idle timeout
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { createServer } from 'node:http';
|
|
22
|
+
import { readFile, stat, readdir } from 'node:fs/promises';
|
|
23
|
+
import { readFileSync, existsSync, realpathSync } from 'node:fs';
|
|
24
|
+
import { execSync } from 'node:child_process';
|
|
25
|
+
import { resolve, join, extname } from 'node:path';
|
|
26
|
+
import { fileURLToPath } from 'node:url';
|
|
27
|
+
import { handleApi } from './api.mjs';
|
|
28
|
+
import { loadNav } from './nav.mjs';
|
|
29
|
+
import { startPoller as startStatusMonPoller } from './status-mon/poller.mjs';
|
|
30
|
+
|
|
31
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
32
|
+
|
|
33
|
+
// In v2 the workspace package is installed inside the operator repo at
|
|
34
|
+
// `node_modules/@stravica-ai/engineering-pa-workspace/`. The operator repo root
|
|
35
|
+
// is wherever `.git` lives — discovered by walking up from process.cwd(), or
|
|
36
|
+
// taken from DAVE_REPO_ROOT / PA_REPO_ROOT for tests and ephemeral harnesses.
|
|
37
|
+
// The package's own assets live at `../app/` (one level up from src/).
|
|
38
|
+
function findRepoRootSync(start) {
|
|
39
|
+
let d = start;
|
|
40
|
+
let prev;
|
|
41
|
+
while (d && d !== prev) {
|
|
42
|
+
try {
|
|
43
|
+
const s = existsSync(join(d, '.git'));
|
|
44
|
+
if (s) return d;
|
|
45
|
+
} catch { /* ignore */ }
|
|
46
|
+
prev = d;
|
|
47
|
+
d = resolve(d, '..');
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const envRepoRoot = process.env.DAVE_REPO_ROOT || process.env.PA_REPO_ROOT;
|
|
53
|
+
const REPO_ROOT = envRepoRoot
|
|
54
|
+
? resolve(envRepoRoot)
|
|
55
|
+
: (findRepoRootSync(process.cwd()) || process.cwd());
|
|
56
|
+
const APP_DIR = resolve(__dirname, '..', 'app');
|
|
57
|
+
|
|
58
|
+
// Silent by default. Set WS_DEBUG=1 to re-enable startup banner, file-change
|
|
59
|
+
// notifications, extension-load messages, and shutdown traces.
|
|
60
|
+
const DEBUG = process.env.WS_DEBUG === '1';
|
|
61
|
+
const log = DEBUG ? console.log.bind(console) : function () {};
|
|
62
|
+
const warn = DEBUG ? console.warn.bind(console) : function () {};
|
|
63
|
+
|
|
64
|
+
// --- Extension dir ---
|
|
65
|
+
// Convention: operator/extensions/workspace/ overlays core app pages and
|
|
66
|
+
// can register additional API routes. No config required — presence of the
|
|
67
|
+
// directory activates the mechanism.
|
|
68
|
+
const EXT_DIR_PATH = join(REPO_ROOT, 'operator', 'extensions', 'workspace');
|
|
69
|
+
const EXT_DIR = existsSync(EXT_DIR_PATH) ? EXT_DIR_PATH : null;
|
|
70
|
+
|
|
71
|
+
// --- Args ---
|
|
72
|
+
const args = process.argv.slice(2);
|
|
73
|
+
let port = 4200;
|
|
74
|
+
let autoOpen = true;
|
|
75
|
+
let timeoutMinutes = 120;
|
|
76
|
+
let noTimeout = false;
|
|
77
|
+
|
|
78
|
+
// Read configured port from preferences if available
|
|
79
|
+
try {
|
|
80
|
+
const prefsPath = join(REPO_ROOT, 'operator', 'config', 'preferences.json');
|
|
81
|
+
const prefs = JSON.parse(readFileSync(prefsPath, 'utf-8'));
|
|
82
|
+
if (prefs.workspacePort) port = prefs.workspacePort;
|
|
83
|
+
} catch { /* no prefs yet — use default */ }
|
|
84
|
+
|
|
85
|
+
// CLI flags override preferences
|
|
86
|
+
for (let i = 0; i < args.length; i++) {
|
|
87
|
+
switch (args[i]) {
|
|
88
|
+
case '--port': port = parseInt(args[++i], 10); break;
|
|
89
|
+
case '--no-open': autoOpen = false; break;
|
|
90
|
+
case '--timeout': timeoutMinutes = parseInt(args[++i], 10); break;
|
|
91
|
+
case '--no-timeout': noTimeout = true; break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const IDLE_TIMEOUT_MS = timeoutMinutes * 60 * 1000;
|
|
96
|
+
|
|
97
|
+
// Side-effect gate. This file is imported by tests to assert exports (Option
|
|
98
|
+
// D). When it is imported (not run), we must NOT attach status-mon or bind a
|
|
99
|
+
// port. Everything side-effectful below is guarded on this flag.
|
|
100
|
+
//
|
|
101
|
+
// Under pnpm's hoisted layout, this file's real path lives under
|
|
102
|
+
// `node_modules/.pnpm/...`, while `process.argv[1]` keeps the symlinked path
|
|
103
|
+
// at `node_modules/@stravica-ai/engineering-pa-workspace/src/server.mjs`. A naive
|
|
104
|
+
// equality check would always be false. Realpath both sides so the comparison
|
|
105
|
+
// reflects the underlying file identity.
|
|
106
|
+
const isMainModule = (() => {
|
|
107
|
+
if (!process.argv[1]) return false;
|
|
108
|
+
try {
|
|
109
|
+
return fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]));
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
})();
|
|
114
|
+
|
|
115
|
+
// --- Extension API routes ---
|
|
116
|
+
// Populated by loadExtensions() before the server starts.
|
|
117
|
+
// Extension routes shadow core routes when method + pathname match.
|
|
118
|
+
const extRoutes = [];
|
|
119
|
+
|
|
120
|
+
// --- MIME types ---
|
|
121
|
+
const MIME = {
|
|
122
|
+
'.html': 'text/html',
|
|
123
|
+
'.css': 'text/css',
|
|
124
|
+
'.js': 'application/javascript',
|
|
125
|
+
'.mjs': 'application/javascript',
|
|
126
|
+
'.json': 'application/json',
|
|
127
|
+
'.png': 'image/png',
|
|
128
|
+
'.jpg': 'image/jpeg',
|
|
129
|
+
'.jpeg': 'image/jpeg',
|
|
130
|
+
'.svg': 'image/svg+xml',
|
|
131
|
+
'.ico': 'image/x-icon',
|
|
132
|
+
'.md': 'text/html',
|
|
133
|
+
'.txt': 'text/plain',
|
|
134
|
+
'.woff': 'font/woff',
|
|
135
|
+
'.woff2': 'font/woff2',
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// --- Page URL resolution ---
|
|
139
|
+
// Workspace pages are addressable by two URL shapes:
|
|
140
|
+
// - the bare top-level form: /<page>.html
|
|
141
|
+
// - the shell-prefixed form: /core/tools/workspace/app/<page>.html
|
|
142
|
+
//
|
|
143
|
+
// The hash-routed shell at / loads inner pages via the prefixed form; older
|
|
144
|
+
// direct links use the bare form. Both must honour the operator overlay the
|
|
145
|
+
// same way — pre-1.0 a regex pinned the overlay block to the bare form only
|
|
146
|
+
// and the prefixed form silently went to the bundled APP_DIR, defeating the
|
|
147
|
+
// overlay for anyone who navigated via the shell.
|
|
148
|
+
//
|
|
149
|
+
// Returns the basename (e.g. 'project-detail.html') when pathname targets an
|
|
150
|
+
// .html app page in either form; returns null for assets, deep paths,
|
|
151
|
+
// dotfile probes, or non-html URLs. Exported for unit testing.
|
|
152
|
+
export const WORKSPACE_PREFIX = '/core/tools/workspace/app/';
|
|
153
|
+
export function appPageBasename(pathname) {
|
|
154
|
+
if (!pathname || pathname.startsWith('/.')) return null;
|
|
155
|
+
const stripped = pathname.startsWith(WORKSPACE_PREFIX)
|
|
156
|
+
? '/' + pathname.slice(WORKSPACE_PREFIX.length)
|
|
157
|
+
: pathname;
|
|
158
|
+
const m = stripped.match(/^\/([^/]+\.html)$/);
|
|
159
|
+
return m ? m[1] : null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// --- Activity timer ---
|
|
163
|
+
// The server auto-shuts after IDLE_TIMEOUT_MS from startup unless
|
|
164
|
+
// --no-timeout is set (the daemon path always passes --no-timeout). The
|
|
165
|
+
// previous implementation reset the timer from the SSE file-watcher; with
|
|
166
|
+
// live-reload gone, the timer is armed once at listen() and fires on the
|
|
167
|
+
// wall clock — sufficient for the daemon (never fires) and for interactive
|
|
168
|
+
// sessions (a 2-hour cap on a lingering foreground process).
|
|
169
|
+
let idleTimer;
|
|
170
|
+
function resetIdle() {
|
|
171
|
+
if (noTimeout) return;
|
|
172
|
+
clearTimeout(idleTimer);
|
|
173
|
+
idleTimer = setTimeout(() => {
|
|
174
|
+
log('[workspace] Idle for ' + timeoutMinutes + ' minutes. Shutting down.');
|
|
175
|
+
process.exit(0);
|
|
176
|
+
}, IDLE_TIMEOUT_MS);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// --- Markdown HTML template ---
|
|
180
|
+
//
|
|
181
|
+
// Auto-wraps a raw .md request into a styled HTML page. The chrome here
|
|
182
|
+
// duplicates viewer.html's surface — both used to embed their own :root
|
|
183
|
+
// palette block, which broke the theme toggle on the content-calendar
|
|
184
|
+
// preview iframe (operator-reported, 2026-06-27). The fix matches what
|
|
185
|
+
// viewer.html does: link the shared theme.css, defer-load theme.js, pre-paint
|
|
186
|
+
// init reads localStorage 'dave.theme', body in humanist sans for prose, and
|
|
187
|
+
// .md-body strong uses the new --emphasis token (matching .content strong).
|
|
188
|
+
// Exported so unit tests can assert on the output without spinning up the
|
|
189
|
+
// HTTP server.
|
|
190
|
+
export function markdownPage(rawContent, filePath) {
|
|
191
|
+
const escaped = rawContent
|
|
192
|
+
.replace(/\\/g, '\\\\')
|
|
193
|
+
.replace(/`/g, '\\`')
|
|
194
|
+
.replace(/\$/g, '\\$');
|
|
195
|
+
const title = filePath.split('/').pop().replace(/\.md$/, '');
|
|
196
|
+
return `<!DOCTYPE html>
|
|
197
|
+
<html lang="en">
|
|
198
|
+
<head>
|
|
199
|
+
<meta charset="UTF-8">
|
|
200
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
201
|
+
<title>${title}</title>
|
|
202
|
+
<script>(function(){try{var t=localStorage.getItem('dave.theme');document.documentElement.dataset.theme=(t==='light'||t==='dark')?t:'dark';}catch(_){document.documentElement.dataset.theme='dark';}})();</script>
|
|
203
|
+
<link rel="stylesheet" href="/core/tools/workspace/app/assets/theme.css">
|
|
204
|
+
<script src="/core/tools/workspace/app/assets/theme.js" defer></script>
|
|
205
|
+
<style>
|
|
206
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
207
|
+
body {
|
|
208
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
209
|
+
background: var(--bg); color: var(--text); padding: 2rem; line-height: 1.7;
|
|
210
|
+
font-size: 16px;
|
|
211
|
+
}
|
|
212
|
+
.md-body { max-width: 760px; margin: 0 auto; }
|
|
213
|
+
.md-body h1 { color: var(--purple); font-size: 1.8rem; margin: 1.5rem 0 0.75rem; border-bottom: 1px solid var(--border); padding-bottom: 0.4rem; line-height: 1.25; }
|
|
214
|
+
.md-body h2 { color: var(--accent); font-size: 1.4rem; margin: 1.3rem 0 0.6rem; line-height: 1.3; }
|
|
215
|
+
.md-body h3 { color: var(--cyan); font-size: 1.15rem; margin: 1.1rem 0 0.5rem; line-height: 1.35; }
|
|
216
|
+
.md-body h4 { color: var(--text-bright); font-size: 1rem; margin: 1rem 0 0.4rem; line-height: 1.4; }
|
|
217
|
+
.md-body p { margin: 0.6rem 0; }
|
|
218
|
+
.md-body a { color: var(--accent); text-decoration: none; }
|
|
219
|
+
.md-body a:hover { text-decoration: underline; }
|
|
220
|
+
.md-body strong { color: var(--emphasis); font-weight: 700; }
|
|
221
|
+
.md-body em { color: var(--text); font-style: italic; }
|
|
222
|
+
.md-body code { background: var(--bg-surface); color: var(--orange); padding: 0.15rem 0.35rem; border-radius: 3px; font-size: 0.9em; font-family: 'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; }
|
|
223
|
+
.md-body pre { background: var(--bg-surface); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; overflow-x: auto; margin: 0.8rem 0; }
|
|
224
|
+
.md-body pre code { background: none; color: var(--text); padding: 0; font-size: 0.85rem; font-family: 'SF Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; }
|
|
225
|
+
.md-body ul, .md-body ol { margin: 0.5rem 0 0.5rem 1.5rem; }
|
|
226
|
+
.md-body li { margin: 0.25rem 0; }
|
|
227
|
+
.md-body li::marker { color: var(--text-dim); }
|
|
228
|
+
.md-body blockquote { border-left: 3px solid var(--accent); margin: 0.8rem 0; padding: 0.4rem 0 0.4rem 1rem; color: var(--text-dim); background: var(--bg-surface); border-radius: 0 4px 4px 0; }
|
|
229
|
+
.md-body hr { border: none; border-top: 1px solid var(--border); margin: 1.5rem 0; }
|
|
230
|
+
.md-body table { border-collapse: collapse; margin: 0.8rem 0; width: 100%; }
|
|
231
|
+
.md-body th, .md-body td { border: 1px solid var(--border); padding: 0.4rem 0.7rem; text-align: left; font-size: 0.85rem; }
|
|
232
|
+
.md-body th { background: var(--bg-highlight); color: var(--text-bright); }
|
|
233
|
+
.md-body td { background: var(--bg-surface); }
|
|
234
|
+
</style>
|
|
235
|
+
</head>
|
|
236
|
+
<body>
|
|
237
|
+
<div class="md-body" id="content"></div>
|
|
238
|
+
<script>
|
|
239
|
+
(function() {
|
|
240
|
+
var raw = \`${escaped}\`;
|
|
241
|
+
function parseMd(src) {
|
|
242
|
+
var codeBlocks = [];
|
|
243
|
+
src = src.replace(/\\\`\\\`\\\`(\\w*)\\n([\\s\\S]*?)\\\`\\\`\\\`/g, function(_, lang, code) {
|
|
244
|
+
codeBlocks.push('<pre><code>' + esc(code.replace(/\\n$/, '')) + '</code></pre>');
|
|
245
|
+
return '%%CB_' + (codeBlocks.length - 1) + '%%';
|
|
246
|
+
});
|
|
247
|
+
var lines = src.split('\\n');
|
|
248
|
+
var html = '';
|
|
249
|
+
var inList = false, listType = '', inBq = false, bqLines = [];
|
|
250
|
+
function flushBq() { if (inBq) { html += '<blockquote>' + bqLines.map(function(l) { return '<p>' + inline(l) + '</p>'; }).join('') + '</blockquote>'; bqLines = []; inBq = false; } }
|
|
251
|
+
function closeList() { if (inList) { html += '</' + listType + '>'; inList = false; listType = ''; } }
|
|
252
|
+
for (var i = 0; i < lines.length; i++) {
|
|
253
|
+
var line = lines[i];
|
|
254
|
+
var cbm = line.match(/^%%CB_(\\d+)%%$/);
|
|
255
|
+
if (cbm) { flushBq(); closeList(); html += codeBlocks[parseInt(cbm[1])]; continue; }
|
|
256
|
+
if (line.match(/^>\\s?/)) { closeList(); inBq = true; bqLines.push(line.replace(/^>\\s?/, '')); continue; } else { flushBq(); }
|
|
257
|
+
var hm = line.match(/^(#{1,6})\\s+(.+)$/);
|
|
258
|
+
if (hm) { closeList(); html += '<h' + hm[1].length + '>' + inline(hm[2]) + '</h' + hm[1].length + '>'; continue; }
|
|
259
|
+
if (line.match(/^(---+|\\*\\*\\*+|___+)\\s*$/)) { closeList(); html += '<hr>'; continue; }
|
|
260
|
+
var ulm = line.match(/^\\s*[-*+]\\s+(.+)$/);
|
|
261
|
+
if (ulm) { if (!inList || listType !== 'ul') { closeList(); html += '<ul>'; inList = true; listType = 'ul'; } html += '<li>' + inline(ulm[1]) + '</li>'; continue; }
|
|
262
|
+
var olm = line.match(/^\\s*\\d+\\.\\s+(.+)$/);
|
|
263
|
+
if (olm) { if (!inList || listType !== 'ol') { closeList(); html += '<ol>'; inList = true; listType = 'ol'; } html += '<li>' + inline(olm[1]) + '</li>'; continue; }
|
|
264
|
+
closeList();
|
|
265
|
+
if (line.trim() === '') continue;
|
|
266
|
+
if (line.includes('|') && line.trim().startsWith('|')) {
|
|
267
|
+
var tl = []; var j = i;
|
|
268
|
+
while (j < lines.length && lines[j].trim().startsWith('|')) { tl.push(lines[j]); j++; }
|
|
269
|
+
if (tl.length >= 2) { html += renderTable(tl); i = j - 1; continue; }
|
|
270
|
+
}
|
|
271
|
+
html += '<p>' + inline(line) + '</p>';
|
|
272
|
+
}
|
|
273
|
+
closeList(); flushBq();
|
|
274
|
+
return html;
|
|
275
|
+
}
|
|
276
|
+
function renderTable(rows) {
|
|
277
|
+
var p = function(r) { return r.replace(/^\\|/, '').replace(/\\|$/, '').split('|').map(function(c) { return c.trim(); }); };
|
|
278
|
+
var hdr = p(rows[0]); var h = '<table><thead><tr>';
|
|
279
|
+
hdr.forEach(function(c) { h += '<th>' + inline(c) + '</th>'; });
|
|
280
|
+
h += '</tr></thead><tbody>';
|
|
281
|
+
for (var r = 2; r < rows.length; r++) { var cells = p(rows[r]); h += '<tr>'; cells.forEach(function(c) { h += '<td>' + inline(c) + '</td>'; }); h += '</tr>'; }
|
|
282
|
+
h += '</tbody></table>'; return h;
|
|
283
|
+
}
|
|
284
|
+
function esc(s) { return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); }
|
|
285
|
+
function inline(s) {
|
|
286
|
+
s = esc(s);
|
|
287
|
+
s = s.replace(/\\\`([^\\\`]+)\\\`/g, '<code>$1</code>');
|
|
288
|
+
s = s.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, '<strong><em>$1</em></strong>');
|
|
289
|
+
s = s.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');
|
|
290
|
+
s = s.replace(/__(.+?)__/g, '<strong>$1</strong>');
|
|
291
|
+
s = s.replace(/\\*(.+?)\\*/g, '<em>$1</em>');
|
|
292
|
+
s = s.replace(/_(.+?)_/g, '<em>$1</em>');
|
|
293
|
+
s = s.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href="$2">$1</a>');
|
|
294
|
+
return s;
|
|
295
|
+
}
|
|
296
|
+
document.getElementById('content').innerHTML = parseMd(raw);
|
|
297
|
+
})();
|
|
298
|
+
</script>
|
|
299
|
+
</body>
|
|
300
|
+
</html>`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// --- HTTP server ---
|
|
304
|
+
const server = createServer(async (req, res) => {
|
|
305
|
+
const url = new URL(req.url, 'http://localhost:' + port);
|
|
306
|
+
const pathname = decodeURIComponent(url.pathname);
|
|
307
|
+
|
|
308
|
+
// API routes -- extension routes shadow core; handleApi handles the rest
|
|
309
|
+
if (pathname.startsWith('/__api/') || pathname.startsWith('/api/')) {
|
|
310
|
+
const extRoute = extRoutes.find(r => r.method === req.method && r.pathname === pathname);
|
|
311
|
+
if (extRoute) { extRoute.handler(req, res, url, REPO_ROOT); return; }
|
|
312
|
+
|
|
313
|
+
// GET /__api/nav -- merged core + extension nav manifest
|
|
314
|
+
if (req.method === 'GET' && pathname === '/__api/nav') {
|
|
315
|
+
try {
|
|
316
|
+
const items = loadNav({ appDir: APP_DIR, extDir: EXT_DIR, warn: warn });
|
|
317
|
+
const body = JSON.stringify({ items: items });
|
|
318
|
+
res.writeHead(200, {
|
|
319
|
+
'Content-Type': 'application/json',
|
|
320
|
+
'Content-Length': Buffer.byteLength(body),
|
|
321
|
+
});
|
|
322
|
+
res.end(body);
|
|
323
|
+
} catch (e) {
|
|
324
|
+
const body = JSON.stringify({ error: e.message, items: [] });
|
|
325
|
+
res.writeHead(500, {
|
|
326
|
+
'Content-Type': 'application/json',
|
|
327
|
+
'Content-Length': Buffer.byteLength(body),
|
|
328
|
+
});
|
|
329
|
+
res.end(body);
|
|
330
|
+
}
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const handled = handleApi(req, res, url, REPO_ROOT);
|
|
335
|
+
if (handled) return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Root serves the shell
|
|
339
|
+
if (pathname === '/' || pathname === '/index.html') {
|
|
340
|
+
try {
|
|
341
|
+
const indexPath = join(APP_DIR, 'index.html');
|
|
342
|
+
const html = await readFile(indexPath, 'utf-8');
|
|
343
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
344
|
+
res.end(html);
|
|
345
|
+
} catch {
|
|
346
|
+
res.writeHead(404);
|
|
347
|
+
res.end('Workspace index not found');
|
|
348
|
+
}
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Top-level workspace assets served out of APP_DIR. Kept here rather than
|
|
353
|
+
// under a workspace-relative prefix so the page-level includes
|
|
354
|
+
// (e.g. <script src="/banner.js">) stay terse and version-independent.
|
|
355
|
+
if (pathname === '/banner.js') {
|
|
356
|
+
try {
|
|
357
|
+
const content = await readFile(join(APP_DIR, 'banner.js'));
|
|
358
|
+
res.writeHead(200, { 'Content-Type': 'application/javascript; charset=utf-8' });
|
|
359
|
+
res.end(content);
|
|
360
|
+
} catch {
|
|
361
|
+
res.writeHead(404);
|
|
362
|
+
res.end('Not found');
|
|
363
|
+
}
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Workspace app pages: both /<page>.html and /core/tools/workspace/app/<page>.html
|
|
368
|
+
// check EXT_DIR first (operator overlay), then APP_DIR (core). The shell at /
|
|
369
|
+
// hash-routes inner pages via the prefixed form, so honouring overlays for that
|
|
370
|
+
// form too is what lets operator extensions actually shadow shell-loaded pages.
|
|
371
|
+
// Fall through to asset/repo-root serving when absent in both.
|
|
372
|
+
const pageBase = appPageBasename(pathname);
|
|
373
|
+
if (pageBase) {
|
|
374
|
+
const candidates = EXT_DIR
|
|
375
|
+
? [join(EXT_DIR, pageBase), join(APP_DIR, pageBase)]
|
|
376
|
+
: [join(APP_DIR, pageBase)];
|
|
377
|
+
for (const candidate of candidates) {
|
|
378
|
+
try {
|
|
379
|
+
const html = await readFile(candidate, 'utf-8');
|
|
380
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
381
|
+
res.end(html);
|
|
382
|
+
return;
|
|
383
|
+
} catch { /* try next candidate */ }
|
|
384
|
+
}
|
|
385
|
+
// Not found in EXT_DIR or APP_DIR — fall through to asset/repo-root serving
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Workspace app assets live with the server code, not under REPO_ROOT.
|
|
389
|
+
// When DAVE_REPO_ROOT is overridden (E2E fixtures), absolute paths that
|
|
390
|
+
// point at the workspace script tree must still resolve against APP_DIR's
|
|
391
|
+
// parent so pages can load their CSS/JS regardless of the fixture root.
|
|
392
|
+
// Historical absolute-URL prefix preserved so existing operator pages that
|
|
393
|
+
// hard-code these paths keep working through the transition. The server
|
|
394
|
+
// strips the prefix and serves out of the package's bundled APP_DIR.
|
|
395
|
+
const filePath = pathname.startsWith(WORKSPACE_PREFIX)
|
|
396
|
+
? join(APP_DIR, pathname.slice(WORKSPACE_PREFIX.length))
|
|
397
|
+
: join(REPO_ROOT, pathname);
|
|
398
|
+
|
|
399
|
+
// Security: no traversal outside repo, no .git or .env. Workspace app
|
|
400
|
+
// assets under APP_DIR are always allowed regardless of REPO_ROOT.
|
|
401
|
+
const allowedBase = pathname.startsWith(WORKSPACE_PREFIX) ? APP_DIR : REPO_ROOT;
|
|
402
|
+
if (!filePath.startsWith(allowedBase) || pathname.includes('/.git/') || pathname.includes('/.env')) {
|
|
403
|
+
res.writeHead(403);
|
|
404
|
+
res.end('Forbidden');
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
try {
|
|
409
|
+
const fileStat = await stat(filePath);
|
|
410
|
+
|
|
411
|
+
if (fileStat.isDirectory()) {
|
|
412
|
+
const indexPath = join(filePath, 'index.html');
|
|
413
|
+
try {
|
|
414
|
+
const html = await readFile(indexPath, 'utf-8');
|
|
415
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
416
|
+
res.end(html);
|
|
417
|
+
} catch {
|
|
418
|
+
res.writeHead(404);
|
|
419
|
+
res.end('Not found');
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const content = await readFile(filePath);
|
|
425
|
+
const ext = extname(filePath);
|
|
426
|
+
const mime = MIME[ext] || 'application/octet-stream';
|
|
427
|
+
|
|
428
|
+
if (ext === '.md') {
|
|
429
|
+
const mdContent = content.toString('utf-8');
|
|
430
|
+
const html = markdownPage(mdContent, pathname);
|
|
431
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
432
|
+
res.end(html);
|
|
433
|
+
} else {
|
|
434
|
+
res.writeHead(200, { 'Content-Type': mime });
|
|
435
|
+
res.end(content);
|
|
436
|
+
}
|
|
437
|
+
} catch {
|
|
438
|
+
res.writeHead(404);
|
|
439
|
+
res.end('Not found');
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// --- Extension loader ---
|
|
444
|
+
// Imports operator/extensions/workspace/api.mjs (if present) and calls its
|
|
445
|
+
// register(addRoute) export. Extensions can add routes or shadow core routes.
|
|
446
|
+
// A shadowed route is logged at startup so operators know the override is live.
|
|
447
|
+
async function loadExtensions() {
|
|
448
|
+
if (!EXT_DIR) return;
|
|
449
|
+
const extApiPath = join(EXT_DIR, 'api.mjs');
|
|
450
|
+
if (!existsSync(extApiPath)) return;
|
|
451
|
+
try {
|
|
452
|
+
const extApi = await import(extApiPath);
|
|
453
|
+
if (typeof extApi.register === 'function') {
|
|
454
|
+
extApi.register(function addRoute(method, pathname, handler) {
|
|
455
|
+
const shadows = extRoutes.some(r => r.method === method && r.pathname === pathname);
|
|
456
|
+
if (!shadows) {
|
|
457
|
+
// Check if it shadows a core route (informational only).
|
|
458
|
+
log('[workspace] Extension route registered: ' + method + ' ' + pathname);
|
|
459
|
+
}
|
|
460
|
+
extRoutes.push({ method: method, pathname: pathname, handler: handler });
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
} catch (e) {
|
|
464
|
+
warn('[workspace] Extension api.mjs failed to load: ' + e.message);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// --- Status-mon poller ---
|
|
469
|
+
// Runs inside the workspace process because the server is the always-on
|
|
470
|
+
// component on this host (launchd-supervised). A separate scheduled task would
|
|
471
|
+
// duplicate supervision. Disabled when DAVE_REPO_ROOT is overridden (E2E
|
|
472
|
+
// fixture runs), because tests drive the state file directly via fixtures.
|
|
473
|
+
let statusMonHandle = null;
|
|
474
|
+
if (isMainModule && !process.env.DAVE_REPO_ROOT && process.env.WS_STATUS_MON !== '0') {
|
|
475
|
+
try {
|
|
476
|
+
statusMonHandle = startStatusMonPoller({
|
|
477
|
+
repoRoot: REPO_ROOT,
|
|
478
|
+
onError: (err) => warn('[workspace] status-mon poll error: ' + err.message),
|
|
479
|
+
});
|
|
480
|
+
log('[workspace] status-mon poller started (60s cadence)');
|
|
481
|
+
} catch (err) {
|
|
482
|
+
warn('[workspace] status-mon poller failed to start: ' + err.message);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// --- Start ---
|
|
487
|
+
// Only auto-start when this file is the process entry point. Tests import
|
|
488
|
+
// server.mjs to assert exports; they must not spawn a listening server as a
|
|
489
|
+
// side effect.
|
|
490
|
+
if (isMainModule) (async function () {
|
|
491
|
+
await loadExtensions();
|
|
492
|
+
|
|
493
|
+
server.listen(port, () => {
|
|
494
|
+
const url = 'http://localhost:' + port;
|
|
495
|
+
log('[workspace] Dave Workspace running at ' + url);
|
|
496
|
+
log('[workspace] Serving from: ' + REPO_ROOT);
|
|
497
|
+
if (EXT_DIR) log('[workspace] Extensions: ' + EXT_DIR.replace(REPO_ROOT + '/', ''));
|
|
498
|
+
log('[workspace] Idle timeout: ' + (noTimeout ? 'disabled (persistent)' : timeoutMinutes + ' minutes'));
|
|
499
|
+
|
|
500
|
+
if (autoOpen) {
|
|
501
|
+
try { execSync('open "' + url + '"'); } catch { /* non-fatal */ }
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
resetIdle();
|
|
505
|
+
});
|
|
506
|
+
}());
|
|
507
|
+
|
|
508
|
+
function shutdown(signal) {
|
|
509
|
+
if (signal === 'SIGINT') console.log('\n[workspace] Shutting down.');
|
|
510
|
+
if (statusMonHandle) { try { statusMonHandle.stop(); } catch { /* ignore */ } }
|
|
511
|
+
server.close();
|
|
512
|
+
process.exit(0);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
516
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|