@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,97 @@
|
|
|
1
|
+
// research mark <done|aborted> <sessionId> [--no-promote | --promote]
|
|
2
|
+
//
|
|
3
|
+
// Set a terminal status on a session: `done` (finalised) or `aborted` (abandoned,
|
|
4
|
+
// e.g. the workflow's >10%-unsourced guardrail). The only verb that mutates an
|
|
5
|
+
// existing session's status, and both transitions are one-way — a session already
|
|
6
|
+
// terminal (done/aborted) is refused (exit 2).
|
|
7
|
+
//
|
|
8
|
+
// The status write goes through the store chokepoint (store.updateManifestStatus),
|
|
9
|
+
// which reads → guards the terminal transition → validates → persists.
|
|
10
|
+
//
|
|
11
|
+
// On `mark done` for a NORMAL or DEEP session we then promote answer.md into the
|
|
12
|
+
// operator knowledge library (w-021). Promotion NEVER fails the mark: the status
|
|
13
|
+
// is already `done` on disk before we touch the library, and promotion skips (with
|
|
14
|
+
// a note where relevant) rather than throwing on expected conditions. Light mode
|
|
15
|
+
// is never promoted — `--promote` on light is a usage error (exit 1). `--no-promote`
|
|
16
|
+
// skips promotion on normal/deep with a one-line note. `mark aborted` never promotes.
|
|
17
|
+
import { parseArgs } from 'node:util';
|
|
18
|
+
import { getDefaultStore } from '../store/index.mjs';
|
|
19
|
+
import { decidePromotion, promoteSession, refreshHint } from '../promote.mjs';
|
|
20
|
+
|
|
21
|
+
const SUBVERBS = ['done', 'aborted'];
|
|
22
|
+
|
|
23
|
+
function usage(msg) {
|
|
24
|
+
return Object.assign(new Error(`usage: research mark <done|aborted> <sessionId> [--no-promote | --promote]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function markCommand(argv, { store, now = Date.now, stdout = process.stdout, promote = promoteSession, knowledgeDir } = {}) {
|
|
28
|
+
if (!store) store = await getDefaultStore();
|
|
29
|
+
let parsed;
|
|
30
|
+
try {
|
|
31
|
+
parsed = parseArgs({
|
|
32
|
+
args: argv,
|
|
33
|
+
options: {
|
|
34
|
+
'no-promote': { type: 'boolean' },
|
|
35
|
+
promote: { type: 'boolean' },
|
|
36
|
+
},
|
|
37
|
+
allowPositionals: true,
|
|
38
|
+
strict: true,
|
|
39
|
+
});
|
|
40
|
+
} catch (e) {
|
|
41
|
+
throw usage(e.message);
|
|
42
|
+
}
|
|
43
|
+
const [subverb, id, ...extra] = parsed.positionals;
|
|
44
|
+
const noPromote = parsed.values['no-promote'] === true;
|
|
45
|
+
const forcePromote = parsed.values.promote === true;
|
|
46
|
+
|
|
47
|
+
if (!subverb) throw usage('a sub-verb is required (one of "done" or "aborted")');
|
|
48
|
+
if (!SUBVERBS.includes(subverb)) throw usage(`unknown sub-verb "${subverb}" (one of "done" or "aborted")`);
|
|
49
|
+
if (!id) throw usage('a <sessionId> is required');
|
|
50
|
+
if (extra.length) throw usage('too many arguments');
|
|
51
|
+
if (noPromote && forcePromote) throw usage('--no-promote and --promote are mutually exclusive');
|
|
52
|
+
if (!store.isValidSessionId(id)) throw usage(`"${id}" is not a valid sessionId`);
|
|
53
|
+
|
|
54
|
+
// The promotion decision reads the session's mode; peek at the manifest BEFORE
|
|
55
|
+
// mutating so that a `--promote` on a light session errors out (exit 1) WITHOUT
|
|
56
|
+
// having already flipped the status. Missing/malformed session → exit 2 here,
|
|
57
|
+
// same as updateManifestStatus would have surfaced.
|
|
58
|
+
if (subverb === 'done') {
|
|
59
|
+
const current = await store.readManifest(id);
|
|
60
|
+
// Throws exit 1 for the light + --promote hard-rule violation. `status` is
|
|
61
|
+
// the post-transition status (done) since that is what we are about to set.
|
|
62
|
+
decidePromotion({ mode: current.mode, status: 'done', noPromote, promote: forcePromote });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const nowIso = new Date(now()).toISOString();
|
|
66
|
+
// The sub-verb IS the target terminal status. Missing session → exit 2 (not
|
|
67
|
+
// found); already terminal → exit 2 (refused, one-way transition). This is the
|
|
68
|
+
// idempotency backstop: `mark done` on an already-done session is refused here,
|
|
69
|
+
// so promotion can never double-write.
|
|
70
|
+
const updated = await store.updateManifestStatus(id, subverb, nowIso);
|
|
71
|
+
stdout.write(`marked ${id} ${subverb} (updatedAt ${updated.updatedAt})\n`);
|
|
72
|
+
|
|
73
|
+
if (subverb !== 'done') return 0;
|
|
74
|
+
|
|
75
|
+
const decision = decidePromotion({ mode: updated.mode, status: updated.status, noPromote, promote: forcePromote });
|
|
76
|
+
if (decision.action === 'skip-silent') return 0; // light → silent by design
|
|
77
|
+
if (decision.action === 'skip-note') {
|
|
78
|
+
stdout.write(` --no-promote set — skipped knowledge-library promotion\n`);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// action === 'promote' (normal/deep). Never fatal: report skips/errors as a
|
|
83
|
+
// note and still return success, since the session is already `done`.
|
|
84
|
+
try {
|
|
85
|
+
const result = await promote(id, { store, knowledgeDir });
|
|
86
|
+
if (result.status === 'promoted') {
|
|
87
|
+
stdout.write(` ${refreshHint(result.path)}\n`);
|
|
88
|
+
} else if (result.status === 'already-promoted') {
|
|
89
|
+
stdout.write(` already promoted to ${result.path} — no change\n`);
|
|
90
|
+
} else if (result.status === 'skipped-no-answer') {
|
|
91
|
+
stdout.write(` ${result.reason}\n`);
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
stdout.write(` promotion failed (non-fatal): ${e && e.message ? e.message : e}\n`);
|
|
95
|
+
}
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// research paths [--json]
|
|
2
|
+
//
|
|
3
|
+
// Emit the absolute paths the /research skill and the workflow scripts
|
|
4
|
+
// consume, resolved against the operator repo root and this package's install
|
|
5
|
+
// location:
|
|
6
|
+
//
|
|
7
|
+
// sessionsDir — where session dirs live (default: <repoRoot>/.cache/research/sessions)
|
|
8
|
+
// briefsDir — dispatch briefs the workflow feeds to searcher/extractor/…
|
|
9
|
+
// workflowsDir — the workflow scripts themselves (research-normal.js et al.)
|
|
10
|
+
// schemaDir — JSON schemas for manifest/plan/finding/sources/gates
|
|
11
|
+
// cli — the invocation prefix the workflow uses to run this CLI
|
|
12
|
+
// from a subagent (`pnpm exec research`)
|
|
13
|
+
//
|
|
14
|
+
// The /research skill calls this once at the top of a session and interpolates
|
|
15
|
+
// the values into the Workflow dispatch args, so nothing on the skill side has
|
|
16
|
+
// to know where the package is installed. `pa knowledge`-style JSON contract.
|
|
17
|
+
//
|
|
18
|
+
// Exit codes: 0 ok, 1 usage, 3 transport/IO (repo-root resolution failure surfaces
|
|
19
|
+
// with its own exitCode via getRepoRoot()).
|
|
20
|
+
import { parseArgs } from 'node:util';
|
|
21
|
+
import { join, resolve, dirname } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { defaultSessionsDir } from '../store/index.mjs';
|
|
24
|
+
|
|
25
|
+
function usage(msg) {
|
|
26
|
+
return Object.assign(new Error(`usage: research paths [--json]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The research package's own root — briefs/ and workflows/ ship inside it.
|
|
30
|
+
// commands/paths.mjs → ../ = src/research/. Resolved from import.meta.url so
|
|
31
|
+
// the answer is right whether the tool is running from the source tree, from
|
|
32
|
+
// dist/ under a published package, or from a symlinked pnpm workspace.
|
|
33
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
const PACKAGE_ROOT = resolve(__dirname, '..');
|
|
35
|
+
|
|
36
|
+
export async function resolvePaths() {
|
|
37
|
+
return {
|
|
38
|
+
sessionsDir: await defaultSessionsDir(),
|
|
39
|
+
briefsDir: join(PACKAGE_ROOT, 'briefs'),
|
|
40
|
+
workflowsDir: join(PACKAGE_ROOT, 'workflows'),
|
|
41
|
+
schemaDir: join(PACKAGE_ROOT, 'schema'),
|
|
42
|
+
cli: 'pnpm exec research',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function pathsCommand(argv, { stdout = process.stdout } = {}) {
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = parseArgs({
|
|
50
|
+
args: argv,
|
|
51
|
+
options: { json: { type: 'boolean' } },
|
|
52
|
+
allowPositionals: false,
|
|
53
|
+
strict: true,
|
|
54
|
+
});
|
|
55
|
+
} catch (e) {
|
|
56
|
+
throw usage(e.message);
|
|
57
|
+
}
|
|
58
|
+
const paths = await resolvePaths();
|
|
59
|
+
if (parsed.values.json) {
|
|
60
|
+
stdout.write(JSON.stringify(paths, null, 2) + '\n');
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
stdout.write(`sessionsDir: ${paths.sessionsDir}\n`);
|
|
64
|
+
stdout.write(`briefsDir: ${paths.briefsDir}\n`);
|
|
65
|
+
stdout.write(`workflowsDir: ${paths.workflowsDir}\n`);
|
|
66
|
+
stdout.write(`schemaDir: ${paths.schemaDir}\n`);
|
|
67
|
+
stdout.write(`cli: ${paths.cli}\n`);
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// research prune [--older-than <days>] [--status <status>] [--dry-run]
|
|
2
|
+
//
|
|
3
|
+
// Deletes sessions older than N days AND/OR matching a status (filters AND
|
|
4
|
+
// together). At least one filter is required — a bare `prune` is a usage error
|
|
5
|
+
// so a fat-fingered command can never wipe every session. --dry-run previews.
|
|
6
|
+
// An explicit filter that matches nothing exits 2 (operational).
|
|
7
|
+
import { parseArgs } from 'node:util';
|
|
8
|
+
import { getDefaultStore } from '../store/index.mjs';
|
|
9
|
+
import { STATUSES } from '../store/manifest.mjs';
|
|
10
|
+
import { table, truncate } from '../format.mjs';
|
|
11
|
+
|
|
12
|
+
function usage(msg) {
|
|
13
|
+
return Object.assign(new Error(`usage: research prune [--older-than <days>] [--status <${STATUSES.join('|')}>] [--dry-run] (at least one filter required)${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const DAY_MS = 86_400_000;
|
|
17
|
+
|
|
18
|
+
// PURE: choose which sessions to prune. `sessions` is the listSessions() shape
|
|
19
|
+
// (each { id, manifest, error }). A session matches only if it satisfies EVERY
|
|
20
|
+
// provided filter. Malformed sessions (no manifest) are never matched — we won't
|
|
21
|
+
// delete what we can't evaluate. `nowMs` is injected for testability.
|
|
22
|
+
export function selectPruneTargets(sessions, { olderThanDays, status, nowMs }) {
|
|
23
|
+
const cutoff = olderThanDays != null ? nowMs - olderThanDays * DAY_MS : null;
|
|
24
|
+
return sessions.filter((s) => {
|
|
25
|
+
if (!s.manifest) return false;
|
|
26
|
+
if (status != null && s.manifest.status !== status) return false;
|
|
27
|
+
if (cutoff != null) {
|
|
28
|
+
const created = Date.parse(s.manifest.createdAt);
|
|
29
|
+
if (Number.isNaN(created) || created >= cutoff) return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function pruneCommand(argv, { store, now = Date.now, stdout = process.stdout, stderr = process.stderr } = {}) {
|
|
36
|
+
if (!store) store = await getDefaultStore();
|
|
37
|
+
let parsed;
|
|
38
|
+
try {
|
|
39
|
+
parsed = parseArgs({
|
|
40
|
+
args: argv,
|
|
41
|
+
options: {
|
|
42
|
+
'older-than': { type: 'string' },
|
|
43
|
+
status: { type: 'string' },
|
|
44
|
+
'dry-run': { type: 'boolean' },
|
|
45
|
+
},
|
|
46
|
+
allowPositionals: false,
|
|
47
|
+
strict: true,
|
|
48
|
+
});
|
|
49
|
+
} catch (e) {
|
|
50
|
+
throw usage(e.message);
|
|
51
|
+
}
|
|
52
|
+
const v = parsed.values;
|
|
53
|
+
|
|
54
|
+
const hasAge = v['older-than'] != null;
|
|
55
|
+
const hasStatus = v.status != null;
|
|
56
|
+
if (!hasAge && !hasStatus) throw usage('provide --older-than and/or --status');
|
|
57
|
+
|
|
58
|
+
let olderThanDays;
|
|
59
|
+
if (hasAge) {
|
|
60
|
+
olderThanDays = Number(v['older-than']);
|
|
61
|
+
if (!Number.isInteger(olderThanDays) || olderThanDays < 0) throw usage('--older-than must be a non-negative integer (days)');
|
|
62
|
+
}
|
|
63
|
+
if (hasStatus && !STATUSES.includes(v.status)) throw usage(`--status must be one of ${STATUSES.join(' | ')}`);
|
|
64
|
+
|
|
65
|
+
const sessions = await store.listSessions();
|
|
66
|
+
const targets = selectPruneTargets(sessions, { olderThanDays, status: v.status, nowMs: now() });
|
|
67
|
+
|
|
68
|
+
if (targets.length === 0) {
|
|
69
|
+
// Explicit filter matched nothing → operational failure (exit 2).
|
|
70
|
+
stderr.write('prune: no sessions matched the filter\n');
|
|
71
|
+
return 2;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const rows = targets.map((s) => [s.id, s.manifest.mode, s.manifest.status, s.manifest.createdAt, truncate(s.manifest.question, 40)]);
|
|
75
|
+
|
|
76
|
+
if (v['dry-run']) {
|
|
77
|
+
stdout.write(`DRY RUN — ${targets.length} session(s) would be deleted:\n`);
|
|
78
|
+
stdout.write(table(['SESSION', 'MODE', 'STATUS', 'CREATED', 'QUESTION'], rows));
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const s of targets) await store.deleteSession(s.id);
|
|
83
|
+
stdout.write(`deleted ${targets.length} session(s):\n`);
|
|
84
|
+
stdout.write(table(['SESSION', 'MODE', 'STATUS', 'CREATED', 'QUESTION'], rows));
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// research run — create a session (dir + manifest + skeleton plan), validate
|
|
2
|
+
// inputs, print the plan, return. Does NOT orchestrate research (build-spec §3).
|
|
3
|
+
// --dry-run validates + prints without persisting; it is the ONLY branch that
|
|
4
|
+
// does not write.
|
|
5
|
+
import { parseArgs } from 'node:util';
|
|
6
|
+
import { getDefaultStore } from '../store/index.mjs';
|
|
7
|
+
import { MODES, GATE_POLICIES, OUTPUT_MODES } from '../store/manifest.mjs';
|
|
8
|
+
import { skeletonPlan } from '../store/plan.mjs';
|
|
9
|
+
import { emptySources } from '../store/sources.mjs';
|
|
10
|
+
import { emptyGates } from '../store/gates.mjs';
|
|
11
|
+
import { manifestLine, planBlock } from '../format.mjs';
|
|
12
|
+
|
|
13
|
+
// Mode-derived scope recorded in the manifest budget (build-spec §4). Not
|
|
14
|
+
// enforced by the CLI — it records what the run was scoped to.
|
|
15
|
+
export const MODE_BUDGETS = {
|
|
16
|
+
light: { maxSubQuestions: 0, maxDeepeningRounds: 0, wallClockMinutes: 2 },
|
|
17
|
+
normal: { maxSubQuestions: 4, maxDeepeningRounds: 1, wallClockMinutes: 10 },
|
|
18
|
+
deep: { maxSubQuestions: 12, maxDeepeningRounds: 3, wallClockMinutes: 45 },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function usage(msg) {
|
|
22
|
+
return Object.assign(new Error(`usage: research run --mode <light|normal|deep> --question "..." [--gate <operatorPresent|background|worker>] [--intent "..."] [--output <shortAnswer|article|structured>] [--dry-run]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Build a fresh manifest from validated inputs. Pure given a clock + id.
|
|
26
|
+
export function buildManifest({ sessionId, mode, question, intent, gatePolicy, outputMode, nowIso }) {
|
|
27
|
+
const m = {
|
|
28
|
+
sessionId,
|
|
29
|
+
mode,
|
|
30
|
+
question,
|
|
31
|
+
gatePolicy,
|
|
32
|
+
status: 'draft',
|
|
33
|
+
outputMode,
|
|
34
|
+
budget: { ...MODE_BUDGETS[mode] },
|
|
35
|
+
assumptions: [],
|
|
36
|
+
createdAt: nowIso,
|
|
37
|
+
updatedAt: nowIso,
|
|
38
|
+
};
|
|
39
|
+
if (intent) m.intent = intent;
|
|
40
|
+
return m;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function runCommand(argv, { store, now = Date.now, stdout = process.stdout } = {}) {
|
|
44
|
+
if (!store) store = await getDefaultStore();
|
|
45
|
+
let parsed;
|
|
46
|
+
try {
|
|
47
|
+
parsed = parseArgs({
|
|
48
|
+
args: argv,
|
|
49
|
+
options: {
|
|
50
|
+
mode: { type: 'string' },
|
|
51
|
+
question: { type: 'string' },
|
|
52
|
+
gate: { type: 'string' },
|
|
53
|
+
intent: { type: 'string' },
|
|
54
|
+
output: { type: 'string' },
|
|
55
|
+
'dry-run': { type: 'boolean' },
|
|
56
|
+
},
|
|
57
|
+
allowPositionals: false,
|
|
58
|
+
strict: true,
|
|
59
|
+
});
|
|
60
|
+
} catch (e) {
|
|
61
|
+
throw usage(e.message);
|
|
62
|
+
}
|
|
63
|
+
const v = parsed.values;
|
|
64
|
+
|
|
65
|
+
if (!v.mode) throw usage('--mode is required');
|
|
66
|
+
if (!MODES.includes(v.mode)) throw usage(`--mode must be one of ${MODES.join(' | ')}`);
|
|
67
|
+
if (!v.question || v.question.trim() === '') throw usage('--question is required and must be non-empty');
|
|
68
|
+
|
|
69
|
+
const gatePolicy = v.gate ?? 'worker';
|
|
70
|
+
if (!GATE_POLICIES.includes(gatePolicy)) throw usage(`--gate must be one of ${GATE_POLICIES.join(' | ')}`);
|
|
71
|
+
|
|
72
|
+
const outputMode = v.output ?? 'shortAnswer';
|
|
73
|
+
if (!OUTPUT_MODES.includes(outputMode)) throw usage(`--output must be one of ${OUTPUT_MODES.join(' | ')}`);
|
|
74
|
+
|
|
75
|
+
const nowIso = new Date(now()).toISOString();
|
|
76
|
+
const sessionId = store.newSessionId(now());
|
|
77
|
+
const manifest = buildManifest({ sessionId, mode: v.mode, question: v.question, intent: v.intent, gatePolicy, outputMode, nowIso });
|
|
78
|
+
const plan = skeletonPlan(v.mode);
|
|
79
|
+
|
|
80
|
+
if (v['dry-run']) {
|
|
81
|
+
stdout.write('DRY RUN — nothing persisted.\n\n');
|
|
82
|
+
stdout.write(manifestLine(manifest));
|
|
83
|
+
stdout.write('\n');
|
|
84
|
+
stdout.write(planBlock(plan));
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await store.createSession({ manifest, plan, sources: emptySources(), gates: emptyGates() });
|
|
89
|
+
stdout.write(`created ${sessionId}\n\n`);
|
|
90
|
+
stdout.write(manifestLine(manifest));
|
|
91
|
+
stdout.write('\n');
|
|
92
|
+
stdout.write(planBlock(plan));
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// research show <sessionId> — dump one session: manifest, plan, findings summary,
|
|
2
|
+
// gate summary, source count. --json emits the full assembled object.
|
|
3
|
+
import { parseArgs } from 'node:util';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { getDefaultStore } from '../store/index.mjs';
|
|
6
|
+
import { manifestLine, planBlock, findingsSummary, gatesSummary } from '../format.mjs';
|
|
7
|
+
|
|
8
|
+
function usage(msg) {
|
|
9
|
+
return Object.assign(new Error(`usage: research show <sessionId> [--json]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function showCommand(argv, { store, stdout = process.stdout } = {}) {
|
|
13
|
+
if (!store) store = await getDefaultStore();
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = parseArgs({ args: argv, options: { json: { type: 'boolean' } }, allowPositionals: true, strict: true });
|
|
17
|
+
} catch (e) {
|
|
18
|
+
throw usage(e.message);
|
|
19
|
+
}
|
|
20
|
+
const id = parsed.positionals[0];
|
|
21
|
+
if (parsed.positionals.length !== 1) throw usage('exactly one <sessionId> is required');
|
|
22
|
+
if (!store.isValidSessionId(id)) throw usage(`"${id}" is not a valid sessionId`);
|
|
23
|
+
|
|
24
|
+
const manifest = await store.readManifest(id); // exit 2 if not found / malformed
|
|
25
|
+
const plan = existsSync(store.paths(id).plan) ? await store.readPlan(id) : null;
|
|
26
|
+
const sources = await store.readSources(id);
|
|
27
|
+
const gates = await store.readGates(id);
|
|
28
|
+
const findings = await store.listFindings(id);
|
|
29
|
+
|
|
30
|
+
if (parsed.values.json) {
|
|
31
|
+
stdout.write(JSON.stringify({ manifest, plan, sources, gates, findings }, null, 2) + '\n');
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
stdout.write(manifestLine(manifest));
|
|
36
|
+
stdout.write('\n');
|
|
37
|
+
stdout.write(plan ? planBlock(plan) : 'plan: none\n');
|
|
38
|
+
stdout.write('\n');
|
|
39
|
+
stdout.write(findingsSummary(findings));
|
|
40
|
+
stdout.write(`sources: ${sources.items.length}\n`);
|
|
41
|
+
stdout.write(gatesSummary(gates));
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Operator-present gate flow
|
|
2
|
+
|
|
3
|
+
How Dave clears human gates **live** during a research run, and how the same
|
|
4
|
+
in-session presence sweeps the queue of gates that earlier `background`-posture runs
|
|
5
|
+
left behind. This is the runbook for the `operatorPresent` gate policy (build-spec
|
|
6
|
+
§6). It is a **flow doc, not a code path** — the Playwright-MCP integration in the
|
|
7
|
+
skill body is a later concern; here we describe what the operator and Dave actually do.
|
|
8
|
+
**Baz** is the operator (the human in the session); **Dave** is the operator's model; a
|
|
9
|
+
**gate** is any fetch blocked by a login wall, paywall, Cloudflare/Turnstile challenge,
|
|
10
|
+
or captcha.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. When to use `operatorPresent`
|
|
15
|
+
|
|
16
|
+
Reach for `--gate operatorPresent` when all three hold:
|
|
17
|
+
|
|
18
|
+
- **Baz is in-session with Dave** — a live, interactive run, not a cron/scheduled one.
|
|
19
|
+
- **The research will touch gated sources** — the answer depends on paywalled docs, a
|
|
20
|
+
logged-in dashboard, or a Cloudflare-fronted site that a headless fetch can't pass.
|
|
21
|
+
- **The answer is worth Baz's attention** — clearing a gate costs a few seconds of the
|
|
22
|
+
operator's time per gate; only spend it when getting the real source materially
|
|
23
|
+
improves the answer over dropping-with-caveat.
|
|
24
|
+
|
|
25
|
+
If Baz is not present, or the run is scheduled, use `background` (queue the gates) or
|
|
26
|
+
`worker` (the default for dispatched agents; park/resume is v2). A worker **never**
|
|
27
|
+
self-upgrades to headed browsing.
|
|
28
|
+
|
|
29
|
+
## 2. The mechanics
|
|
30
|
+
|
|
31
|
+
Dave invokes the run, declaring the posture:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
/research <question> --mode <light|normal> --gate operatorPresent
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
On a gate hit, Dave does **not** drop the source. Instead:
|
|
38
|
+
|
|
39
|
+
1. Dave escalates to Baz in plain language, naming the URL and the obstacle — e.g.
|
|
40
|
+
*"Cloudflare check on docs.example.com — can you clear it?"*
|
|
41
|
+
2. Baz acts in the **shared headed browser** (a real Playwright MCP session Dave
|
|
42
|
+
drives): Dave calls the Playwright MCP browser (in prose: `browser_navigate` to the
|
|
43
|
+
URL, then `browser_snapshot` so Baz sees the page; Baz solves the challenge or signs
|
|
44
|
+
in; Dave re-snapshots to confirm the content is now reachable).
|
|
45
|
+
3. Dave reads the now-ungated content and continues the fetch as normal — the source is
|
|
46
|
+
cited like any other.
|
|
47
|
+
|
|
48
|
+
**The MCP browser is shared parent state.** There is exactly **one** headed consumer at
|
|
49
|
+
a time, and it is Dave (the parent). Subagents — the `research-normal.js` workflow's
|
|
50
|
+
searchers — run headless and **never** touch it. That has a hard consequence:
|
|
51
|
+
|
|
52
|
+
> **Do not run a normal-mode workflow under `operatorPresent`.** The workflow's searcher
|
|
53
|
+
> subagents cannot attach to Dave's headed Playwright session, so they can't benefit from
|
|
54
|
+
> a live clearance. Operator-present runs are effectively **light mode** (Dave does the
|
|
55
|
+
> fetching inline, on the shared browser) or a single-worker fetch that Dave supervises.
|
|
56
|
+
> A normal-mode run that expects gated sources should use `background` and be swept later
|
|
57
|
+
> (§3).
|
|
58
|
+
|
|
59
|
+
## 3. Sweeping the queued `background` gates
|
|
60
|
+
|
|
61
|
+
`background`-posture runs don't block on gates: each searcher drops the source and the
|
|
62
|
+
workflow's Finalise phase persists the record via `research gates --append`, so the
|
|
63
|
+
gate lands in `sessions/<id>/gates.json` with `status: pending`. Those records
|
|
64
|
+
accumulate across runs. A later operator-present session drains them:
|
|
65
|
+
|
|
66
|
+
1. **See what's queued** — across all sessions, or one:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
research gates --list # every session's pending/retrying gates
|
|
70
|
+
research gates --list <id> # just one session
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
2. **Clear each gate Baz wants** — for a chosen row, Dave drives the shared Playwright
|
|
74
|
+
MCP browser to the `url` (in prose: `browser_navigate` + `browser_snapshot`), Baz
|
|
75
|
+
clears the challenge/login, and Dave captures the page. Because browser sessions
|
|
76
|
+
don't transfer between processes, **clearance produces an artifact, not a cleared
|
|
77
|
+
path**: Dave saves the fetched content to `sessions/<id>/gated/<hash>.md` so it can be
|
|
78
|
+
re-read exactly like a fetch.
|
|
79
|
+
|
|
80
|
+
3. **Mark the swept items** — flag the session's eligible gates for follow-up:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
research gates --retry <id> # marks pending/retrying items as `retrying`
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
In v1, `--retry` **only marks** — it does not re-run the pipeline. `retrying` means
|
|
87
|
+
*"queued for the operator to hand-run the fetch"*; Dave (or Baz) reads the saved
|
|
88
|
+
`gated/<hash>.md` artifact and folds it into the answer by hand. The automated
|
|
89
|
+
re-run of just the parked sub-questions is v2 (§4).
|
|
90
|
+
|
|
91
|
+
## 4. What v1 covers vs what v2 adds
|
|
92
|
+
|
|
93
|
+
**v1 (this and w-018):**
|
|
94
|
+
- `background`-posture gates queue automatically via `research gates --append` (workflow
|
|
95
|
+
Finalise phase).
|
|
96
|
+
- `operatorPresent` runs skip gates live: Dave escalates, Baz clears in the shared headed
|
|
97
|
+
Playwright browser, the fetch continues.
|
|
98
|
+
- `research gates --list` aggregates the queue; `research gates --retry` marks items for
|
|
99
|
+
operator follow-up; clearance content is saved to `sessions/<id>/gated/<hash>.md`.
|
|
100
|
+
|
|
101
|
+
**v2 (deferred):**
|
|
102
|
+
- Worker-posture **park → escalate → resume** automation: a dispatched worker parks the
|
|
103
|
+
gated sub-question, checkpoints `GATE: {...}` up its channel, continues its remaining
|
|
104
|
+
queue, and is resumed from the clearance artifact.
|
|
105
|
+
- A `research resume <sessionId>` verb that re-runs extract+verify for just the parked
|
|
106
|
+
sub-questions against `gated/<hash>.md`.
|
|
107
|
+
- `research gates --retry` triggering that automated re-run rather than only marking.
|
|
108
|
+
|
|
109
|
+
## 5. Anti-patterns
|
|
110
|
+
|
|
111
|
+
- **Do not try to defeat a gate from a worker.** Spec §6: a worker never self-upgrades to
|
|
112
|
+
headed browsing. Background workers drop-and-log; that is correct, not a failure.
|
|
113
|
+
- **Do not run headed Playwright from a subagent.** The MCP browser is shared parent
|
|
114
|
+
state with one headed consumer. Only Dave (the parent) drives it; searchers stay
|
|
115
|
+
headless.
|
|
116
|
+
- **Do not auto-approve gate clearances.** The entire point of `operatorPresent` is live
|
|
117
|
+
consent — Baz decides which gates to clear. Never script past a login/paywall on Baz's
|
|
118
|
+
behalf without the explicit ask.
|
|
119
|
+
- **Do not run `operatorPresent` for a normal-mode workflow.** Its searchers can't attach
|
|
120
|
+
to the shared browser (§2). Use `background` + a later sweep instead.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Pure presentation helpers. No I/O — every function returns a string. Commands
|
|
2
|
+
// write these to their injected out/err streams. Keeps rendering testable and
|
|
3
|
+
// keeps the exit-code/side-effect logic out of the formatting layer.
|
|
4
|
+
|
|
5
|
+
export function truncate(s, n) {
|
|
6
|
+
const one = String(s ?? '').replace(/\s+/g, ' ').trim();
|
|
7
|
+
return one.length > n ? one.slice(0, n - 1) + '…' : one;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// A compact fixed-width table. rows is an array of arrays of strings.
|
|
11
|
+
export function table(headers, rows) {
|
|
12
|
+
const all = [headers, ...rows];
|
|
13
|
+
const widths = headers.map((_, c) => Math.max(...all.map((r) => String(r[c] ?? '').length)));
|
|
14
|
+
const line = (r) => r.map((cell, c) => String(cell ?? '').padEnd(widths[c])).join(' ').trimEnd();
|
|
15
|
+
const out = [line(headers), widths.map((w) => '-'.repeat(w)).join(' ').trimEnd()];
|
|
16
|
+
for (const r of rows) out.push(line(r));
|
|
17
|
+
return out.join('\n') + '\n';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function manifestLine(m) {
|
|
21
|
+
return [
|
|
22
|
+
`session ${m.sessionId}`,
|
|
23
|
+
` mode: ${m.mode}`,
|
|
24
|
+
` status: ${m.status}`,
|
|
25
|
+
` gatePolicy: ${m.gatePolicy}`,
|
|
26
|
+
` outputMode: ${m.outputMode}`,
|
|
27
|
+
` question: ${m.question}`,
|
|
28
|
+
m.intent ? ` intent: ${m.intent}` : null,
|
|
29
|
+
` budget: subQ=${m.budget.maxSubQuestions} rounds=${m.budget.maxDeepeningRounds} wallMin=${m.budget.wallClockMinutes}`,
|
|
30
|
+
m.assumptions.length ? ` assumptions: ${m.assumptions.join('; ')}` : null,
|
|
31
|
+
` created: ${m.createdAt}`,
|
|
32
|
+
` updated: ${m.updatedAt}`,
|
|
33
|
+
].filter((x) => x != null).join('\n') + '\n';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function planBlock(p) {
|
|
37
|
+
const lines = [`plan: ${p.subQuestions.length} sub-question(s), deepeningRounds=${p.deepeningRounds}, verificationTier=${p.verificationTier}`];
|
|
38
|
+
for (const sq of p.subQuestions) {
|
|
39
|
+
const dep = sq.dependsOn.length ? ` (depends on ${sq.dependsOn.join(', ')})` : '';
|
|
40
|
+
lines.push(` [${sq.id}] ${sq.kind}${dep}: ${sq.text}`);
|
|
41
|
+
}
|
|
42
|
+
return lines.join('\n') + '\n';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function findingsSummary(findings) {
|
|
46
|
+
if (findings.length === 0) return 'findings: none yet\n';
|
|
47
|
+
const lines = [`findings: ${findings.length}`];
|
|
48
|
+
for (const f of findings) {
|
|
49
|
+
const votes = f.verificationVotes.length ? ` votes=${f.verificationVotes.map((v) => v.outcome).join('/')}` : '';
|
|
50
|
+
lines.push(` [${f.subQuestionId}] confidence=${f.confidence}${f.unsourced ? ' UNSOURCED' : ''}${votes}: ${truncate(f.summary, 60)}`);
|
|
51
|
+
}
|
|
52
|
+
return lines.join('\n') + '\n';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function gatesSummary(gates) {
|
|
56
|
+
const counts = { pending: 0, retrying: 0, resolved: 0, failed: 0 };
|
|
57
|
+
for (const g of gates.queue) counts[g.status]++;
|
|
58
|
+
return `gates: ${gates.queue.length} total (pending=${counts.pending}, retrying=${counts.retrying}, resolved=${counts.resolved}, failed=${counts.failed})\n`;
|
|
59
|
+
}
|