@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,124 @@
|
|
|
1
|
+
# Brief — synthesizer (deep-research, mode `normal`)
|
|
2
|
+
|
|
3
|
+
You are a **synthesizer** in the `research-normal.js` pipeline. One synthesizer owns
|
|
4
|
+
**one sub-question**: merge its verified claims into a single finding, **write the
|
|
5
|
+
finding file to disk**, and return a receipt. You are the stage that turns verified
|
|
6
|
+
claims into a durable, schema-valid `findings/sq-<id>.json`.
|
|
7
|
+
|
|
8
|
+
The dispatching workflow supplies concrete values for every `{{placeholder}}` below.
|
|
9
|
+
|
|
10
|
+
## 1. Goal
|
|
11
|
+
|
|
12
|
+
For sub-question **`{{subQuestionId}}`** — *"{{subQuestionText}}"* — write
|
|
13
|
+
`{{sessionDir}}/findings/{{findingFilename}}` conforming exactly to the finding schema,
|
|
14
|
+
containing: a 1–4 sentence `summary` answering the sub-question, the surviving quotes,
|
|
15
|
+
the source ids used, an honest `confidence`, the verification votes on central claims,
|
|
16
|
+
and the `unsourced` flag. Merge semantic duplicates. Be transparent about refuted
|
|
17
|
+
claims.
|
|
18
|
+
|
|
19
|
+
## 2. Trace
|
|
20
|
+
|
|
21
|
+
- Parent run: session `{{sessionId}}`, output mode `{{outputMode}}`.
|
|
22
|
+
- Inputs handed to you by the workflow:
|
|
23
|
+
- **Verified central claims** (survived 3-vote verify, <2 refutes), each with its
|
|
24
|
+
quote, sourceId, and the three vote outcomes: {{verifiedClaims}}
|
|
25
|
+
- **Supporting/incidental claims** (reported, not verified): {{supportingClaims}}
|
|
26
|
+
- **Refuted central claims** (≥2 refutes — do NOT assert these; disclose them):
|
|
27
|
+
{{refutedClaims}}
|
|
28
|
+
- Your finding file is validated by the store: the workflow round-trips
|
|
29
|
+
`research show {{sessionId}} --json` and treats a non-zero exit as your write being
|
|
30
|
+
rejected. **`subQuestionId` inside the file MUST equal `{{subQuestionId}}` AND match
|
|
31
|
+
the filename stem `{{findingFilename}}`** — the store keys findings by filename, so a
|
|
32
|
+
mismatch is a consistency bug you must not ship.
|
|
33
|
+
|
|
34
|
+
## 3. Context — confidence & transparency
|
|
35
|
+
|
|
36
|
+
- **confidence** (`low | medium | high`), your honest read:
|
|
37
|
+
- `high` — central claims confirmed by the panel and grounded in `primary` sources
|
|
38
|
+
that agree.
|
|
39
|
+
- `medium` — mostly confirmed but thinner sourcing, some `secondary`-only support,
|
|
40
|
+
or minor unresolved tension.
|
|
41
|
+
- `low` — sparse/gated sources, unresolved contradictions, or several central claims
|
|
42
|
+
refuted.
|
|
43
|
+
- **Refuted-claim transparency is mandatory.** Do not silently drop refuted central
|
|
44
|
+
claims — name them in the `summary` (e.g. "A common claim that X was tested and did
|
|
45
|
+
not hold: …") so the reader sees what was checked and rejected.
|
|
46
|
+
- **Merge duplicates**: collapse claims that say the same thing; keep the strongest
|
|
47
|
+
quote/source.
|
|
48
|
+
- `unsourced` is `true` iff any assertion in your `summary` lacks a supporting quote in
|
|
49
|
+
`quotes[]`. Aim for `false` — every summary sentence should trace to a quote.
|
|
50
|
+
|
|
51
|
+
## 4. Tools & sources
|
|
52
|
+
|
|
53
|
+
- `Read` to inspect the inputs and the schema at
|
|
54
|
+
`{{schemaDir}}/finding.schema.json` if you need it.
|
|
55
|
+
- `Write` to create the finding file.
|
|
56
|
+
- `Bash` to round-trip: `{{cli}} show {{sessionId}} --json` —
|
|
57
|
+
exit 0 means every finding on disk (including yours) validates.
|
|
58
|
+
|
|
59
|
+
## 5. Boundaries
|
|
60
|
+
|
|
61
|
+
- One finding file, for `{{subQuestionId}}` only. Do not write `sources.json`,
|
|
62
|
+
`manifest.json`, the session answer, or any sibling's finding — the workflow's
|
|
63
|
+
finalise stage owns those.
|
|
64
|
+
- Do not invent quotes or source ids: every `quotes[].sourceId` and every id in
|
|
65
|
+
`sources[]` must come from the claims you were handed.
|
|
66
|
+
- Do not mark the session done — the finalise stage does that after all findings land.
|
|
67
|
+
|
|
68
|
+
## 6. Output format
|
|
69
|
+
|
|
70
|
+
### The file you write — `findings/{{findingFilename}}` (finding schema)
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"subQuestionId": "{{subQuestionId}}",
|
|
75
|
+
"summary": "1–4 sentences answering the sub-question, incl. a refuted-claim note if any.",
|
|
76
|
+
"quotes": [
|
|
77
|
+
{ "text": "verbatim quote", "sourceId": "s1-1", "importance": "central" }
|
|
78
|
+
],
|
|
79
|
+
"sources": ["s1-1", "s1-2"],
|
|
80
|
+
"confidence": "high",
|
|
81
|
+
"verificationVotes": [
|
|
82
|
+
{ "outcome": "confirmed", "lens": "contradiction-search", "note": "re: claim c-1 — no contradicting source found" }
|
|
83
|
+
],
|
|
84
|
+
"unsourced": false
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `quotes[].importance` ∈ `central | supporting | incidental` (optional per field but
|
|
89
|
+
include it). `confidence` ∈ `low | medium | high`.
|
|
90
|
+
- `verificationVotes[].outcome` ∈ `confirmed | refuted | unverified-infra`; `lens` and
|
|
91
|
+
`note` are optional but use `note` to name which central claim each vote concerns
|
|
92
|
+
(the schema has no per-claim vote linkage, so the note carries it).
|
|
93
|
+
- **No extra top-level fields** — the validator rejects unknown keys.
|
|
94
|
+
|
|
95
|
+
### Your structured return to the workflow (the receipt)
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"subQuestionId": "{{subQuestionId}}",
|
|
100
|
+
"written": true,
|
|
101
|
+
"path": "findings/{{findingFilename}}",
|
|
102
|
+
"confidence": "high",
|
|
103
|
+
"claimCount": 5,
|
|
104
|
+
"centralConfirmed": 3,
|
|
105
|
+
"centralRefuted": 1,
|
|
106
|
+
"unsourcedCount": 0,
|
|
107
|
+
"refutedTransparency": "one line naming any refuted central claims, or 'none'"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 7. Done when
|
|
112
|
+
|
|
113
|
+
- `findings/{{findingFilename}}` exists, its `subQuestionId` equals `{{subQuestionId}}`
|
|
114
|
+
and the filename stem, and `research show {{sessionId}} --json` exits 0 (your file
|
|
115
|
+
and every sibling's validate). Your receipt reports the real counts.
|
|
116
|
+
|
|
117
|
+
## 8. Escalation
|
|
118
|
+
|
|
119
|
+
- **The store rejects your file** (`show --json` exits 2 with a named error) → read the
|
|
120
|
+
error, fix the offending field, rewrite, re-run `show`. Never return `written: true`
|
|
121
|
+
while the round-trip is red.
|
|
122
|
+
- **Schema and a coherent answer genuinely cannot agree** → return `written: false`
|
|
123
|
+
with `refutedTransparency` explaining the conflict; the workflow escalates rather
|
|
124
|
+
than shipping a broken finding.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Brief — verifier (deep-research, mode `normal`)
|
|
2
|
+
|
|
3
|
+
You are a **verifier** in the `research-normal.js` pipeline. You cast **one adversarial
|
|
4
|
+
vote** on **one claim**. Three independent verifiers vote on each central claim; the
|
|
5
|
+
workflow tallies. Your job is to *try to break the claim*, not to confirm it.
|
|
6
|
+
|
|
7
|
+
The dispatching workflow supplies concrete values for every `{{placeholder}}` below.
|
|
8
|
+
|
|
9
|
+
## 1. Goal
|
|
10
|
+
|
|
11
|
+
Decide whether this claim survives an honest attempt to refute it:
|
|
12
|
+
|
|
13
|
+
- Claim: **"{{claimText}}"**
|
|
14
|
+
- Supporting quote (from the extractor): *"{{quote}}"*
|
|
15
|
+
- Cited source: {{sourceUrl}}
|
|
16
|
+
- In service of sub-question: *"{{subQuestionText}}"*
|
|
17
|
+
- Your assigned lens (if any): **{{lens}}**
|
|
18
|
+
|
|
19
|
+
Return one of three outcomes: `confirmed`, `refuted`, `unverified-infra`.
|
|
20
|
+
|
|
21
|
+
## 2. Trace
|
|
22
|
+
|
|
23
|
+
- Parent run: session `{{sessionId}}`. You are one of a 3-vote panel on this claim.
|
|
24
|
+
- Downstream rule the workflow applies to the panel: **≥ 2 `refuted` → the claim is
|
|
25
|
+
dropped** from the finding and reported as refuted. `unverified-infra` votes do
|
|
26
|
+
**not** count toward refutation — they record that verification could not run, not
|
|
27
|
+
that the claim is false.
|
|
28
|
+
|
|
29
|
+
## 3. Context — the adversarial posture
|
|
30
|
+
|
|
31
|
+
- **Default to `refuted` when uncertain.** The burden is on the claim to survive, not
|
|
32
|
+
on you to disprove it beyond doubt. A claim you cannot corroborate from an
|
|
33
|
+
independent angle is not "probably fine" — it is `refuted`.
|
|
34
|
+
- Vote `confirmed` only when an **independent** check agrees: the quote genuinely
|
|
35
|
+
supports the claim AND (where checkable) a second source, the primary source itself,
|
|
36
|
+
or first-principles reasoning agrees. Do not confirm on the strength of the single
|
|
37
|
+
cited source alone if the claim is checkable elsewhere.
|
|
38
|
+
- Vote `refuted` when: the quote does not actually support the claim (quote–claim
|
|
39
|
+
mismatch is a top failure mode — read it literally); an independent source
|
|
40
|
+
contradicts it; the claim is stale (superseded version/date); or it overreaches
|
|
41
|
+
beyond what any source supports.
|
|
42
|
+
- Lens focus (if `{{lens}}` is set): `quote-support` = does the quote prove the claim;
|
|
43
|
+
`contradiction-search` = actively search for a source that disagrees;
|
|
44
|
+
`recency-source-fit` = is it current and is the source the right kind of authority.
|
|
45
|
+
With no lens, apply all three.
|
|
46
|
+
|
|
47
|
+
## 4. Tools & sources
|
|
48
|
+
|
|
49
|
+
- `WebSearch` + `WebFetch` to seek contradiction and corroboration. Keep it lean —
|
|
50
|
+
a few targeted calls, not a re-research. You are testing one claim, not rebuilding
|
|
51
|
+
the sub-question.
|
|
52
|
+
|
|
53
|
+
## 5. Boundaries
|
|
54
|
+
|
|
55
|
+
- One claim, one vote. Do not re-extract, do not evaluate sibling claims, do not write
|
|
56
|
+
files.
|
|
57
|
+
- Do not soften a genuine refutation into `unverified-infra` to be polite —
|
|
58
|
+
`unverified-infra` is **only** for infrastructure failure (rate limits, everything
|
|
59
|
+
you fetched timed out / errored), never for "I found it doubtful."
|
|
60
|
+
- Conversely, do not report a real infra failure as `refuted` — that would falsely
|
|
61
|
+
sink a possibly-true claim.
|
|
62
|
+
|
|
63
|
+
## 6. Output format — structured return (enforced by the workflow's schema)
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"outcome": "confirmed",
|
|
68
|
+
"note": "one line: what you checked and why it lands here (cite the contradicting/corroborating source if any)"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `outcome` ∈ `confirmed | refuted | unverified-infra` (exact spelling; these are the
|
|
73
|
+
finding schema's vote outcomes).
|
|
74
|
+
- `note` is mandatory and must name the evidence — a bare outcome is not auditable.
|
|
75
|
+
|
|
76
|
+
## 7. Done when
|
|
77
|
+
|
|
78
|
+
- You have one `outcome` backed by a one-line, evidence-citing `note`, reached under
|
|
79
|
+
the adversarial default (uncertain ⇒ refuted).
|
|
80
|
+
|
|
81
|
+
## 8. Escalation
|
|
82
|
+
|
|
83
|
+
- **All your fetches failed (rate limit / network)** → `unverified-infra` with a note
|
|
84
|
+
naming the failure. Do not guess an outcome from the claim's plausibility.
|
|
85
|
+
- You never block or hand back — a vote is always due; when truly unable to check and
|
|
86
|
+
it is not an infra failure, the adversarial default (`refuted`) applies.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// research — deep-research session store CLI.
|
|
2
|
+
//
|
|
3
|
+
// The ONLY module that owns exit codes. Commands return a number or throw an
|
|
4
|
+
// Error carrying `.exitCode`; this wrapper translates:
|
|
5
|
+
// 0 — ok
|
|
6
|
+
// 1 — usage error (bad args, unknown verb, bad enum, missing sessionId)
|
|
7
|
+
// 2 — operational (session not found, malformed session dir, explicit prune matched nothing)
|
|
8
|
+
// 3 — transport/IO (disk read/write failure)
|
|
9
|
+
//
|
|
10
|
+
// Shape: `main(argv)` returns the exit code as a number (async). The bin shim
|
|
11
|
+
// converts to `process.exit`; `pa research <verb>` in `pa/cli.mjs` awaits the
|
|
12
|
+
// number so `pa` can surface the same code. Same pattern as `pa/knowledge/cli.mjs`.
|
|
13
|
+
|
|
14
|
+
import { realpathSync } from 'node:fs';
|
|
15
|
+
import { resolve } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
|
|
18
|
+
const HELP = `research — deep-research session store
|
|
19
|
+
|
|
20
|
+
Creates, validates, inspects and prunes research sessions under
|
|
21
|
+
<repoRoot>/.cache/research/sessions/<sessionId>/. Owns the schemas every
|
|
22
|
+
research workflow reads. Zero runtime dependencies.
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
research run --mode <light|normal|deep> --question "..." [--gate <policy>]
|
|
26
|
+
[--intent "..."] [--output <mode>] [--dry-run]
|
|
27
|
+
Create a session (dir + manifest + skeleton plan), validate inputs, print
|
|
28
|
+
the plan, and return. Does NOT orchestrate research. --dry-run validates and
|
|
29
|
+
prints without persisting. Gate policy: operatorPresent | background | worker.
|
|
30
|
+
Output mode: shortAnswer | article | structured (default shortAnswer).
|
|
31
|
+
|
|
32
|
+
research list [--status <status>] [--all] [--json]
|
|
33
|
+
List sessions, newest first. Default: 20 most recent. --all lists every one.
|
|
34
|
+
|
|
35
|
+
research show <sessionId> [--json]
|
|
36
|
+
Dump one session: manifest, findings summary, gate summary.
|
|
37
|
+
|
|
38
|
+
research gates --list [<sessionId>] | --retry <sessionId> | --append <sessionId>
|
|
39
|
+
--list aggregates the gate queue across all sessions (or one if given).
|
|
40
|
+
--retry marks eligible (pending/retrying) gates as retrying and prints them.
|
|
41
|
+
--append reads gate records (JSON array on stdin, or --record '<json>' for a
|
|
42
|
+
single one) and appends them to the session's gates.json with fresh g-N ids.
|
|
43
|
+
|
|
44
|
+
research prune [--older-than <days>] [--status <status>] [--dry-run]
|
|
45
|
+
Delete sessions older than N days and/or matching a status. At least one
|
|
46
|
+
filter is required. --dry-run prints what would be deleted without deleting.
|
|
47
|
+
|
|
48
|
+
research mark <done|aborted> <sessionId> [--no-promote | --promote]
|
|
49
|
+
Set a terminal status on a session: done (finalised) or aborted (abandoned).
|
|
50
|
+
Bumps updatedAt. Both transitions are one-way — a session already done or
|
|
51
|
+
aborted is refused (exit 2). The one verb that mutates a session's status.
|
|
52
|
+
On mark done, a normal/deep session's answer.md is promoted into the
|
|
53
|
+
operator knowledge library (operator/knowledge/research/); light is never
|
|
54
|
+
promoted (--promote on light is a usage error). --no-promote skips promotion
|
|
55
|
+
on normal/deep with a note. Aborted sessions are never promoted.
|
|
56
|
+
|
|
57
|
+
research paths [--json]
|
|
58
|
+
Emit the resolved absolute paths the /research skill and workflow scripts
|
|
59
|
+
consume: sessionsDir, briefsDir, workflowsDir, cli. Text default; --json
|
|
60
|
+
for machine input. Uses the same repo-root resolver as pa knowledge / pa
|
|
61
|
+
work: \$DAVE_REPO_ROOT / \$PA_REPO_ROOT, else walk upward for a .git entry.
|
|
62
|
+
|
|
63
|
+
research --help | -h This message.
|
|
64
|
+
|
|
65
|
+
Exit codes: 0 ok, 1 usage error, 2 operational failure, 3 transport/IO failure.
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
export async function main(argv) {
|
|
69
|
+
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
70
|
+
process.stdout.write(HELP);
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const verb = argv[0];
|
|
75
|
+
const rest = argv.slice(1);
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
switch (verb) {
|
|
79
|
+
case 'run': {
|
|
80
|
+
const { runCommand } = await import('./commands/run.mjs');
|
|
81
|
+
return (await runCommand(rest)) ?? 0;
|
|
82
|
+
}
|
|
83
|
+
case 'list': {
|
|
84
|
+
const { listCommand } = await import('./commands/list.mjs');
|
|
85
|
+
return (await listCommand(rest)) ?? 0;
|
|
86
|
+
}
|
|
87
|
+
case 'show': {
|
|
88
|
+
const { showCommand } = await import('./commands/show.mjs');
|
|
89
|
+
return (await showCommand(rest)) ?? 0;
|
|
90
|
+
}
|
|
91
|
+
case 'gates': {
|
|
92
|
+
const { gatesCommand } = await import('./commands/gates.mjs');
|
|
93
|
+
return (await gatesCommand(rest)) ?? 0;
|
|
94
|
+
}
|
|
95
|
+
case 'prune': {
|
|
96
|
+
const { pruneCommand } = await import('./commands/prune.mjs');
|
|
97
|
+
return (await pruneCommand(rest)) ?? 0;
|
|
98
|
+
}
|
|
99
|
+
case 'mark': {
|
|
100
|
+
const { markCommand } = await import('./commands/mark.mjs');
|
|
101
|
+
return (await markCommand(rest)) ?? 0;
|
|
102
|
+
}
|
|
103
|
+
case 'paths': {
|
|
104
|
+
const { pathsCommand } = await import('./commands/paths.mjs');
|
|
105
|
+
return (await pathsCommand(rest)) ?? 0;
|
|
106
|
+
}
|
|
107
|
+
default:
|
|
108
|
+
process.stderr.write(`unknown command: ${verb}\n\n`);
|
|
109
|
+
process.stderr.write(HELP);
|
|
110
|
+
return 1;
|
|
111
|
+
}
|
|
112
|
+
} catch (err) {
|
|
113
|
+
// parseArgs strict-mode errors and our own usage errors both surface here.
|
|
114
|
+
const exitCode = err && err.exitCode != null ? err.exitCode : 1;
|
|
115
|
+
process.stderr.write(`${err && err.message ? err.message : err}\n`);
|
|
116
|
+
return exitCode;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Allow `node src/research/cli.mjs ...` in addition to the bin shim.
|
|
121
|
+
//
|
|
122
|
+
// ISMAIN-AUDIT (bug-3 sweep): the previous strict `file://${argv[1]}`
|
|
123
|
+
// equality has the same fragility as the endsWith idiom fixed elsewhere —
|
|
124
|
+
// no realpath resolution on argv[1], so a symlinked invocation path (e.g.
|
|
125
|
+
// via a pnpm .bin shim) would silently fail to match import.meta.url
|
|
126
|
+
// (which Node always resolves to the real path). Not proven to fire in
|
|
127
|
+
// production today (the shipped `bin/research` imports and calls main()
|
|
128
|
+
// directly, bypassing this branch entirely) but fixed defensively to match
|
|
129
|
+
// the robust realpath-on-both-sides pattern used across the repo.
|
|
130
|
+
function isDirectlyInvoked() {
|
|
131
|
+
if (!process.argv[1]) return false;
|
|
132
|
+
try {
|
|
133
|
+
return fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]));
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (isDirectlyInvoked()) {
|
|
140
|
+
main(process.argv.slice(2)).then((code) => process.exit(code));
|
|
141
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// research gates --list [<sessionId>] | --retry <sessionId> | --append <sessionId>
|
|
2
|
+
//
|
|
3
|
+
// --list aggregates the gate queue across all sessions (or one, if given).
|
|
4
|
+
// --retry marks eligible (pending/retrying) gates as `retrying` and prints them.
|
|
5
|
+
// Actual re-execution is workflow-side (w-018+); this only marks + prints.
|
|
6
|
+
// --append reads gate records (JSON array on stdin, or --record '<json>' for a single
|
|
7
|
+
// one) and appends them to the session's gates.json with fresh g-N ids. The
|
|
8
|
+
// caller supplies the semantic fields ({url,gateType,whatIsNeeded,subQuestionId?});
|
|
9
|
+
// the verb assigns the id, sets blockedAt from the clock, defaults status:pending.
|
|
10
|
+
// The write goes through the store chokepoint (store.writeGates → validateGates).
|
|
11
|
+
import { parseArgs } from 'node:util';
|
|
12
|
+
import { getDefaultStore } from '../store/index.mjs';
|
|
13
|
+
import { markEligibleForRetry, GATE_STATUSES } from '../store/gates.mjs';
|
|
14
|
+
import { isObject } from '../store/validate.mjs';
|
|
15
|
+
import { table, truncate } from '../format.mjs';
|
|
16
|
+
|
|
17
|
+
function usage(msg) {
|
|
18
|
+
return Object.assign(new Error(`usage: research gates --list [<sessionId>] | --retry <sessionId> | --append <sessionId> [--record '<json>'] [--json]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
19
|
+
}
|
|
20
|
+
function notFound(msg) {
|
|
21
|
+
return Object.assign(new Error(msg), { exitCode: 2 });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Read all of a readable stream to a utf8 string. Injected in tests.
|
|
25
|
+
async function readAllStdin(stream = process.stdin) {
|
|
26
|
+
const chunks = [];
|
|
27
|
+
for await (const chunk of stream) chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
28
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Collect every gate across sessions (or one session) into flat rows carrying
|
|
32
|
+
// their sessionId. Pure over the store's reads.
|
|
33
|
+
async function collectGates(store, onlyId) {
|
|
34
|
+
const ids = onlyId
|
|
35
|
+
? [onlyId]
|
|
36
|
+
: (await store.listSessions()).filter((s) => s.manifest).map((s) => s.id);
|
|
37
|
+
const rows = [];
|
|
38
|
+
for (const id of ids) {
|
|
39
|
+
const gates = await store.readGates(id);
|
|
40
|
+
for (const g of gates.queue) rows.push({ sessionId: id, ...g });
|
|
41
|
+
}
|
|
42
|
+
return rows;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Parse a caller-supplied record/records blob. Bad JSON is USER input → exit 1
|
|
46
|
+
// (not the store validator's exit 2). Returns a normalised array.
|
|
47
|
+
function parseRecords(text, where) {
|
|
48
|
+
let raw;
|
|
49
|
+
try {
|
|
50
|
+
raw = JSON.parse(text);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
throw usage(`invalid JSON on ${where}: ${e.message}`);
|
|
53
|
+
}
|
|
54
|
+
return Array.isArray(raw) ? raw : [raw];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Turn one caller record into a full gate item. Validates input fields (exit 1 on a
|
|
58
|
+
// bad one) and stamps the verb-owned fields (id, blockedAt, default status).
|
|
59
|
+
function buildGateItem(r, id, nowIso, i) {
|
|
60
|
+
const at = `record[${i}]`;
|
|
61
|
+
if (!isObject(r)) throw usage(`${at} must be a JSON object`);
|
|
62
|
+
const KNOWN = new Set(['url', 'gateType', 'whatIsNeeded', 'subQuestionId', 'status']);
|
|
63
|
+
for (const k of Object.keys(r)) {
|
|
64
|
+
if (!KNOWN.has(k)) throw usage(`${at} has unexpected field "${k}" (allowed: url, gateType, whatIsNeeded, subQuestionId, status)`);
|
|
65
|
+
}
|
|
66
|
+
const reqStr = (k) => {
|
|
67
|
+
if (typeof r[k] !== 'string' || r[k].length === 0) throw usage(`${at}.${k} must be a non-empty string`);
|
|
68
|
+
return r[k];
|
|
69
|
+
};
|
|
70
|
+
const item = {
|
|
71
|
+
id,
|
|
72
|
+
url: reqStr('url'),
|
|
73
|
+
gateType: reqStr('gateType'),
|
|
74
|
+
whatIsNeeded: reqStr('whatIsNeeded'),
|
|
75
|
+
status: 'pending',
|
|
76
|
+
blockedAt: nowIso,
|
|
77
|
+
};
|
|
78
|
+
if (r.subQuestionId != null) {
|
|
79
|
+
if (typeof r.subQuestionId !== 'string' || r.subQuestionId.length === 0) throw usage(`${at}.subQuestionId must be a non-empty string if present`);
|
|
80
|
+
item.subQuestionId = r.subQuestionId;
|
|
81
|
+
}
|
|
82
|
+
if (r.status != null) {
|
|
83
|
+
if (!GATE_STATUSES.includes(r.status)) throw usage(`${at}.status must be one of ${GATE_STATUSES.join(' | ')} (got ${JSON.stringify(r.status)})`);
|
|
84
|
+
item.status = r.status;
|
|
85
|
+
}
|
|
86
|
+
return item;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function gatesCommand(argv, { store, stdout = process.stdout, now = Date.now, readStdin = readAllStdin } = {}) {
|
|
90
|
+
if (!store) store = await getDefaultStore();
|
|
91
|
+
let parsed;
|
|
92
|
+
try {
|
|
93
|
+
parsed = parseArgs({
|
|
94
|
+
args: argv,
|
|
95
|
+
options: {
|
|
96
|
+
list: { type: 'boolean' },
|
|
97
|
+
retry: { type: 'string' },
|
|
98
|
+
append: { type: 'boolean' },
|
|
99
|
+
record: { type: 'string' },
|
|
100
|
+
json: { type: 'boolean' },
|
|
101
|
+
},
|
|
102
|
+
allowPositionals: true,
|
|
103
|
+
strict: true,
|
|
104
|
+
});
|
|
105
|
+
} catch (e) {
|
|
106
|
+
throw usage(e.message);
|
|
107
|
+
}
|
|
108
|
+
const v = parsed.values;
|
|
109
|
+
const modes = [v.list && 'list', v.retry != null && 'retry', v.append && 'append'].filter(Boolean);
|
|
110
|
+
if (modes.length !== 1) throw usage('exactly one of --list, --retry <sessionId>, or --append <sessionId> is required');
|
|
111
|
+
if (v.record != null && !v.append) throw usage('--record is only valid with --append');
|
|
112
|
+
|
|
113
|
+
if (v.list) {
|
|
114
|
+
const onlyId = parsed.positionals[0];
|
|
115
|
+
if (parsed.positionals.length > 1) throw usage('--list takes at most one <sessionId>');
|
|
116
|
+
if (onlyId != null) {
|
|
117
|
+
if (!store.isValidSessionId(onlyId)) throw usage(`"${onlyId}" is not a valid sessionId`);
|
|
118
|
+
if (!store.exists(onlyId)) throw notFound(`session ${onlyId} not found`);
|
|
119
|
+
}
|
|
120
|
+
const rows = await collectGates(store, onlyId);
|
|
121
|
+
if (v.json) { stdout.write(JSON.stringify(rows, null, 2) + '\n'); return 0; }
|
|
122
|
+
if (rows.length === 0) { stdout.write('no gates\n'); return 0; }
|
|
123
|
+
stdout.write(table(
|
|
124
|
+
['SESSION', 'GATE', 'STATUS', 'TYPE', 'URL', 'NEEDED'],
|
|
125
|
+
rows.map((r) => [r.sessionId, r.id, r.status, r.gateType, truncate(r.url, 40), truncate(r.whatIsNeeded, 40)]),
|
|
126
|
+
));
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (v.append) {
|
|
131
|
+
const id = parsed.positionals[0];
|
|
132
|
+
if (!id) throw usage('--append requires a <sessionId>');
|
|
133
|
+
if (parsed.positionals.length > 1) throw usage('--append takes exactly one <sessionId>');
|
|
134
|
+
if (!store.isValidSessionId(id)) throw usage(`"${id}" is not a valid sessionId`);
|
|
135
|
+
if (!store.exists(id)) throw notFound(`session ${id} not found`);
|
|
136
|
+
|
|
137
|
+
const text = v.record != null ? v.record : await readStdin();
|
|
138
|
+
const records = parseRecords(text, v.record != null ? '--record' : 'stdin');
|
|
139
|
+
if (records.length === 0) throw notFound('no gate records supplied');
|
|
140
|
+
|
|
141
|
+
const existing = await store.readGates(id);
|
|
142
|
+
let maxN = 0;
|
|
143
|
+
for (const it of existing.queue) {
|
|
144
|
+
const m = /^g-(\d+)$/.exec(it.id);
|
|
145
|
+
if (m) maxN = Math.max(maxN, Number(m[1]));
|
|
146
|
+
}
|
|
147
|
+
const nowIso = new Date(now()).toISOString();
|
|
148
|
+
const newItems = records.map((r, i) => buildGateItem(r, `g-${maxN + i + 1}`, nowIso, i));
|
|
149
|
+
const next = { ...existing, queue: [...existing.queue, ...newItems] };
|
|
150
|
+
await store.writeGates(id, next); // chokepoint: validates the whole file before persist
|
|
151
|
+
|
|
152
|
+
if (v.json) { stdout.write(JSON.stringify(newItems, null, 2) + '\n'); return 0; }
|
|
153
|
+
stdout.write(`appended ${newItems.length} gate(s) to ${id}: ${newItems.map((it) => it.id).join(', ')}\n`);
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// --retry <sessionId>
|
|
158
|
+
const id = v.retry;
|
|
159
|
+
if (!store.isValidSessionId(id)) throw usage(`"${id}" is not a valid sessionId`);
|
|
160
|
+
if (!store.exists(id)) throw notFound(`session ${id} not found`);
|
|
161
|
+
|
|
162
|
+
const gates = await store.readGates(id);
|
|
163
|
+
const { gates: next, marked } = markEligibleForRetry(gates);
|
|
164
|
+
if (marked.length === 0) {
|
|
165
|
+
stdout.write('no eligible gates to retry\n');
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
await store.writeGates(id, next);
|
|
169
|
+
if (v.json) { stdout.write(JSON.stringify(marked, null, 2) + '\n'); return 0; }
|
|
170
|
+
stdout.write(`marked ${marked.length} gate(s) as retrying in ${id}:\n`);
|
|
171
|
+
stdout.write(table(
|
|
172
|
+
['GATE', 'TYPE', 'URL', 'NEEDED'],
|
|
173
|
+
marked.map((r) => [r.id, r.gateType, truncate(r.url, 40), truncate(r.whatIsNeeded, 40)]),
|
|
174
|
+
));
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// research list — list sessions, newest first (sessionId sorts by creation time).
|
|
2
|
+
// Default: 20 most recent. --all: every session. --status: filter. --json: machine output.
|
|
3
|
+
import { parseArgs } from 'node:util';
|
|
4
|
+
import { getDefaultStore } from '../store/index.mjs';
|
|
5
|
+
import { STATUSES } from '../store/manifest.mjs';
|
|
6
|
+
import { table, truncate } from '../format.mjs';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_LIMIT = 20;
|
|
9
|
+
|
|
10
|
+
function usage(msg) {
|
|
11
|
+
return Object.assign(new Error(`usage: research list [--status <${STATUSES.join('|')}>] [--all] [--json]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function listCommand(argv, { store, stdout = process.stdout } = {}) {
|
|
15
|
+
if (!store) store = await getDefaultStore();
|
|
16
|
+
let parsed;
|
|
17
|
+
try {
|
|
18
|
+
parsed = parseArgs({
|
|
19
|
+
args: argv,
|
|
20
|
+
options: {
|
|
21
|
+
status: { type: 'string' },
|
|
22
|
+
all: { type: 'boolean' },
|
|
23
|
+
json: { type: 'boolean' },
|
|
24
|
+
},
|
|
25
|
+
allowPositionals: false,
|
|
26
|
+
strict: true,
|
|
27
|
+
});
|
|
28
|
+
} catch (e) {
|
|
29
|
+
throw usage(e.message);
|
|
30
|
+
}
|
|
31
|
+
const v = parsed.values;
|
|
32
|
+
if (v.status != null && !STATUSES.includes(v.status)) throw usage(`--status must be one of ${STATUSES.join(' | ')}`);
|
|
33
|
+
|
|
34
|
+
let sessions = await store.listSessions();
|
|
35
|
+
if (v.status != null) sessions = sessions.filter((s) => s.manifest && s.manifest.status === v.status);
|
|
36
|
+
const limited = v.all ? sessions : sessions.slice(0, DEFAULT_LIMIT);
|
|
37
|
+
|
|
38
|
+
if (v.json) {
|
|
39
|
+
stdout.write(JSON.stringify(limited.map((s) => (s.manifest ? s.manifest : { sessionId: s.id, error: s.error })), null, 2) + '\n');
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (limited.length === 0) {
|
|
44
|
+
stdout.write('no sessions\n');
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const rows = limited.map((s) => s.manifest
|
|
49
|
+
? [s.id, s.manifest.mode, s.manifest.status, s.manifest.createdAt, truncate(s.manifest.question, 50)]
|
|
50
|
+
: [s.id, '?', 'MALFORMED', '?', truncate(s.error, 50)]);
|
|
51
|
+
stdout.write(table(['SESSION', 'MODE', 'STATUS', 'CREATED', 'QUESTION'], rows));
|
|
52
|
+
if (!v.all && sessions.length > limited.length) {
|
|
53
|
+
stdout.write(`\n… ${sessions.length - limited.length} more (use --all)\n`);
|
|
54
|
+
}
|
|
55
|
+
return 0;
|
|
56
|
+
}
|