@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,174 @@
|
|
|
1
|
+
// slice — input loading.
|
|
2
|
+
//
|
|
3
|
+
// Reads the inputs the slice generator needs:
|
|
4
|
+
// - profile.md (required) — the operator's full profile (source of truth).
|
|
5
|
+
// - learned-rules.md (optional) — operational rules from corrections.
|
|
6
|
+
// - observations dir (optional) — a directory of recent observation .md files.
|
|
7
|
+
//
|
|
8
|
+
// Pure I/O + assembly; no spawning, no API calls. The assembled output is a
|
|
9
|
+
// single string with stable section headers that the prompt's {{INPUTS}}
|
|
10
|
+
// placeholder is replaced with.
|
|
11
|
+
//
|
|
12
|
+
// Observation filtering: we don't trust the caller to have already filtered
|
|
13
|
+
// to "recent". We accept an optional `recentDays` window and keep only files
|
|
14
|
+
// whose mtime is within that window. Files under `_archive/` (any case,
|
|
15
|
+
// any prefix) are skipped — those are post-distillation archives and are
|
|
16
|
+
// not recent signal.
|
|
17
|
+
|
|
18
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
19
|
+
import { basename, join } from 'node:path';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Load all slice inputs and assemble them into a single inputs string ready
|
|
23
|
+
* to be substituted into the prompt template's {{INPUTS}} placeholder.
|
|
24
|
+
*
|
|
25
|
+
* @param {object} opts
|
|
26
|
+
* @param {string} opts.profilePath Path to profile.md (required).
|
|
27
|
+
* @param {string} [opts.learnedRulesPath] Path to learned-rules.md (optional).
|
|
28
|
+
* @param {string} [opts.observationsDir] Path to a directory of observation .md files (optional).
|
|
29
|
+
* @param {number} [opts.recentDays=21] Window in days for filtering observations by mtime.
|
|
30
|
+
* @param {() => Date} [opts.now] Injectable clock for tests.
|
|
31
|
+
* @returns {Promise<{
|
|
32
|
+
* text: string,
|
|
33
|
+
* profileBytes: number,
|
|
34
|
+
* profileLines: number,
|
|
35
|
+
* learnedRulesBytes: number,
|
|
36
|
+
* observationsBytes: number,
|
|
37
|
+
* observationsCount: number,
|
|
38
|
+
* }>}
|
|
39
|
+
*/
|
|
40
|
+
export async function loadInputs({
|
|
41
|
+
profilePath,
|
|
42
|
+
learnedRulesPath,
|
|
43
|
+
observationsDir,
|
|
44
|
+
recentDays = 21,
|
|
45
|
+
now = () => new Date(),
|
|
46
|
+
} = {}) {
|
|
47
|
+
if (!profilePath) {
|
|
48
|
+
const err = new Error('loadInputs: profilePath is required');
|
|
49
|
+
err.sliceExitCode = 1;
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let profile;
|
|
54
|
+
try {
|
|
55
|
+
profile = await readFile(profilePath, 'utf8');
|
|
56
|
+
} catch (err) {
|
|
57
|
+
const e = new Error(`failed to read profile at ${profilePath}: ${err.message}`);
|
|
58
|
+
e.sliceExitCode = 2;
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
const profileBytes = Buffer.byteLength(profile, 'utf8');
|
|
62
|
+
const profileLines = profile.split('\n').length;
|
|
63
|
+
|
|
64
|
+
let learnedRules = null;
|
|
65
|
+
let learnedRulesBytes = 0;
|
|
66
|
+
if (learnedRulesPath) {
|
|
67
|
+
try {
|
|
68
|
+
learnedRules = await readFile(learnedRulesPath, 'utf8');
|
|
69
|
+
learnedRulesBytes = Buffer.byteLength(learnedRules, 'utf8');
|
|
70
|
+
} catch (err) {
|
|
71
|
+
const e = new Error(`failed to read learned-rules at ${learnedRulesPath}: ${err.message}`);
|
|
72
|
+
e.sliceExitCode = 2;
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let observationsText = null;
|
|
78
|
+
let observationsBytes = 0;
|
|
79
|
+
let observationsCount = 0;
|
|
80
|
+
if (observationsDir) {
|
|
81
|
+
const result = await loadRecentObservations({ dir: observationsDir, recentDays, now });
|
|
82
|
+
observationsText = result.text;
|
|
83
|
+
observationsBytes = result.bytes;
|
|
84
|
+
observationsCount = result.count;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Assemble.
|
|
88
|
+
const parts = [
|
|
89
|
+
'## INPUT 1 — OPERATOR PROFILE (authoritative, source of truth)',
|
|
90
|
+
'',
|
|
91
|
+
profile.trim(),
|
|
92
|
+
];
|
|
93
|
+
if (learnedRules) {
|
|
94
|
+
parts.push(
|
|
95
|
+
'',
|
|
96
|
+
'## INPUT 2 — LEARNED RULES (operational rules from corrections)',
|
|
97
|
+
'',
|
|
98
|
+
learnedRules.trim(),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
if (observationsText) {
|
|
102
|
+
parts.push(
|
|
103
|
+
'',
|
|
104
|
+
`## INPUT 3 — RECENT OBSERVATIONS (raw, last ${recentDays} days, synthesise — do not quote)`,
|
|
105
|
+
'',
|
|
106
|
+
observationsText.trim(),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
const text = parts.join('\n') + '\n';
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
text,
|
|
113
|
+
profileBytes,
|
|
114
|
+
profileLines,
|
|
115
|
+
learnedRulesBytes,
|
|
116
|
+
observationsBytes,
|
|
117
|
+
observationsCount,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Walk an observations directory, keep .md files modified within
|
|
123
|
+
* `recentDays`, exclude anything under an `_archive`/`_archived` subtree.
|
|
124
|
+
* Returns a concatenated string with one section per file, prefixed by
|
|
125
|
+
* the filename for traceability.
|
|
126
|
+
*/
|
|
127
|
+
export async function loadRecentObservations({ dir, recentDays = 21, now = () => new Date() }) {
|
|
128
|
+
let entries;
|
|
129
|
+
try {
|
|
130
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
131
|
+
} catch (err) {
|
|
132
|
+
if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
|
|
133
|
+
return { text: null, bytes: 0, count: 0 };
|
|
134
|
+
}
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const cutoffMs = now().getTime() - recentDays * 24 * 60 * 60 * 1000;
|
|
139
|
+
const files = [];
|
|
140
|
+
for (const e of entries) {
|
|
141
|
+
if (!e.isFile()) continue;
|
|
142
|
+
if (!e.name.endsWith('.md')) continue;
|
|
143
|
+
if (e.name.startsWith('_')) continue; // _archive.md and friends
|
|
144
|
+
const full = join(dir, e.name);
|
|
145
|
+
let s;
|
|
146
|
+
try {
|
|
147
|
+
s = await stat(full);
|
|
148
|
+
} catch {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (s.mtimeMs < cutoffMs) continue;
|
|
152
|
+
files.push({ path: full, name: e.name, mtime: s.mtimeMs });
|
|
153
|
+
}
|
|
154
|
+
// Newest first — for the prompt this helps recency-bias the synthesis.
|
|
155
|
+
files.sort((a, b) => b.mtime - a.mtime);
|
|
156
|
+
|
|
157
|
+
const sections = [];
|
|
158
|
+
let bytes = 0;
|
|
159
|
+
for (const f of files) {
|
|
160
|
+
let content;
|
|
161
|
+
try {
|
|
162
|
+
content = await readFile(f.path, 'utf8');
|
|
163
|
+
} catch {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const section = `### ${basename(f.name)}\n\n${content.trim()}\n`;
|
|
167
|
+
sections.push(section);
|
|
168
|
+
bytes += Buffer.byteLength(content, 'utf8');
|
|
169
|
+
}
|
|
170
|
+
if (sections.length === 0) {
|
|
171
|
+
return { text: null, bytes: 0, count: 0 };
|
|
172
|
+
}
|
|
173
|
+
return { text: sections.join('\n'), bytes, count: sections.length };
|
|
174
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// slice — prompt assembly.
|
|
2
|
+
//
|
|
3
|
+
// Loads a prompt template by name (e.g. "dave-boot" → `prompts/dave-boot.md`),
|
|
4
|
+
// substitutes the {{INPUTS}} placeholder with the assembled inputs string,
|
|
5
|
+
// and returns the final prompt text. Pure string + I/O — no Claude calls,
|
|
6
|
+
// no spawning.
|
|
7
|
+
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a slice prompt template path.
|
|
16
|
+
*
|
|
17
|
+
* - If `nameOrPath` looks like a path (contains a separator or `.md`), it is
|
|
18
|
+
* used as-is (resolved to absolute if relative).
|
|
19
|
+
* - Otherwise it is treated as a template name and resolved against the
|
|
20
|
+
* bundled `prompts/` directory.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} nameOrPath
|
|
23
|
+
* @returns {string} absolute path
|
|
24
|
+
*/
|
|
25
|
+
export function resolveTemplatePath(nameOrPath) {
|
|
26
|
+
if (!nameOrPath || typeof nameOrPath !== 'string') {
|
|
27
|
+
throw new Error('resolveTemplatePath: nameOrPath is required');
|
|
28
|
+
}
|
|
29
|
+
if (nameOrPath.endsWith('.md') || nameOrPath.includes('/') || nameOrPath.includes('\\')) {
|
|
30
|
+
return isAbsolute(nameOrPath) ? nameOrPath : resolve(process.cwd(), nameOrPath);
|
|
31
|
+
}
|
|
32
|
+
return resolve(__dirname, 'prompts', `${nameOrPath}.md`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Load a prompt template and substitute the {{INPUTS}} placeholder.
|
|
37
|
+
*
|
|
38
|
+
* @param {object} opts
|
|
39
|
+
* @param {string} opts.template Template name or path.
|
|
40
|
+
* @param {string} opts.inputs Inputs string to substitute.
|
|
41
|
+
* @returns {Promise<string>} Final prompt text.
|
|
42
|
+
*/
|
|
43
|
+
export async function buildSlicePrompt({ template, inputs } = {}) {
|
|
44
|
+
if (!template) throw new Error('buildSlicePrompt: template is required');
|
|
45
|
+
if (inputs === undefined || inputs === null) {
|
|
46
|
+
throw new Error('buildSlicePrompt: inputs is required');
|
|
47
|
+
}
|
|
48
|
+
const path = resolveTemplatePath(template);
|
|
49
|
+
let tpl;
|
|
50
|
+
try {
|
|
51
|
+
tpl = await readFile(path, 'utf8');
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const e = new Error(`failed to read prompt template at ${path}: ${err.message}`);
|
|
54
|
+
e.sliceExitCode = 2;
|
|
55
|
+
throw e;
|
|
56
|
+
}
|
|
57
|
+
if (!tpl.includes('{{INPUTS}}')) {
|
|
58
|
+
const e = new Error(`prompt template at ${path} is missing the {{INPUTS}} placeholder`);
|
|
59
|
+
e.sliceExitCode = 2;
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
62
|
+
return tpl.replace('{{INPUTS}}', inputs);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Argv for the `claude` CLI when running a slice generation.
|
|
67
|
+
*
|
|
68
|
+
* v0.1.5: the prompt is no longer passed as a positional CLI argument. On
|
|
69
|
+
* Linux execve() enforces a per-arg ARG_MAX (typically 128 KB on a single
|
|
70
|
+
* arg) — a slice prompt that includes observations routinely exceeds this
|
|
71
|
+
* and surfaces as `spawn E2BIG` (w-2026-05-18-016). We now pipe the prompt
|
|
72
|
+
* to claude via stdin; argv carries only flags. The runner's `spawn`
|
|
73
|
+
* supports `{ stdin }` already (see distill/runner.mjs), so the call-site
|
|
74
|
+
* change in run.mjs is local.
|
|
75
|
+
*
|
|
76
|
+
* The `prompt` parameter is accepted but ignored to keep callers that pass
|
|
77
|
+
* it (and existing tests) working. Callers MUST pass the prompt as
|
|
78
|
+
* `stdin` to runner.spawn — see run.mjs.
|
|
79
|
+
*
|
|
80
|
+
* @param {object} opts
|
|
81
|
+
* @param {string} opts.sessionName
|
|
82
|
+
* @param {string} [opts.prompt] No longer placed in argv. Kept for API
|
|
83
|
+
* back-compat; pass the prompt to spawn
|
|
84
|
+
* via `{ stdin: prompt }`.
|
|
85
|
+
* @returns {string[]}
|
|
86
|
+
*/
|
|
87
|
+
export function claudeArgs({ sessionName }) {
|
|
88
|
+
return [
|
|
89
|
+
'--print',
|
|
90
|
+
'--permission-mode', 'bypassPermissions',
|
|
91
|
+
'--no-session-persistence',
|
|
92
|
+
'--name', sessionName,
|
|
93
|
+
];
|
|
94
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
You are operating as a compression assistant. Your job is to produce a compact "boot slice" of the operator's profile — a short markdown document that loads into the PA's context at every session start, in place of the full profile.
|
|
2
|
+
|
|
3
|
+
The full profile is the source of truth. This slice is a fresh snapshot, regenerated periodically. Stale content in the slice is acceptable for ~24 hours.
|
|
4
|
+
|
|
5
|
+
## What the slice is for
|
|
6
|
+
|
|
7
|
+
When the PA boots, it needs to know — in roughly 1–2 KB of context — *who it is working for*. Not every preference, not every historical decision, not every technical opinion. Just enough that:
|
|
8
|
+
|
|
9
|
+
- It addresses the operator correctly (name, register, tone).
|
|
10
|
+
- It knows the operator's mission framing this year.
|
|
11
|
+
- It knows what's in flight right now (active projects, active relationships).
|
|
12
|
+
- It is aware of the tools and capabilities already built and available.
|
|
13
|
+
- It avoids the highest-cost mistakes (5–10 most load-bearing recent corrections / rules).
|
|
14
|
+
- It can read the rest of the profile or knowledge base when it needs detail.
|
|
15
|
+
|
|
16
|
+
This is a navigation card, not the territory. **Prefer pointers to canonical sources over baked-in content** that will go stale between regenerations.
|
|
17
|
+
|
|
18
|
+
## Inputs you have
|
|
19
|
+
|
|
20
|
+
You are given:
|
|
21
|
+
|
|
22
|
+
1. **The full operator profile** (`profile.md`) — the source of truth, ~18 KB.
|
|
23
|
+
2. **Recent corrections / load-bearing rules** (optional, `learned-rules.md`) — ~50 KB of operational rules accumulated from corrections.
|
|
24
|
+
3. **Recent observations** (optional) — a concatenated dump of raw observation files filed in the last 2–4 weeks, useful for "what's been on his mind lately" but not authoritative.
|
|
25
|
+
|
|
26
|
+
Treat the profile as authoritative. Treat learned-rules as second-tier authoritative (they ARE rules). Treat observations as raw signal — synthesise, do not quote.
|
|
27
|
+
|
|
28
|
+
## Output structure
|
|
29
|
+
|
|
30
|
+
Produce a markdown document with exactly these seven sections, in this order:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
# Operator Boot Slice -- <Operator Name>
|
|
34
|
+
|
|
35
|
+
_Generated <ISO timestamp>. Refreshed periodically. Source of truth: operator/profile/profile.md._
|
|
36
|
+
|
|
37
|
+
## Operator basics
|
|
38
|
+
<3-5 bullets: name, what they go by, communication register, tone preferences, sensitivities>
|
|
39
|
+
|
|
40
|
+
## Mission framing
|
|
41
|
+
<1-2 lines: the north-star / what we're building toward this year>
|
|
42
|
+
|
|
43
|
+
## Active projects
|
|
44
|
+
<3-6 bullets, one line each: project name -- one-line status>
|
|
45
|
+
|
|
46
|
+
## Active relationships
|
|
47
|
+
<2-4 bullets, one line each: who -- relationship context>
|
|
48
|
+
|
|
49
|
+
## Tools at your disposal
|
|
50
|
+
<2-3 lines: a one-line summary of the HQ-built operator-extension tools you have available (look for evidence of these in the inputs — names like wsd-ingest, dispatch, svc, monitoring, scheduled cron tasks, etc.), followed by a pointer line to the canonical list:>
|
|
51
|
+
For the canonical inventory of operator-built tools and scheduled tasks, read `operator/knowledge/systems/operator-tools.md`.
|
|
52
|
+
|
|
53
|
+
## Load-bearing rules right now
|
|
54
|
+
<5-10 bullets, one line each: most-cited or most-recent operational rules from learned-rules and the profile preferences section. Pick rules whose violation would be most costly>
|
|
55
|
+
|
|
56
|
+
## Live state — fetch on boot
|
|
57
|
+
For current project and work-item state, run: `pnpm exec desk overview`.
|
|
58
|
+
Do not bake state into this slice — it will be wrong by the time it is read.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The last section is a **fixed instruction**, not generated content. Reproduce it verbatim. The whole point is to send the PA to the live tool for any state question rather than relying on a frozen snapshot.
|
|
62
|
+
|
|
63
|
+
## Budget
|
|
64
|
+
|
|
65
|
+
**Soft target: under 2 KB total output.** Aim for ~1.2–1.8 KB. If you can't fit a section in the budget, prefer fewer items over shorter items — better to give 3 sharp project lines than 6 mushy ones. Over-budget is warned but not blocked; under-information is more costly.
|
|
66
|
+
|
|
67
|
+
## Style
|
|
68
|
+
|
|
69
|
+
- No emojis (the operator has a strict no-emoji rule for persisted artefacts).
|
|
70
|
+
- No em-dashes — use double-hyphens (`--`) instead.
|
|
71
|
+
- Use the operator's own vocabulary where you can pull it cleanly from the profile.
|
|
72
|
+
- Don't editorialise. State, don't sell.
|
|
73
|
+
- "Operator" not "user". "PA" or the PA's name, not "the assistant".
|
|
74
|
+
|
|
75
|
+
## What NOT to include
|
|
76
|
+
|
|
77
|
+
- Technical opinions (the full Technical Opinions section of profile.md).
|
|
78
|
+
- Historical decision patterns.
|
|
79
|
+
- Communication-style examples that aren't load-bearing.
|
|
80
|
+
- Anything the PA can look up at the moment it needs it (this is what the pointers are for).
|
|
81
|
+
- A baked snapshot of project state — the Live-state section's pointer covers that.
|
|
82
|
+
|
|
83
|
+
The test for "should this be in the slice": *if this is wrong or missing, will the PA make a costly mistake in its first 5 messages?* If yes, include it. If no, leave it out.
|
|
84
|
+
|
|
85
|
+
## Now produce the slice
|
|
86
|
+
|
|
87
|
+
The inputs follow below. Read them, then produce the slice. Output ONLY the slice markdown — no preamble, no postscript, no explanation. Your entire response is what gets written to disk.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
{{INPUTS}}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
// slice — orchestrator.
|
|
2
|
+
//
|
|
3
|
+
// Flow:
|
|
4
|
+
// 1. Load inputs (profile + optional learned-rules + optional observations).
|
|
5
|
+
// 2. Build the prompt (template + substituted inputs).
|
|
6
|
+
// 3. Invoke `claude --print` via the shared runner.
|
|
7
|
+
// 4. Validate the response (six required sections, size budget).
|
|
8
|
+
// 5. Write the slice to the configured output path.
|
|
9
|
+
//
|
|
10
|
+
// Output is plain markdown — no front-matter, no JSON envelope. Validation is
|
|
11
|
+
// soft on size (warn over budget, don't fail) and hard on structure (a
|
|
12
|
+
// response missing required headers is a generator failure, not a stale
|
|
13
|
+
// snapshot).
|
|
14
|
+
//
|
|
15
|
+
// Exit codes (§6 tooling standard):
|
|
16
|
+
// 0 ok | 1 usage | 2 prerequisite/operational | 3 claude transport failure
|
|
17
|
+
|
|
18
|
+
import { mkdir, writeFile, appendFile } from 'node:fs/promises';
|
|
19
|
+
import { dirname } from 'node:path';
|
|
20
|
+
|
|
21
|
+
import { loadInputs } from './inputs.mjs';
|
|
22
|
+
import { buildSlicePrompt, claudeArgs } from './prompt.mjs';
|
|
23
|
+
|
|
24
|
+
const REQUIRED_HEADERS = [
|
|
25
|
+
'## Operator basics',
|
|
26
|
+
'## Mission framing',
|
|
27
|
+
'## Active projects',
|
|
28
|
+
'## Active relationships',
|
|
29
|
+
'## Tools at your disposal',
|
|
30
|
+
'## Load-bearing rules right now',
|
|
31
|
+
'## Live state',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const SIZE_BUDGET_BYTES = 2048;
|
|
35
|
+
|
|
36
|
+
function opError(msg, code = 2) {
|
|
37
|
+
const err = new Error(msg);
|
|
38
|
+
err.sliceExitCode = code;
|
|
39
|
+
return err;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function log(line, { stderr = process.stderr } = {}) {
|
|
43
|
+
stderr.write(`[slice] ${line}\n`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Build a canonical audit record in stable field order. Required by the
|
|
48
|
+
* tasks-status consumer: ts (ISO-Z), status, exitCode. The status
|
|
49
|
+
* vocabulary is closed and matches the sibling tools (distill, wsd-ingest):
|
|
50
|
+
* ok — slice generated, validated, written.
|
|
51
|
+
* noop-dry-run — dry-run path; no claude call, no write.
|
|
52
|
+
* fail-usage — caller-side input error (missing arg, bad path).
|
|
53
|
+
* fail-validation — claude returned content missing required headers.
|
|
54
|
+
* fail-claude — claude exited non-zero (transport failure).
|
|
55
|
+
* fail-prereq — input loading failed (missing profile / observations / template).
|
|
56
|
+
* fail-write — writing the slice output file failed.
|
|
57
|
+
* fail-unexpected — any other thrown exception (defensive catch-all
|
|
58
|
+
* so cron failures never disappear silently).
|
|
59
|
+
*
|
|
60
|
+
* `reason` is omitted on `ok`. `outputBytes` is null on paths that didn't
|
|
61
|
+
* produce a file.
|
|
62
|
+
*/
|
|
63
|
+
function buildAuditRecord({ ts, status, exitCode, durationSec, dryRun, outputBytes, reason }) {
|
|
64
|
+
const rec = {
|
|
65
|
+
ts,
|
|
66
|
+
status,
|
|
67
|
+
exitCode,
|
|
68
|
+
durationSec,
|
|
69
|
+
dryRun,
|
|
70
|
+
outputBytes,
|
|
71
|
+
};
|
|
72
|
+
if (reason !== undefined) rec.reason = reason;
|
|
73
|
+
return rec;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Append one audit record to runs.jsonl. Best-effort: a failed audit write
|
|
78
|
+
* must NOT change the slice's exit code (a lost audit line is less bad than
|
|
79
|
+
* a poll being misclassified as a transport failure). Mirrors the policy
|
|
80
|
+
* used by `distill`'s writeAudit.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} runsLog
|
|
83
|
+
* @param {object} record
|
|
84
|
+
* @param {object} [opts]
|
|
85
|
+
* @param {object} [opts.stderr]
|
|
86
|
+
*/
|
|
87
|
+
export async function writeAudit(runsLog, record, { stderr = process.stderr } = {}) {
|
|
88
|
+
try {
|
|
89
|
+
await mkdir(dirname(runsLog), { recursive: true });
|
|
90
|
+
await appendFile(runsLog, JSON.stringify(record) + '\n');
|
|
91
|
+
} catch (e) {
|
|
92
|
+
log(`warning: failed to append audit record to ${runsLog}: ${e.message}`, { stderr });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** ISO-Z timestamp at second precision; parseable by `new Date()`. */
|
|
97
|
+
function tsNowIso(now = new Date()) {
|
|
98
|
+
return now.toISOString().replace(/\.\d+Z$/, 'Z');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Validate that the generated slice has the structural shape we asked for.
|
|
103
|
+
* Returns { ok: true } or { ok: false, missing: string[] }.
|
|
104
|
+
*/
|
|
105
|
+
export function validateSlice(text) {
|
|
106
|
+
const missing = REQUIRED_HEADERS.filter((h) => !text.includes(h));
|
|
107
|
+
if (missing.length > 0) return { ok: false, missing };
|
|
108
|
+
return { ok: true };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Compose a short session-name for the claude invocation. Filename-safe,
|
|
113
|
+
* UTC-compact, slice-prefixed.
|
|
114
|
+
*/
|
|
115
|
+
function sessionName(now) {
|
|
116
|
+
const d = now;
|
|
117
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
118
|
+
return (
|
|
119
|
+
`slice-${d.getUTCFullYear()}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}` +
|
|
120
|
+
`-${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Run slice generation end-to-end.
|
|
126
|
+
*
|
|
127
|
+
* @param {object} opts
|
|
128
|
+
* @param {string} opts.profilePath
|
|
129
|
+
* @param {string} [opts.learnedRulesPath]
|
|
130
|
+
* @param {string} [opts.observationsDir]
|
|
131
|
+
* @param {string} opts.template Template name (e.g. "dave-boot") or path.
|
|
132
|
+
* @param {string} opts.outputPath Where to write the slice.
|
|
133
|
+
* @param {boolean} [opts.dryRun=false] If true, build the prompt and report,
|
|
134
|
+
* but skip the claude call and file write.
|
|
135
|
+
* @param {object} opts.runner Shared runner (spawn/now/ts/tsIso).
|
|
136
|
+
* @param {object} [opts.stderr] Capture stream for tests.
|
|
137
|
+
* @returns {Promise<number>} Exit code.
|
|
138
|
+
*/
|
|
139
|
+
export async function runSlice({
|
|
140
|
+
profilePath,
|
|
141
|
+
learnedRulesPath,
|
|
142
|
+
observationsDir,
|
|
143
|
+
template,
|
|
144
|
+
outputPath,
|
|
145
|
+
runsLog,
|
|
146
|
+
dryRun = false,
|
|
147
|
+
runner,
|
|
148
|
+
stderr = process.stderr,
|
|
149
|
+
} = {}) {
|
|
150
|
+
if (!runner) throw new Error('runSlice: runner is required');
|
|
151
|
+
|
|
152
|
+
// Capture invocation start FIRST so every exit path — including the
|
|
153
|
+
// early-validation throws below — emits a duration that reflects the
|
|
154
|
+
// whole pass, not just the claude call.
|
|
155
|
+
const startedAtMs = Date.now();
|
|
156
|
+
const overallDurationSec = () => Math.round((Date.now() - startedAtMs) / 1000);
|
|
157
|
+
|
|
158
|
+
// Audit helper. Only writes if --runs-log was passed; otherwise a no-op
|
|
159
|
+
// so unscheduled invocations (humans regenerating a slice by hand) don't
|
|
160
|
+
// accidentally pollute a freshness-monitor file.
|
|
161
|
+
//
|
|
162
|
+
// Best-effort: never throws — `writeAudit` swallows fs errors and the
|
|
163
|
+
// helper itself catches anything else (e.g. a runner.now bug). A lost
|
|
164
|
+
// audit line is less bad than masking the real exit code.
|
|
165
|
+
const emitAudit = async ({ status, exitCode, outputBytes = null, reason }) => {
|
|
166
|
+
if (!runsLog) return;
|
|
167
|
+
try {
|
|
168
|
+
await writeAudit(
|
|
169
|
+
runsLog,
|
|
170
|
+
buildAuditRecord({
|
|
171
|
+
ts: tsNowIso(runner.now ? runner.now() : new Date()),
|
|
172
|
+
status,
|
|
173
|
+
exitCode,
|
|
174
|
+
durationSec: overallDurationSec(),
|
|
175
|
+
dryRun,
|
|
176
|
+
outputBytes,
|
|
177
|
+
reason,
|
|
178
|
+
}),
|
|
179
|
+
{ stderr },
|
|
180
|
+
);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
log(`warning: emitAudit failed: ${e.message || e}`, { stderr });
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Defensive outer try/catch. Every cron-class tool must record one
|
|
187
|
+
// audit line per invocation (canonical contract). Without this catch,
|
|
188
|
+
// an exception in loadInputs (missing profile path), buildSlicePrompt
|
|
189
|
+
// (template not found), writeFile (permission denied), or the early
|
|
190
|
+
// arg-validation `opError`s below would propagate silently — leaving
|
|
191
|
+
// a runs.jsonl monitor seeing "no record" instead of a fail-status.
|
|
192
|
+
try {
|
|
193
|
+
// Early arg validation — separated from the !runner check above so we
|
|
194
|
+
// get an audit line even for misconfigured cron invocations.
|
|
195
|
+
if (!profilePath) throw opError('profilePath is required', 1);
|
|
196
|
+
if (!template) throw opError('template is required', 1);
|
|
197
|
+
if (!outputPath) throw opError('outputPath is required', 1);
|
|
198
|
+
|
|
199
|
+
// Step 1 — load inputs.
|
|
200
|
+
let inputsResult;
|
|
201
|
+
try {
|
|
202
|
+
inputsResult = await loadInputs({
|
|
203
|
+
profilePath,
|
|
204
|
+
learnedRulesPath,
|
|
205
|
+
observationsDir,
|
|
206
|
+
now: runner.now,
|
|
207
|
+
});
|
|
208
|
+
} catch (e) {
|
|
209
|
+
// Wrap so the outer catch can classify this as `fail-prereq` rather
|
|
210
|
+
// than the catch-all `fail-unexpected`. Preserve the original
|
|
211
|
+
// message so operators can diagnose without digging through
|
|
212
|
+
// stderr.
|
|
213
|
+
const wrapped = opError(`loadInputs: ${e.message || e}`, 2);
|
|
214
|
+
wrapped.sliceFailStatus = 'fail-prereq';
|
|
215
|
+
throw wrapped;
|
|
216
|
+
}
|
|
217
|
+
log(
|
|
218
|
+
`inputs: profile=${inputsResult.profileBytes}B (${inputsResult.profileLines} lines)` +
|
|
219
|
+
(learnedRulesPath ? `, learned-rules=${inputsResult.learnedRulesBytes}B` : '') +
|
|
220
|
+
(observationsDir
|
|
221
|
+
? `, observations=${inputsResult.observationsCount} files / ${inputsResult.observationsBytes}B`
|
|
222
|
+
: ''),
|
|
223
|
+
{ stderr },
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// Step 2 — build prompt.
|
|
227
|
+
let prompt;
|
|
228
|
+
try {
|
|
229
|
+
prompt = await buildSlicePrompt({ template, inputs: inputsResult.text });
|
|
230
|
+
} catch (e) {
|
|
231
|
+
const wrapped = opError(`buildSlicePrompt: ${e.message || e}`, 2);
|
|
232
|
+
wrapped.sliceFailStatus = 'fail-prereq';
|
|
233
|
+
throw wrapped;
|
|
234
|
+
}
|
|
235
|
+
log(`prompt assembled: ${Buffer.byteLength(prompt, 'utf8')}B`, { stderr });
|
|
236
|
+
|
|
237
|
+
if (dryRun) {
|
|
238
|
+
log('DRY RUN — would invoke:', { stderr });
|
|
239
|
+
log(` template: ${template}`, { stderr });
|
|
240
|
+
log(` output: ${outputPath}`, { stderr });
|
|
241
|
+
log(` session name: ${sessionName(runner.now())}`, { stderr });
|
|
242
|
+
log(' command: claude --print --permission-mode bypassPermissions \\', { stderr });
|
|
243
|
+
log(' --no-session-persistence --name <session> <prompt>', { stderr });
|
|
244
|
+
await emitAudit({ status: 'noop-dry-run', exitCode: 0 });
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Step 3 — invoke claude.
|
|
249
|
+
//
|
|
250
|
+
// v0.1.5: prompt piped via stdin (not argv). Slice prompts that include
|
|
251
|
+
// observations routinely exceed Linux's per-arg ARG_MAX limit (~128 KB);
|
|
252
|
+
// the legacy positional-arg shape surfaced as `spawn E2BIG` on Linux
|
|
253
|
+
// even when the prompt was a moderate 148 KB. Piping via stdin removes
|
|
254
|
+
// the limit entirely — the kernel's pipe buffer is the only ceiling and
|
|
255
|
+
// it streams.
|
|
256
|
+
const argv = claudeArgs({ sessionName: sessionName(runner.now()) });
|
|
257
|
+
log('invoking claude…', { stderr });
|
|
258
|
+
const start = Date.now();
|
|
259
|
+
const result = await runner.spawn('claude', argv, { stdin: prompt });
|
|
260
|
+
const durationSec = Math.round((Date.now() - start) / 1000);
|
|
261
|
+
|
|
262
|
+
if (result.code !== 0) {
|
|
263
|
+
log(`claude exited ${result.code} (${durationSec}s)`, { stderr });
|
|
264
|
+
if (result.stderr) log(`stderr: ${result.stderr.trim().slice(0, 500)}`, { stderr });
|
|
265
|
+
await emitAudit({
|
|
266
|
+
status: 'fail-claude',
|
|
267
|
+
exitCode: 3,
|
|
268
|
+
reason: `claude exited ${result.code}`,
|
|
269
|
+
});
|
|
270
|
+
return 3;
|
|
271
|
+
}
|
|
272
|
+
const sliceText = (result.stdout || '').trim() + '\n';
|
|
273
|
+
log(`claude ok (${durationSec}s) — produced ${Buffer.byteLength(sliceText, 'utf8')}B`, { stderr });
|
|
274
|
+
|
|
275
|
+
// Step 4 — validate.
|
|
276
|
+
const v = validateSlice(sliceText);
|
|
277
|
+
if (!v.ok) {
|
|
278
|
+
log(`generated slice missing required headers: ${v.missing.join(', ')}`, { stderr });
|
|
279
|
+
await emitAudit({
|
|
280
|
+
status: 'fail-validation',
|
|
281
|
+
exitCode: 2,
|
|
282
|
+
reason: `missing required headers: ${v.missing.join(', ')}`,
|
|
283
|
+
});
|
|
284
|
+
return 2;
|
|
285
|
+
}
|
|
286
|
+
const bytes = Buffer.byteLength(sliceText, 'utf8');
|
|
287
|
+
if (bytes > SIZE_BUDGET_BYTES) {
|
|
288
|
+
log(
|
|
289
|
+
`WARN: slice is ${bytes}B, exceeds soft budget of ${SIZE_BUDGET_BYTES}B — writing anyway`,
|
|
290
|
+
{ stderr },
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Step 5 — write.
|
|
295
|
+
try {
|
|
296
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
297
|
+
await writeFile(outputPath, sliceText, 'utf8');
|
|
298
|
+
} catch (e) {
|
|
299
|
+
const wrapped = opError(`writeFile ${outputPath}: ${e.message || e}`, 2);
|
|
300
|
+
wrapped.sliceFailStatus = 'fail-write';
|
|
301
|
+
throw wrapped;
|
|
302
|
+
}
|
|
303
|
+
log(`wrote slice to ${outputPath} (${bytes}B)`, { stderr });
|
|
304
|
+
|
|
305
|
+
await emitAudit({ status: 'ok', exitCode: 0, outputBytes: bytes });
|
|
306
|
+
return 0;
|
|
307
|
+
} catch (err) {
|
|
308
|
+
// Defensive catch-all. Emit an audit line, then re-throw so the CLI
|
|
309
|
+
// gets the same exit-code translation it already does (via main's
|
|
310
|
+
// try/catch on sliceExitCode). Without this, an unexpected throw in
|
|
311
|
+
// loadInputs / buildSlicePrompt / writeFile / etc. would produce a
|
|
312
|
+
// silent failure: cron logs it, but runs.jsonl has no record and
|
|
313
|
+
// the freshness monitor can't tell the difference between "tool
|
|
314
|
+
// exploded" and "tool was never invoked".
|
|
315
|
+
const exitCode = err?.sliceExitCode ?? 2;
|
|
316
|
+
// Status priority:
|
|
317
|
+
// 1. Specific `sliceFailStatus` set by a wrap-throw (fail-prereq,
|
|
318
|
+
// fail-write).
|
|
319
|
+
// 2. `fail-usage` for exitCode 1 (caller-side: missing args).
|
|
320
|
+
// 3. `fail-unexpected` for everything else (defensive catch-all).
|
|
321
|
+
let status;
|
|
322
|
+
if (err?.sliceFailStatus) status = err.sliceFailStatus;
|
|
323
|
+
else if (exitCode === 1) status = 'fail-usage';
|
|
324
|
+
else status = 'fail-unexpected';
|
|
325
|
+
await emitAudit({
|
|
326
|
+
status,
|
|
327
|
+
exitCode,
|
|
328
|
+
reason: err?.message || String(err),
|
|
329
|
+
});
|
|
330
|
+
throw err;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export { REQUIRED_HEADERS, SIZE_BUDGET_BYTES };
|