@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,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// graph-builder.mjs — Builds a knowledge graph from forward links and backlinks.
|
|
3
|
+
//
|
|
4
|
+
// Reads forward links from markdown files + backlinks from .backlinks.json.
|
|
5
|
+
// Output: operator/knowledge/.graph.json
|
|
6
|
+
//
|
|
7
|
+
// CLI: node graph-builder.mjs [--root /path/to/repo]
|
|
8
|
+
|
|
9
|
+
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
|
10
|
+
import { join, resolve, dirname, relative, normalize } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const DEFAULT_ROOT = resolve(__dirname, '../../../..');
|
|
15
|
+
|
|
16
|
+
const USAGE = `
|
|
17
|
+
graph-builder — Build a knowledge graph from markdown links and backlinks
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
node graph-builder.mjs [options]
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--root <path> Repository root (default: 4 levels up from this script)
|
|
24
|
+
--help, -h Show this help
|
|
25
|
+
|
|
26
|
+
Reads forward links from .md files in operator/knowledge/ and core/knowledge/.
|
|
27
|
+
Reads backlinks from operator/knowledge/.backlinks.json.
|
|
28
|
+
|
|
29
|
+
Output: operator/knowledge/.graph.json
|
|
30
|
+
`.trim();
|
|
31
|
+
|
|
32
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
async function walkDir(dir) {
|
|
35
|
+
const results = [];
|
|
36
|
+
let entries;
|
|
37
|
+
try {
|
|
38
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (err.code === 'ENOENT') return results;
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const full = join(dir, entry.name);
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
if (entry.name.startsWith('.')) continue;
|
|
47
|
+
results.push(...await walkDir(full));
|
|
48
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
49
|
+
results.push(full);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function extractTitle(content) {
|
|
56
|
+
const match = content.match(/^#\s+(.+)$/m);
|
|
57
|
+
return match ? match[1].trim() : null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function extractForwardLinks(content, sourcePath, repoRoot) {
|
|
61
|
+
const links = [];
|
|
62
|
+
const sourceDir = dirname(sourcePath);
|
|
63
|
+
|
|
64
|
+
// Wiki-style: [[target]]
|
|
65
|
+
const wikiRe = /\[\[([^\]]+)\]\]/g;
|
|
66
|
+
let m;
|
|
67
|
+
while ((m = wikiRe.exec(content)) !== null) {
|
|
68
|
+
let target = m[1].trim();
|
|
69
|
+
if (!target.endsWith('.md')) target += '.md';
|
|
70
|
+
links.push(normalize(target));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Markdown-style: [text](relative/path.md)
|
|
74
|
+
const mdRe = /\[([^\]]*)\]\(([^)]+)\)/g;
|
|
75
|
+
while ((m = mdRe.exec(content)) !== null) {
|
|
76
|
+
const href = m[2].trim();
|
|
77
|
+
if (href.startsWith('http://') || href.startsWith('https://') || href.startsWith('#') || href.startsWith('mailto:')) continue;
|
|
78
|
+
const path = href.split('#')[0];
|
|
79
|
+
if (!path || !path.endsWith('.md')) continue;
|
|
80
|
+
const abs = resolve(sourceDir, path);
|
|
81
|
+
const rel = relative(repoRoot, abs);
|
|
82
|
+
links.push(normalize(rel));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return [...new Set(links)];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function deriveDomain(relPath) {
|
|
89
|
+
const parts = relPath.split('/');
|
|
90
|
+
if (parts.length >= 3 && (parts[0] === 'operator' || parts[0] === 'core') && parts[1] === 'knowledge') {
|
|
91
|
+
return parts[2];
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ── Main ────────────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
async function main(args) {
|
|
99
|
+
let root = DEFAULT_ROOT;
|
|
100
|
+
|
|
101
|
+
for (let i = 0; i < args.length; i++) {
|
|
102
|
+
const a = args[i];
|
|
103
|
+
if (a === '--help' || a === '-h') {
|
|
104
|
+
console.log(USAGE);
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
if (a === '--root') {
|
|
108
|
+
root = resolve(args[++i]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const scanDirs = [
|
|
113
|
+
join(root, 'operator', 'knowledge'),
|
|
114
|
+
join(root, 'core', 'knowledge'),
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
const allFiles = [];
|
|
118
|
+
for (const dir of scanDirs) {
|
|
119
|
+
allFiles.push(...await walkDir(dir));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const nodesMap = new Map();
|
|
123
|
+
const edges = [];
|
|
124
|
+
const edgeSet = new Set();
|
|
125
|
+
|
|
126
|
+
for (const filePath of allFiles) {
|
|
127
|
+
const content = await readFile(filePath, 'utf8');
|
|
128
|
+
const relPath = relative(root, filePath);
|
|
129
|
+
const title = extractTitle(content) || relPath.split('/').pop().replace('.md', '');
|
|
130
|
+
const domain = deriveDomain(relPath);
|
|
131
|
+
|
|
132
|
+
nodesMap.set(relPath, { id: relPath, title, domain });
|
|
133
|
+
|
|
134
|
+
const forwardLinks = extractForwardLinks(content, filePath, root);
|
|
135
|
+
for (const target of forwardLinks) {
|
|
136
|
+
const edgeKey = `link:${relPath}->${target}`;
|
|
137
|
+
if (!edgeSet.has(edgeKey)) {
|
|
138
|
+
edgeSet.add(edgeKey);
|
|
139
|
+
edges.push({ from: relPath, to: target, type: 'link' });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Read backlinks and add backlink edges
|
|
145
|
+
const backlinksPath = join(root, 'operator', 'knowledge', '.backlinks.json');
|
|
146
|
+
try {
|
|
147
|
+
const raw = await readFile(backlinksPath, 'utf8');
|
|
148
|
+
const backlinksData = JSON.parse(raw);
|
|
149
|
+
const bl = backlinksData.backlinks || {};
|
|
150
|
+
for (const [target, sources] of Object.entries(bl)) {
|
|
151
|
+
for (const source of sources) {
|
|
152
|
+
const edgeKey = `backlink:${target}->${source}`;
|
|
153
|
+
if (!edgeSet.has(edgeKey)) {
|
|
154
|
+
edgeSet.add(edgeKey);
|
|
155
|
+
edges.push({ from: target, to: source, type: 'backlink' });
|
|
156
|
+
}
|
|
157
|
+
if (!nodesMap.has(target)) {
|
|
158
|
+
nodesMap.set(target, { id: target, title: target.split('/').pop().replace('.md', ''), domain: deriveDomain(target) });
|
|
159
|
+
}
|
|
160
|
+
if (!nodesMap.has(source)) {
|
|
161
|
+
nodesMap.set(source, { id: source, title: source.split('/').pop().replace('.md', ''), domain: deriveDomain(source) });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch (err) {
|
|
166
|
+
if (err.code !== 'ENOENT') throw err;
|
|
167
|
+
console.warn('No .backlinks.json found — run backlink-indexer.mjs first. Building graph from forward links only.');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const nodes = [...nodesMap.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
171
|
+
|
|
172
|
+
const output = {
|
|
173
|
+
version: '1.0',
|
|
174
|
+
generatedAt: new Date().toISOString(),
|
|
175
|
+
nodes,
|
|
176
|
+
edges,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const outPath = join(root, 'operator', 'knowledge', '.graph.json');
|
|
180
|
+
await writeFile(outPath, JSON.stringify(output, null, 2) + '\n', 'utf8');
|
|
181
|
+
console.log(`Wrote ${outPath} (${nodes.length} nodes, ${edges.length} edges)`);
|
|
182
|
+
return 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const exitCode = await main(process.argv.slice(2));
|
|
186
|
+
process.exit(exitCode ?? 0);
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// index-builder.mjs — Builds a domain index from operator/knowledge/ directories.
|
|
3
|
+
//
|
|
4
|
+
// Walks top-level directories under operator/knowledge/, extracts metadata
|
|
5
|
+
// from each domain's README.md, and outputs operator/knowledge/domains.json.
|
|
6
|
+
//
|
|
7
|
+
// CLI: node index-builder.mjs [--root /path/to/repo]
|
|
8
|
+
|
|
9
|
+
import { readdir, readFile, writeFile, stat } from 'node:fs/promises';
|
|
10
|
+
import { join, resolve, dirname } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const DEFAULT_ROOT = process.env.DAVE_ROOT
|
|
15
|
+
? resolve(process.env.DAVE_ROOT)
|
|
16
|
+
: resolve(__dirname, '../../../..');
|
|
17
|
+
|
|
18
|
+
const USAGE = `
|
|
19
|
+
index-builder — Build a domain index from operator knowledge directories
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
node index-builder.mjs [options]
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--root <path> Repository root (default: $DAVE_ROOT if set, else 4 levels up from this script)
|
|
26
|
+
--help, -h Show this help
|
|
27
|
+
|
|
28
|
+
Walks top-level directories under operator/knowledge/.
|
|
29
|
+
Extracts domain metadata from each directory's README.md (first paragraph).
|
|
30
|
+
|
|
31
|
+
Output: operator/knowledge/domains.json
|
|
32
|
+
`.trim();
|
|
33
|
+
|
|
34
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
function slugToName(slug) {
|
|
37
|
+
return slug
|
|
38
|
+
.split('-')
|
|
39
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
40
|
+
.join(' ');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function extractFirstParagraph(content) {
|
|
44
|
+
const lines = stripFrontMatter(content).split('\n');
|
|
45
|
+
let collecting = false;
|
|
46
|
+
const para = [];
|
|
47
|
+
for (const line of lines) {
|
|
48
|
+
const trimmed = line.trim();
|
|
49
|
+
if (trimmed.startsWith('#')) {
|
|
50
|
+
if (collecting) break;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (trimmed === '') {
|
|
54
|
+
if (collecting) break;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
collecting = true;
|
|
58
|
+
para.push(trimmed);
|
|
59
|
+
}
|
|
60
|
+
return para.join(' ') || null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Parses a leading `---`-delimited YAML front-matter block. Only supports
|
|
64
|
+
// the flat `key: value` pairs we need (displayName primarily). Returns an
|
|
65
|
+
// object of parsed keys (string values) or {} when no front-matter is
|
|
66
|
+
// present or parsing fails.
|
|
67
|
+
//
|
|
68
|
+
// We deliberately DO NOT pull in a YAML dependency — the platform is
|
|
69
|
+
// zero-dep by policy, and domain READMEs only need a handful of scalar
|
|
70
|
+
// fields. A strict line-based parser is both sufficient and auditable.
|
|
71
|
+
export function parseFrontMatter(content) {
|
|
72
|
+
if (typeof content !== 'string') return {};
|
|
73
|
+
if (!content.startsWith('---')) return {};
|
|
74
|
+
const lines = content.split(/\r?\n/);
|
|
75
|
+
if (lines[0].trim() !== '---') return {};
|
|
76
|
+
const out = {};
|
|
77
|
+
for (let i = 1; i < lines.length; i++) {
|
|
78
|
+
const line = lines[i];
|
|
79
|
+
if (line.trim() === '---') return out;
|
|
80
|
+
const m = /^([A-Za-z_][\w-]*)\s*:\s*(.*)$/.exec(line);
|
|
81
|
+
if (!m) continue;
|
|
82
|
+
let value = m[2].trim();
|
|
83
|
+
// Strip matching quotes.
|
|
84
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
85
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
86
|
+
value = value.slice(1, -1);
|
|
87
|
+
}
|
|
88
|
+
out[m[1]] = value;
|
|
89
|
+
}
|
|
90
|
+
// Unterminated front-matter — treat as no front-matter so the body
|
|
91
|
+
// parses as written.
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Returns `content` with the leading `---`-delimited front-matter block
|
|
96
|
+
// removed. If there's no front-matter, returns the content unchanged.
|
|
97
|
+
export function stripFrontMatter(content) {
|
|
98
|
+
if (typeof content !== 'string') return '';
|
|
99
|
+
if (!content.startsWith('---')) return content;
|
|
100
|
+
const lines = content.split(/\r?\n/);
|
|
101
|
+
if (lines[0].trim() !== '---') return content;
|
|
102
|
+
for (let i = 1; i < lines.length; i++) {
|
|
103
|
+
if (lines[i].trim() === '---') {
|
|
104
|
+
return lines.slice(i + 1).join('\n');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return content;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function countMdFiles(dir) {
|
|
111
|
+
let count = 0;
|
|
112
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
113
|
+
for (const entry of entries) {
|
|
114
|
+
const full = join(dir, entry.name);
|
|
115
|
+
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
116
|
+
count += await countMdFiles(full);
|
|
117
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
118
|
+
count++;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return count;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function getLatestMtime(dir) {
|
|
125
|
+
let latest = new Date(0);
|
|
126
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
127
|
+
for (const entry of entries) {
|
|
128
|
+
const full = join(dir, entry.name);
|
|
129
|
+
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
130
|
+
const sub = await getLatestMtime(full);
|
|
131
|
+
if (sub > latest) latest = sub;
|
|
132
|
+
} else if (entry.isFile()) {
|
|
133
|
+
const s = await stat(full);
|
|
134
|
+
if (s.mtime > latest) latest = s.mtime;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return latest;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── Main ────────────────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
async function main(args) {
|
|
143
|
+
let root = DEFAULT_ROOT;
|
|
144
|
+
|
|
145
|
+
for (let i = 0; i < args.length; i++) {
|
|
146
|
+
const a = args[i];
|
|
147
|
+
if (a === '--help' || a === '-h') {
|
|
148
|
+
console.log(USAGE);
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
if (a === '--root') {
|
|
152
|
+
root = resolve(args[++i]);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const knowledgeDir = join(root, 'operator', 'knowledge');
|
|
157
|
+
let entries;
|
|
158
|
+
try {
|
|
159
|
+
entries = await readdir(knowledgeDir, { withFileTypes: true });
|
|
160
|
+
} catch (err) {
|
|
161
|
+
if (err.code === 'ENOENT') {
|
|
162
|
+
console.error(`Knowledge directory not found: ${knowledgeDir}`);
|
|
163
|
+
return 1;
|
|
164
|
+
}
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const domains = [];
|
|
169
|
+
|
|
170
|
+
for (const entry of entries) {
|
|
171
|
+
if (!entry.isDirectory()) continue;
|
|
172
|
+
if (entry.name.startsWith('.')) continue;
|
|
173
|
+
|
|
174
|
+
const domainPath = join(knowledgeDir, entry.name);
|
|
175
|
+
const id = entry.name;
|
|
176
|
+
const name = slugToName(id);
|
|
177
|
+
const relPath = `operator/knowledge/${id}`;
|
|
178
|
+
|
|
179
|
+
let description = null;
|
|
180
|
+
let displayName = null;
|
|
181
|
+
try {
|
|
182
|
+
const readme = await readFile(join(domainPath, 'README.md'), 'utf8');
|
|
183
|
+
const fm = parseFrontMatter(readme);
|
|
184
|
+
if (fm && typeof fm.displayName === 'string' && fm.displayName.length) {
|
|
185
|
+
displayName = fm.displayName;
|
|
186
|
+
}
|
|
187
|
+
description = extractFirstParagraph(readme);
|
|
188
|
+
} catch (err) {
|
|
189
|
+
if (err.code !== 'ENOENT') throw err;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const fileCount = await countMdFiles(domainPath);
|
|
193
|
+
const lastUpdated = await getLatestMtime(domainPath);
|
|
194
|
+
|
|
195
|
+
// displayName is emitted only when explicitly set in front-matter.
|
|
196
|
+
// Consumers fall back to `name` (capitalised id) when absent — this
|
|
197
|
+
// keeps the field optional and the downstream schema additive.
|
|
198
|
+
const record = {
|
|
199
|
+
id,
|
|
200
|
+
name,
|
|
201
|
+
path: relPath,
|
|
202
|
+
description,
|
|
203
|
+
fileCount,
|
|
204
|
+
lastUpdated: lastUpdated.toISOString(),
|
|
205
|
+
};
|
|
206
|
+
if (displayName) record.displayName = displayName;
|
|
207
|
+
domains.push(record);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
domains.sort((a, b) => a.id.localeCompare(b.id));
|
|
211
|
+
|
|
212
|
+
const output = {
|
|
213
|
+
version: '1.0',
|
|
214
|
+
generatedAt: new Date().toISOString(),
|
|
215
|
+
domains,
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const outPath = join(knowledgeDir, 'domains.json');
|
|
219
|
+
await writeFile(outPath, JSON.stringify(output, null, 2) + '\n', 'utf8');
|
|
220
|
+
console.log(`Wrote ${outPath} (${domains.length} domains indexed)`);
|
|
221
|
+
return 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const exitCode = await main(process.argv.slice(2));
|
|
225
|
+
process.exit(exitCode ?? 0);
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// query.mjs — Knowledge graph query functions and CLI.
|
|
3
|
+
//
|
|
4
|
+
// Exports:
|
|
5
|
+
// findRelated(path, root) — files linked to/from the given path
|
|
6
|
+
// getBacklinks(path, root) — files that link TO the given path
|
|
7
|
+
// traverseFrom(path, depth, root) — BFS traversal, reachable nodes within depth
|
|
8
|
+
// searchByDomain(domain, root) — all files in a domain
|
|
9
|
+
//
|
|
10
|
+
// CLI:
|
|
11
|
+
// node query.mjs backlinks <path>
|
|
12
|
+
// node query.mjs related <path>
|
|
13
|
+
// node query.mjs traverse <path> [depth]
|
|
14
|
+
// node query.mjs domain <name>
|
|
15
|
+
|
|
16
|
+
import { readFile } from 'node:fs/promises';
|
|
17
|
+
import { realpathSync } from 'node:fs';
|
|
18
|
+
import { join, resolve, dirname, normalize } from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
|
|
21
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const DEFAULT_ROOT = resolve(__dirname, '../../../..');
|
|
23
|
+
|
|
24
|
+
const USAGE = `
|
|
25
|
+
query — Query the knowledge graph
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
node query.mjs <command> [args]
|
|
29
|
+
|
|
30
|
+
Commands:
|
|
31
|
+
backlinks <path> Files that link TO the given path
|
|
32
|
+
related <path> Files linked to/from the given path (forward + back)
|
|
33
|
+
traverse <path> [depth] BFS traversal from a node (default depth: 2)
|
|
34
|
+
domain <name> All files in a domain
|
|
35
|
+
|
|
36
|
+
Options:
|
|
37
|
+
--root <path> Repository root (default: 4 levels up from this script)
|
|
38
|
+
--help, -h Show this help
|
|
39
|
+
|
|
40
|
+
Reads from:
|
|
41
|
+
operator/knowledge/.backlinks.json
|
|
42
|
+
operator/knowledge/.graph.json
|
|
43
|
+
operator/knowledge/domains.json
|
|
44
|
+
`.trim();
|
|
45
|
+
|
|
46
|
+
// ── Index readers ───────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
async function readBacklinks(root) {
|
|
49
|
+
const path = join(root, 'operator', 'knowledge', '.backlinks.json');
|
|
50
|
+
try {
|
|
51
|
+
const raw = await readFile(path, 'utf8');
|
|
52
|
+
return JSON.parse(raw);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
if (err.code === 'ENOENT') return { backlinks: {} };
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function readGraph(root) {
|
|
60
|
+
const path = join(root, 'operator', 'knowledge', '.graph.json');
|
|
61
|
+
try {
|
|
62
|
+
const raw = await readFile(path, 'utf8');
|
|
63
|
+
return JSON.parse(raw);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err.code === 'ENOENT') return { nodes: [], edges: [] };
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function readDomains(root) {
|
|
71
|
+
const path = join(root, 'operator', 'knowledge', 'domains.json');
|
|
72
|
+
try {
|
|
73
|
+
const raw = await readFile(path, 'utf8');
|
|
74
|
+
return JSON.parse(raw);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
if (err.code === 'ENOENT') return { domains: [] };
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Exported query functions ────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
export async function findRelated(path, root = DEFAULT_ROOT) {
|
|
84
|
+
const normPath = normalize(path);
|
|
85
|
+
const graph = await readGraph(root);
|
|
86
|
+
const related = new Set();
|
|
87
|
+
|
|
88
|
+
for (const edge of graph.edges) {
|
|
89
|
+
if (normalize(edge.from) === normPath) related.add(edge.to);
|
|
90
|
+
if (normalize(edge.to) === normPath) related.add(edge.from);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return [...related].sort();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function getBacklinks(path, root = DEFAULT_ROOT) {
|
|
97
|
+
const normPath = normalize(path);
|
|
98
|
+
const data = await readBacklinks(root);
|
|
99
|
+
const bl = data.backlinks || {};
|
|
100
|
+
|
|
101
|
+
for (const [target, sources] of Object.entries(bl)) {
|
|
102
|
+
if (normalize(target) === normPath) {
|
|
103
|
+
return [...sources].sort();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function traverseFrom(path, depth = 2, root = DEFAULT_ROOT) {
|
|
111
|
+
const normPath = normalize(path);
|
|
112
|
+
const graph = await readGraph(root);
|
|
113
|
+
|
|
114
|
+
// Build adjacency list from all edges (undirected traversal)
|
|
115
|
+
const adj = new Map();
|
|
116
|
+
for (const edge of graph.edges) {
|
|
117
|
+
const from = normalize(edge.from);
|
|
118
|
+
const to = normalize(edge.to);
|
|
119
|
+
if (!adj.has(from)) adj.set(from, new Set());
|
|
120
|
+
if (!adj.has(to)) adj.set(to, new Set());
|
|
121
|
+
adj.get(from).add(to);
|
|
122
|
+
adj.get(to).add(from);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// BFS
|
|
126
|
+
const visited = new Set([normPath]);
|
|
127
|
+
let frontier = [normPath];
|
|
128
|
+
|
|
129
|
+
for (let d = 0; d < depth && frontier.length > 0; d++) {
|
|
130
|
+
const nextFrontier = [];
|
|
131
|
+
for (const node of frontier) {
|
|
132
|
+
const neighbours = adj.get(node) || new Set();
|
|
133
|
+
for (const n of neighbours) {
|
|
134
|
+
if (!visited.has(n)) {
|
|
135
|
+
visited.add(n);
|
|
136
|
+
nextFrontier.push(n);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
frontier = nextFrontier;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
visited.delete(normPath);
|
|
144
|
+
return [...visited].sort();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function searchByDomain(domain, root = DEFAULT_ROOT) {
|
|
148
|
+
const graph = await readGraph(root);
|
|
149
|
+
return graph.nodes
|
|
150
|
+
.filter((n) => n.domain === domain)
|
|
151
|
+
.map((n) => n.id)
|
|
152
|
+
.sort();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ── CLI ─────────────────────────────────────────────────────────────
|
|
156
|
+
|
|
157
|
+
async function main(args) {
|
|
158
|
+
let root = DEFAULT_ROOT;
|
|
159
|
+
|
|
160
|
+
const filtered = [];
|
|
161
|
+
for (let i = 0; i < args.length; i++) {
|
|
162
|
+
if (args[i] === '--root') {
|
|
163
|
+
root = resolve(args[++i]);
|
|
164
|
+
} else {
|
|
165
|
+
filtered.push(args[i]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!filtered.length || filtered[0] === '--help' || filtered[0] === '-h') {
|
|
170
|
+
console.log(USAGE);
|
|
171
|
+
return 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const cmd = filtered[0];
|
|
175
|
+
|
|
176
|
+
if (cmd === 'backlinks') {
|
|
177
|
+
const target = filtered[1];
|
|
178
|
+
if (!target) {
|
|
179
|
+
console.error('Usage: query.mjs backlinks <path>');
|
|
180
|
+
return 1;
|
|
181
|
+
}
|
|
182
|
+
const results = await getBacklinks(target, root);
|
|
183
|
+
if (!results.length) {
|
|
184
|
+
console.log('No backlinks found.');
|
|
185
|
+
} else {
|
|
186
|
+
for (const r of results) console.log(r);
|
|
187
|
+
}
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (cmd === 'related') {
|
|
192
|
+
const target = filtered[1];
|
|
193
|
+
if (!target) {
|
|
194
|
+
console.error('Usage: query.mjs related <path>');
|
|
195
|
+
return 1;
|
|
196
|
+
}
|
|
197
|
+
const results = await findRelated(target, root);
|
|
198
|
+
if (!results.length) {
|
|
199
|
+
console.log('No related files found.');
|
|
200
|
+
} else {
|
|
201
|
+
for (const r of results) console.log(r);
|
|
202
|
+
}
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (cmd === 'traverse') {
|
|
207
|
+
const target = filtered[1];
|
|
208
|
+
if (!target) {
|
|
209
|
+
console.error('Usage: query.mjs traverse <path> [depth]');
|
|
210
|
+
return 1;
|
|
211
|
+
}
|
|
212
|
+
const depth = parseInt(filtered[2], 10) || 2;
|
|
213
|
+
const results = await traverseFrom(target, depth, root);
|
|
214
|
+
if (!results.length) {
|
|
215
|
+
console.log('No reachable nodes found.');
|
|
216
|
+
} else {
|
|
217
|
+
for (const r of results) console.log(r);
|
|
218
|
+
}
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (cmd === 'domain') {
|
|
223
|
+
const name = filtered[1];
|
|
224
|
+
if (!name) {
|
|
225
|
+
console.error('Usage: query.mjs domain <name>');
|
|
226
|
+
return 1;
|
|
227
|
+
}
|
|
228
|
+
const results = await searchByDomain(name, root);
|
|
229
|
+
if (!results.length) {
|
|
230
|
+
console.log('No files found in domain.');
|
|
231
|
+
} else {
|
|
232
|
+
for (const r of results) console.log(r);
|
|
233
|
+
}
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
console.error(`Unknown command: ${cmd}`);
|
|
238
|
+
console.error('Run `node query.mjs --help` for usage.');
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ISMAIN-AUDIT (bug-3 sweep): path.resolve() normalises path segments but
|
|
243
|
+
// does not dereference symlinks, so this had the same class of fragility
|
|
244
|
+
// as the endsWith idiom fixed elsewhere in the scheduler — an argv[1]
|
|
245
|
+
// reached via a symlinked path (pnpm .bin shim, workspace link) would not
|
|
246
|
+
// equal the realpath-resolved import.meta.url. This file is not currently
|
|
247
|
+
// registered as a package `bin` (only invoked directly via `node
|
|
248
|
+
// .../query.mjs` per its own usage docs), so it is not proven to fire in
|
|
249
|
+
// production, but is fixed defensively to match the robust pattern used
|
|
250
|
+
// across the repo.
|
|
251
|
+
function isDirectlyInvoked() {
|
|
252
|
+
if (!process.argv[1]) return false;
|
|
253
|
+
try {
|
|
254
|
+
return fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]));
|
|
255
|
+
} catch {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (isDirectlyInvoked()) {
|
|
261
|
+
const exitCode = await main(process.argv.slice(2));
|
|
262
|
+
process.exit(exitCode ?? 0);
|
|
263
|
+
}
|