@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,175 @@
|
|
|
1
|
+
# Google Search Console (`pa gsc`)
|
|
2
|
+
|
|
3
|
+
`pa gsc` automates Google Search Console onboarding and analytics across any
|
|
4
|
+
domain whose DNS lives on Cloudflare in an account the operator controls.
|
|
5
|
+
|
|
6
|
+
## Status
|
|
7
|
+
|
|
8
|
+
Implemented: `add-property`, `verify-via-cf-dns`, `submit-sitemap`,
|
|
9
|
+
`pull-analytics`, `list-properties`. Auth via Google service-account JSON
|
|
10
|
+
loaded from the SOPS vault. Cloudflare planting via the CF v4 REST API.
|
|
11
|
+
|
|
12
|
+
## Dependencies
|
|
13
|
+
|
|
14
|
+
Two npm packages (declared in `@stravica-ai/digital-operator-pa`):
|
|
15
|
+
|
|
16
|
+
- `googleapis` — the canonical Node SDK for Google Cloud APIs.
|
|
17
|
+
- `google-auth-library` — JWT auth helper used by `googleapis`.
|
|
18
|
+
|
|
19
|
+
## Operator setup (one-time per platform install)
|
|
20
|
+
|
|
21
|
+
1. **Create a Google Cloud project** dedicated to GSC automation. Pick a
|
|
22
|
+
short name like `gsc-automation-prod`.
|
|
23
|
+
|
|
24
|
+
2. **Enable the APIs** in that project:
|
|
25
|
+
- Search Console API:
|
|
26
|
+
https://console.cloud.google.com/apis/library/searchconsole.googleapis.com
|
|
27
|
+
- Site Verification API:
|
|
28
|
+
https://console.cloud.google.com/apis/library/siteverification.googleapis.com
|
|
29
|
+
|
|
30
|
+
3. **Create a service account** under IAM & Admin → Service accounts:
|
|
31
|
+
- Name: `gsc-automation`
|
|
32
|
+
- No project-level roles needed (GSC permissions are granted per-property
|
|
33
|
+
in the GSC dashboard, not at GCP IAM level).
|
|
34
|
+
|
|
35
|
+
4. **Generate a JSON key** for the service account (Keys tab → Add Key →
|
|
36
|
+
JSON). Download the file — this is the SA key.
|
|
37
|
+
|
|
38
|
+
5. **Store the SA key in the SOPS vault**:
|
|
39
|
+
```bash
|
|
40
|
+
pnpm exec secrets set GSC_SERVICE_ACCOUNT_KEY -
|
|
41
|
+
# paste the entire JSON contents, then Ctrl-D
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
6. **Store Cloudflare credentials** (also one-time). Two key shapes are
|
|
45
|
+
supported; pick whichever fits your setup:
|
|
46
|
+
|
|
47
|
+
**Single-account setup** — one CF account, no `--account` flag needed:
|
|
48
|
+
```bash
|
|
49
|
+
pnpm exec secrets set CLOUDFLARE_PAGES_API_KEY <token>
|
|
50
|
+
pnpm exec secrets set CLOUDFLARE_PAGES_ACCOUNT_ID <account-id>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Multi-account setup** — multiple CF accounts, each addressed by name:
|
|
54
|
+
```bash
|
|
55
|
+
# Stravica account → addressed as --account stravica
|
|
56
|
+
pnpm exec secrets set CLOUDFLARE_PAGES_API_KEY_STRAVICA <token>
|
|
57
|
+
pnpm exec secrets set CLOUDFLARE_PAGES_ACCOUNT_ID_STRAVICA <account-id>
|
|
58
|
+
|
|
59
|
+
# Clive account → addressed as --account clive
|
|
60
|
+
pnpm exec secrets set CLOUDFLARE_PAGES_API_KEY_CLIVE <token>
|
|
61
|
+
pnpm exec secrets set CLOUDFLARE_PAGES_ACCOUNT_ID_CLIVE <account-id>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The CF API token needs `Zone:DNS:Edit` and `Zone:Zone:Read` for any
|
|
65
|
+
zones the tool will operate on. Account-level "Write to all resources"
|
|
66
|
+
tokens also work.
|
|
67
|
+
|
|
68
|
+
For back-compat, the legacy `CLOUDFLARE_API_TOKEN` /
|
|
69
|
+
`CLOUDFLARE_ACCOUNT_ID` pair is read as a last-resort fallback when
|
|
70
|
+
no `--account` flag is passed and the `CLOUDFLARE_PAGES_*` unsuffixed
|
|
71
|
+
pair is absent. Don't rely on it — set the `CLOUDFLARE_PAGES_*` keys.
|
|
72
|
+
|
|
73
|
+
## Per-domain setup (each time you onboard a new property)
|
|
74
|
+
|
|
75
|
+
7. **Grant the service-account access to the GSC property.** Until the
|
|
76
|
+
property exists, you can't grant access. So the workflow is:
|
|
77
|
+
|
|
78
|
+
1. Run `pa gsc verify-via-cf-dns <domain>` — this performs verification
|
|
79
|
+
end-to-end and registers the property under the SA's identity, so
|
|
80
|
+
the SA implicitly has Owner permission.
|
|
81
|
+
|
|
82
|
+
*Or, if a property already exists under a human Google account:*
|
|
83
|
+
|
|
84
|
+
2. Open Search Console → Settings → Users and permissions →
|
|
85
|
+
Add user, paste the SA email (`<name>@<project>.iam.gserviceaccount.com`),
|
|
86
|
+
grant Owner (or Full).
|
|
87
|
+
|
|
88
|
+
The `pa gsc list-properties` command will then show the property.
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Get the verification TXT token for a domain (no DNS change yet)
|
|
94
|
+
pnpm exec pa gsc add-property stravica.ai
|
|
95
|
+
|
|
96
|
+
# Plant the TXT in Cloudflare, wait, verify, register
|
|
97
|
+
pnpm exec pa gsc verify-via-cf-dns stravica.ai
|
|
98
|
+
# Optional --wait SECONDS to override the default 60s propagation pause:
|
|
99
|
+
pnpm exec pa gsc verify-via-cf-dns stravica.ai --wait 120
|
|
100
|
+
# Multi-account: select which CF account's vault keys to use:
|
|
101
|
+
pnpm exec pa gsc verify-via-cf-dns stravica.ai --account stravica
|
|
102
|
+
pnpm exec pa gsc verify-via-cf-dns besafetraining.co.uk --account clive
|
|
103
|
+
|
|
104
|
+
# Submit a sitemap
|
|
105
|
+
pnpm exec pa gsc submit-sitemap stravica.ai https://stravica.ai/sitemap.xml
|
|
106
|
+
|
|
107
|
+
# Pull search analytics (default 28d, top queries, 100 rows)
|
|
108
|
+
pnpm exec pa gsc pull-analytics stravica.ai
|
|
109
|
+
pnpm exec pa gsc pull-analytics stravica.ai --days 90 --dimensions query,page --rows 500
|
|
110
|
+
|
|
111
|
+
# List every property the SA can see (sanity-check setup)
|
|
112
|
+
pnpm exec pa gsc list-properties
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Multi-account selection
|
|
116
|
+
|
|
117
|
+
When `--account <name>` is passed to `verify-via-cf-dns`, the tool resolves
|
|
118
|
+
the Cloudflare credentials by upper-casing the name and looking up the
|
|
119
|
+
corresponding suffixed vault pair. For example:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
--account stravica -> CLOUDFLARE_PAGES_API_KEY_STRAVICA
|
|
123
|
+
CLOUDFLARE_PAGES_ACCOUNT_ID_STRAVICA
|
|
124
|
+
--account clive -> CLOUDFLARE_PAGES_API_KEY_CLIVE
|
|
125
|
+
CLOUDFLARE_PAGES_ACCOUNT_ID_CLIVE
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
If `--account` is passed but the suffixed pair isn't set, the command
|
|
129
|
+
fails fast with a message telling you which key is missing. It does
|
|
130
|
+
**not** silently fall back to the unsuffixed pair — that would defeat
|
|
131
|
+
the safety the flag exists to provide.
|
|
132
|
+
|
|
133
|
+
Without `--account`, resolution order is:
|
|
134
|
+
1. `CLOUDFLARE_PAGES_API_KEY` + `CLOUDFLARE_PAGES_ACCOUNT_ID`
|
|
135
|
+
2. Legacy `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` (back-compat
|
|
136
|
+
only; do not rely on this).
|
|
137
|
+
|
|
138
|
+
The account name accepts letters and digits only — anything else is a
|
|
139
|
+
usage error.
|
|
140
|
+
|
|
141
|
+
## Notes
|
|
142
|
+
|
|
143
|
+
- Properties are always registered as **domain-properties** (`sc-domain:<host>`),
|
|
144
|
+
which cover https + http + every subdomain under a single property. The
|
|
145
|
+
legacy URL-prefix shape is not supported by this tool.
|
|
146
|
+
- The verification TXT record is planted at the **apex** of the domain
|
|
147
|
+
(no `_google-site-verification` subdomain prefix — that is required for
|
|
148
|
+
URL-prefix properties only).
|
|
149
|
+
- The Cloudflare DNS write is **idempotent**: a re-run with the same
|
|
150
|
+
token leaves DNS untouched; a re-run after a token rotation updates
|
|
151
|
+
the existing record in place.
|
|
152
|
+
- Verification can fail if DNS hasn't propagated yet. Re-run with
|
|
153
|
+
`--wait 180` if the default 60s is too short.
|
|
154
|
+
|
|
155
|
+
## Exit codes
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
0 OK
|
|
159
|
+
1 Usage error / vault uninitialised / domain ambiguous
|
|
160
|
+
2 Operational failure (Google API, Cloudflare API, verification failed)
|
|
161
|
+
3 Transport / network / missing SDK
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Live-test gap
|
|
165
|
+
|
|
166
|
+
The mock test suite covers the auth-construction path, domain
|
|
167
|
+
normalisation, CF API request shape, and the GSC verb plumbing. Live
|
|
168
|
+
testing requires:
|
|
169
|
+
|
|
170
|
+
1. The operator setup above completed (GCP project + APIs + SA key in vault).
|
|
171
|
+
2. CF credentials in vault.
|
|
172
|
+
3. One real domain to verify.
|
|
173
|
+
|
|
174
|
+
After GCP setup, run `pa gsc list-properties` first — it requires no
|
|
175
|
+
DNS or verification and proves the SA key + scopes work end-to-end.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# pa lint linkedin
|
|
2
|
+
|
|
3
|
+
Deterministic voice-rule linter for operator-authored LinkedIn text. Loads a
|
|
4
|
+
JSON rule corpus and reports voice-rule violations in **alter-format** — each
|
|
5
|
+
finding tells the writer what to do (`swap → X`, `cut`, `rename`) rather than
|
|
6
|
+
just flagging a banned token.
|
|
7
|
+
|
|
8
|
+
## Why this exists
|
|
9
|
+
|
|
10
|
+
Voice rules that are machine-checkable should be machine-checked, not left to a
|
|
11
|
+
prompt instruction the writer mentally verifies against. Three voice failures
|
|
12
|
+
shipped in one week despite a pre-delivery checklist (a forced "isn't X, it's Y"
|
|
13
|
+
contrast, a `the right cut` reaction phrase reused across sibling replies, an
|
|
14
|
+
`Indeed..` opener repeated across replies). This linter moves those rules into a
|
|
15
|
+
validator. The framing is deliberately **alter, not block**: the writer is more
|
|
16
|
+
reliable picking from a known target than avoiding a blacklist, so every rule
|
|
17
|
+
carries its swap / cut / rename guidance inline.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pa lint linkedin <input-file> [options]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
| Option | Default | Meaning |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `--rules <path>` | `operator/knowledge/writing/linkedin-rules.json` under the repo root | Rule corpus JSON. Required if the default file is absent. |
|
|
28
|
+
| `--format <text\|json>` | `text` | Output format. |
|
|
29
|
+
| `--severity <error\|warning\|info>` | `error` | Severity floor — only violations at or above this level are reported. |
|
|
30
|
+
| `--surface <name>` | `linkedin` | Surface context: `all`, `linkedin`, `article`, `newsletter`, `reply`. A rule applies if its `surface` is `all` or includes this value. |
|
|
31
|
+
| `-h, --help` | | Show help. |
|
|
32
|
+
|
|
33
|
+
The default rules path resolves relative to the operator repo root (located via
|
|
34
|
+
`$DAVE_REPO_ROOT` / `$PA_REPO_ROOT`, else by walking up to the nearest `.git`).
|
|
35
|
+
If it is absent and `--rules` is not given, the command exits 3 with guidance.
|
|
36
|
+
|
|
37
|
+
### Text output
|
|
38
|
+
|
|
39
|
+
One line per violation:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
<file>:<line>:<col> <severity> <ruleId> <matched-text> → <alter-guidance>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
post.md:1:14 error punct-em-dash "—" → swap → "," | " - " — Comma or hyphen carries the load.
|
|
49
|
+
post.md:2:7 error vocab-utilize "utilize" → swap → "use" — Plain word.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### JSON output
|
|
53
|
+
|
|
54
|
+
`--format json` prints an array (`[]` when clean — always valid JSON). Each
|
|
55
|
+
entry:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"file": "post.md",
|
|
60
|
+
"line": 1,
|
|
61
|
+
"col": 14,
|
|
62
|
+
"ruleId": "punct-em-dash",
|
|
63
|
+
"severity": "error",
|
|
64
|
+
"matched": "—",
|
|
65
|
+
"alter": "swap → \",\" | \" - \" — Comma or hyphen carries the load.",
|
|
66
|
+
"rationale": "Hard AI tell. Operator-mandated permanent rule.",
|
|
67
|
+
"source": "operator/knowledge/writing/voice-guide.md"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Exit codes
|
|
72
|
+
|
|
73
|
+
This command uses **lint-semantic exit codes** (ESLint/ruff-style), where the
|
|
74
|
+
code reports the worst severity among the *reported* (post-floor) findings:
|
|
75
|
+
|
|
76
|
+
| Code | Meaning |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `0` | Clean — no findings at/above the floor (info-only also exits 0) |
|
|
79
|
+
| `1` | At least one `error` finding |
|
|
80
|
+
| `2` | `warning` findings only (no errors) |
|
|
81
|
+
| `3` | Usage / IO / config error (bad flag, missing file, malformed corpus) |
|
|
82
|
+
|
|
83
|
+
> **Note — deviation from tooling standard §6.** The platform standard reserves
|
|
84
|
+
> exit `1` for usage errors and `2`/`3` for operational/transport failure. A
|
|
85
|
+
> linter's exit code is load-bearing differently: automation needs to branch on
|
|
86
|
+
> *what was found*, not just *did the tool run*. So this command follows the
|
|
87
|
+
> universal linter convention (`1` = findings, higher = clean-vs-broken) and
|
|
88
|
+
> maps every non-finding failure to `3`. This is the only `pa` verb that
|
|
89
|
+
> deviates, and it does so intentionally.
|
|
90
|
+
|
|
91
|
+
## Rule corpus schema
|
|
92
|
+
|
|
93
|
+
The corpus is a JSON array of independent rule objects (order does not matter).
|
|
94
|
+
The loader validates strictly — a malformed corpus is a config error (exit 3),
|
|
95
|
+
never a silent skip.
|
|
96
|
+
|
|
97
|
+
```jsonc
|
|
98
|
+
{
|
|
99
|
+
"ruleId": "punct-em-dash", // kebab-case, unique across the corpus
|
|
100
|
+
"category": "punctuation", // punctuation | vocabulary | phrase |
|
|
101
|
+
// reaction-phrase | filler | structural |
|
|
102
|
+
// format | count
|
|
103
|
+
"surface": ["all"], // any of: all linkedin article newsletter reply
|
|
104
|
+
"severity": "error", // error | warning | info
|
|
105
|
+
"detect": { /* see below */ },
|
|
106
|
+
"alter": { /* see below */ },
|
|
107
|
+
"rationale": "Hard AI tell.", // why the rule exists
|
|
108
|
+
"source": "operator/knowledge/writing/voice-guide.md" // human-readable home
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `detect`
|
|
113
|
+
|
|
114
|
+
| `type` | Fields | Behaviour |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `literal-phrase` | `phrase`, `caseSensitive` (default `false`), `wordBoundary` (default `true`) | Matches the phrase as text. Word boundaries are applied at word-character edges only. |
|
|
117
|
+
| `regex` | `pattern`, `caseSensitive` (default `false`) | Matches the pattern. Scanned line-by-line, so positions are exact and negated classes can't swallow newlines. |
|
|
118
|
+
| `count` | `pattern`, `max` | Counts matches document-wide; flags every occurrence **beyond** `max`. Use `(?:^\|\n)…` anchoring to count line openers. |
|
|
119
|
+
|
|
120
|
+
### `alter`
|
|
121
|
+
|
|
122
|
+
| `kind` | Fields | Rendered as |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| `swap` | `with` (array of replacement strings), `guidance` | `swap → "a" \| "b" — guidance` |
|
|
125
|
+
| `cut` | `guidance` | `cut → guidance` |
|
|
126
|
+
| `rename` | `guidance` (open-ended rephrase instruction) | `rename → guidance` |
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
# Lint a draft against the default operator corpus.
|
|
132
|
+
pa lint linkedin drafts/post.md
|
|
133
|
+
|
|
134
|
+
# Lint a reply, surfacing warnings too, as JSON.
|
|
135
|
+
pa lint linkedin drafts/reply.md --surface reply --severity warning --format json
|
|
136
|
+
|
|
137
|
+
# Lint against an explicit corpus (e.g. in CI or a fixture).
|
|
138
|
+
pa lint linkedin post.md --rules path/to/linkedin-rules.json
|
|
139
|
+
```
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Secrets Management
|
|
2
|
+
|
|
3
|
+
Identity: `ai.stravica.ops.secrets` — CLI alias `secrets`.
|
|
4
|
+
|
|
5
|
+
Dave uses SOPS with age encryption for secrets management. Secrets are encrypted at rest and stored in `.vault/` within the repository. The encrypted file is safe to commit to git — only the holder of the private key can decrypt it.
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
Implemented: `init`, `get`, `set`, `list`, `delete`, `rotate`, `status`, `backup`, `vaults`, `find` (alias `which`), `verify`. No npm dependencies — shells out to `sops` and `age` via `node:child_process.spawn`.
|
|
10
|
+
|
|
11
|
+
`set` additionally supports `--canonical-clone PATH` (write a canonical clone's vault file first, then the resolved workspace copy — aborts before touching the workspace copy if the canonical write fails). `verify --values --against PATH` does a byte-level comparison of DECRYPTED values between the resolved vault and a reference vault at PATH — never a decrypt-only pass. See "Value-compare verification" and "Canonical-first writes" below.
|
|
12
|
+
|
|
13
|
+
`get`/`set` run without `--scope`/`--file` now resolve a **default scope** — `$SECRETS_DEFAULT_SCOPE` env var, then `"defaultScope"` in `~/.config/stravica-pa/defaults.json`, then the calling PA's own `agents/<name>/identity.json`, then the legacy single-file vault as a last resort. Every such invocation prints a one-line stderr notice naming the target vault BEFORE the operation runs, including the legacy-fallback case ("no scope specified and no default configured") — see `secrets --help` → "Default scope" for the full precedence and example notices.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Two tools are required:
|
|
18
|
+
|
|
19
|
+
- **age** — modern encryption tool
|
|
20
|
+
- macOS: `brew install age`
|
|
21
|
+
- Debian/Ubuntu: `sudo apt install age`
|
|
22
|
+
- Manual: https://github.com/FiloSottile/age/releases/latest
|
|
23
|
+
|
|
24
|
+
- **SOPS** — encrypted file editor
|
|
25
|
+
- macOS: `brew install sops`
|
|
26
|
+
- Debian/Ubuntu: download from https://github.com/getsops/sops/releases
|
|
27
|
+
- Manual: https://github.com/getsops/sops/releases/latest
|
|
28
|
+
|
|
29
|
+
## Invoke
|
|
30
|
+
|
|
31
|
+
The CLI shim is `core/tools/secrets/bin/secrets`. You can run it directly with `node`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
node core/tools/secrets/bin/secrets <verb> [ARGS]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or via the per-tool symlink convention (see tooling standard §14):
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
secrets <verb> [ARGS]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Initialise the vault (generate keys, create config, empty encrypted store)
|
|
47
|
+
node core/tools/secrets/bin/secrets init
|
|
48
|
+
|
|
49
|
+
# Store a secret
|
|
50
|
+
node core/tools/secrets/bin/secrets set API_KEY "sk-abc123"
|
|
51
|
+
|
|
52
|
+
# Retrieve a secret
|
|
53
|
+
node core/tools/secrets/bin/secrets get API_KEY
|
|
54
|
+
|
|
55
|
+
# List all secret names (values are not shown)
|
|
56
|
+
node core/tools/secrets/bin/secrets list
|
|
57
|
+
|
|
58
|
+
# Remove a secret
|
|
59
|
+
node core/tools/secrets/bin/secrets delete API_KEY
|
|
60
|
+
|
|
61
|
+
# Re-encrypt all secrets with the current recipients
|
|
62
|
+
node core/tools/secrets/bin/secrets rotate
|
|
63
|
+
|
|
64
|
+
# Check vault health (exit 0 when initialised, 1 otherwise)
|
|
65
|
+
node core/tools/secrets/bin/secrets status
|
|
66
|
+
|
|
67
|
+
# Open a browser with a QR code of the master key for backup
|
|
68
|
+
node core/tools/secrets/bin/secrets backup
|
|
69
|
+
|
|
70
|
+
# Write a canonical clone's vault FIRST, then the workspace copy second.
|
|
71
|
+
# Aborts (exit 2) before touching the workspace copy if the canonical
|
|
72
|
+
# write fails (e.g. the existing canonical store can't be decrypted).
|
|
73
|
+
node core/tools/secrets/bin/secrets set API_KEY "sk-abc123" --canonical-clone /path/to/canonical/vault/scope.enc.json
|
|
74
|
+
|
|
75
|
+
# Byte-level comparison of DECRYPTED values against a reference vault.
|
|
76
|
+
# --values is required — there is no decrypt-only verification mode
|
|
77
|
+
# (decrypt-only false-passes a vault that decrypts cleanly but holds the
|
|
78
|
+
# wrong content, e.g. a clobbered/stale copy with placeholder values).
|
|
79
|
+
node core/tools/secrets/bin/secrets verify --values --against /path/to/other/vault/scope.enc.json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Canonical-first writes (`set --canonical-clone`)
|
|
83
|
+
|
|
84
|
+
Without the flag, `set` behaves exactly as before — it writes only the
|
|
85
|
+
resolved workspace copy. With `--canonical-clone PATH`, `set`:
|
|
86
|
+
|
|
87
|
+
1. Resolves `PATH` the same way `--file` resolves any other vault (its
|
|
88
|
+
own `.sops.yaml` expected alongside it), reusing this host's own key
|
|
89
|
+
material (`keyDir`/`keyFile`) — the canonical clone and the workspace
|
|
90
|
+
copy are expected to share recipients in practice (same operator,
|
|
91
|
+
same device).
|
|
92
|
+
2. Decrypts the existing canonical store (if any) and writes the new key
|
|
93
|
+
into it. **If this fails for any reason — the existing canonical
|
|
94
|
+
store can't be decrypted, or the encrypt itself fails — `set` aborts
|
|
95
|
+
with exit 2 and the workspace copy is never touched.**
|
|
96
|
+
3. Only on canonical success does it proceed to the existing
|
|
97
|
+
decrypt-mutate-encrypt cycle against the resolved workspace copy.
|
|
98
|
+
|
|
99
|
+
This closes the "device-side vault mutation only round-trips halfway"
|
|
100
|
+
class: a device-side `secrets set` that updates the workspace copy but
|
|
101
|
+
never reaches canonical leaves the two vaults silently diverged until the
|
|
102
|
+
next down-path materialisation clobbers the device's fresher value.
|
|
103
|
+
`--canonical-clone` makes the canonical write the FIRST, gating step —
|
|
104
|
+
the workspace never ends up ahead of canonical.
|
|
105
|
+
|
|
106
|
+
### Value-compare verification (`verify --values --against`)
|
|
107
|
+
|
|
108
|
+
Any vault verification that stops at "the store decrypts" is a false-pass
|
|
109
|
+
waiting to happen: an always-take-canonical materialisation can silently
|
|
110
|
+
overwrite a device's real secret values with stale or placeholder
|
|
111
|
+
content, and the decrypt still succeeds (same recipients) — only a
|
|
112
|
+
byte-level VALUE comparison against a known-good reference catches it.
|
|
113
|
+
`secrets verify` therefore has no decrypt-only mode at all; `--values` is
|
|
114
|
+
required, and omitting it is a usage error (exit 1), not a lesser check.
|
|
115
|
+
|
|
116
|
+
`--against PATH` names the reference vault (any vault file, resolved the
|
|
117
|
+
same way `--file` resolves elsewhere). Both vaults are decrypted and
|
|
118
|
+
compared key-by-key; the report never prints a decrypted value, only the
|
|
119
|
+
per-key result:
|
|
120
|
+
|
|
121
|
+
- `same` — both sides hold byte-identical values
|
|
122
|
+
- `differs` — both sides have the key, values differ
|
|
123
|
+
- `missing-in-reference` — key exists in the working vault only
|
|
124
|
+
- `missing-in-working` — key exists in the reference vault only
|
|
125
|
+
|
|
126
|
+
Exit 0 only when every key is `same`; exit 2 otherwise (or if either side
|
|
127
|
+
fails to decrypt at all).
|
|
128
|
+
|
|
129
|
+
## Exit codes
|
|
130
|
+
|
|
131
|
+
| Code | Meaning |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `0` | OK |
|
|
134
|
+
| `1` | Usage / not-initialised / not-found |
|
|
135
|
+
| `2` | Operational failure (sops decrypt or encrypt failed, bad JSON) |
|
|
136
|
+
| `3` | Transport failure (spawn failed) |
|
|
137
|
+
|
|
138
|
+
## Operational discipline
|
|
139
|
+
|
|
140
|
+
- The private key must never be committed. It lives only at `~/.config/dave/age-key.txt`, with mode `600` on a `700` key directory.
|
|
141
|
+
- All sops/age invocations are spawned with arguments as an array — no shell interpolation surface.
|
|
142
|
+
- Tests must never touch the real `~/.config/dave/` or repo `.vault/`. The test helpers mint a disposable temp directory for every case.
|
|
143
|
+
|
|
144
|
+
## Project layout
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
core/tools/secrets/
|
|
148
|
+
bin/secrets # node shebang shim — one line
|
|
149
|
+
package.json # name: ai.stravica.ops.secrets, type: module, no deps
|
|
150
|
+
README.md # this file
|
|
151
|
+
src/
|
|
152
|
+
cli.mjs # verb routing + exit-code translation
|
|
153
|
+
vault.mjs # domain + sops/age spawn chokepoint
|
|
154
|
+
commands/
|
|
155
|
+
init.mjs # generate keypair, write recipients/config, empty store
|
|
156
|
+
get.mjs # print a single secret value
|
|
157
|
+
set.mjs # upsert and re-encrypt
|
|
158
|
+
list.mjs # sorted key names
|
|
159
|
+
delete.mjs # remove and re-encrypt
|
|
160
|
+
rotate.mjs # decrypt + re-encrypt with current recipients
|
|
161
|
+
status.mjs # vault health report
|
|
162
|
+
backup.mjs # render QR-code HTML and open it in the default browser
|
|
163
|
+
backup-template.mjs # HTML + embedded alphanumeric QR generator
|
|
164
|
+
vaults.mjs # enumerate every visible vault (names only, no decryption)
|
|
165
|
+
find.mjs # report which vault(s) contain a key by name (alias: which)
|
|
166
|
+
verify.mjs # byte-level DECRYPTED-value comparison against a reference vault
|
|
167
|
+
test/
|
|
168
|
+
helpers.mjs # temp-vault isolation
|
|
169
|
+
*.test.mjs # node:test coverage per subcommand + CLI routing
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Security model
|
|
173
|
+
|
|
174
|
+
- The **private key** (`~/.config/dave/age-key.txt`) never enters the repository. It is gitignored and lives only on the machine where secrets need to be decrypted.
|
|
175
|
+
- The **public key** (`.vault/recipients.txt`) is committed. It allows anyone with repo access to encrypt new secrets, but only the private key holder can decrypt them.
|
|
176
|
+
- The **encrypted secrets file** (`.vault/secrets.enc.json`) is committed. It is safe to store in git because its contents are encrypted with the age public key.
|
|
177
|
+
- SOPS handles encryption/decryption transparently. The `.vault/.sops.yaml` config tells SOPS which key to use.
|
|
178
|
+
|
|
179
|
+
## Key rotation
|
|
180
|
+
|
|
181
|
+
If you need to rotate keys (e.g. a machine was compromised):
|
|
182
|
+
|
|
183
|
+
1. Generate a new keypair: `age-keygen -o ~/.config/dave/age-key.txt`
|
|
184
|
+
2. Update `.vault/recipients.txt` with the new public key
|
|
185
|
+
3. Update `.vault/.sops.yaml` with the new public key
|
|
186
|
+
4. Run `node core/tools/secrets/bin/secrets rotate` to re-encrypt all secrets with the new key
|
|
187
|
+
|
|
188
|
+
Note: you need the old private key present to decrypt before re-encrypting. If the old key is lost, the secrets cannot be recovered.
|
|
189
|
+
|
|
190
|
+
## Multi-machine setup
|
|
191
|
+
|
|
192
|
+
To use secrets on a second machine:
|
|
193
|
+
|
|
194
|
+
1. Clone the repository (public key and encrypted secrets are included)
|
|
195
|
+
2. Copy your private key to `~/.config/dave/age-key.txt` on the new machine
|
|
196
|
+
3. Secrets are immediately accessible via `node core/tools/secrets/bin/secrets get`
|
|
197
|
+
|
|
198
|
+
The private key must be transferred securely (e.g. via a password manager, secure file transfer, or physical media). Never send it over unencrypted channels.
|
|
199
|
+
|
|
200
|
+
## Backup
|
|
201
|
+
|
|
202
|
+
Back up `~/.config/dave/age-key.txt` securely. If you lose it, your encrypted secrets are unrecoverable. The encrypted file in git is useless without the private key.
|
|
203
|
+
|
|
204
|
+
The `backup` command renders the master key as a QR code in a temporary HTML file and opens it in the default browser. The file self-destructs after 30 seconds. No browser-automation dependency — the QR generator is a small pure-JS module embedded in the generated HTML.
|
|
205
|
+
|
|
206
|
+
## Tests
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
node --test core/tools/secrets/test/*.test.mjs
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The integration tests require `sops` and `age` on PATH and skip gracefully when either is missing. The CLI-routing tests always run.
|
|
213
|
+
|
|
214
|
+
## The tooling standard
|
|
215
|
+
|
|
216
|
+
This tool conforms to the standard in [`core/knowledge/standards/tooling.md`](../../knowledge/standards/tooling.md). Notable points:
|
|
217
|
+
|
|
218
|
+
- Zero npm dependencies. Node stdlib only.
|
|
219
|
+
- All external effects (sops, age, fs writes in the vault path) route through `src/vault.mjs`.
|
|
220
|
+
- Commands return numeric exit codes or throw `VaultError` with an `exitCode` property. The CLI wrapper translates to `process.exit`.
|
|
221
|
+
- JSON property names are camelCase.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# smoke
|
|
2
|
+
|
|
3
|
+
## Identity
|
|
4
|
+
|
|
5
|
+
- **Name**: `ai.stravica.platform.smoke`
|
|
6
|
+
- **Alias**: `smoke`
|
|
7
|
+
- **Purpose**: Fresh-clone smoke suite for the Dave platform. Simulates a clean clone and validates structure, server, APIs, and CLI tools before shipping.
|
|
8
|
+
|
|
9
|
+
## Status
|
|
10
|
+
|
|
11
|
+
Implemented: all 52 assertions from the legacy `test/smoke.sh` (path existence, workspace server boot, HTML page HTTP 200s, JSON API validity, CLI `--help` invocations, `secrets` execution, `dave.sh --help`).
|
|
12
|
+
|
|
13
|
+
Deferred: none. This is a direct Node.js port with no scope change.
|
|
14
|
+
|
|
15
|
+
## Install / invoke
|
|
16
|
+
|
|
17
|
+
From the repo root:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm run test:smoke
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or invoke the binary directly:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
node core/tools/smoke/bin/smoke
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Commands
|
|
30
|
+
|
|
31
|
+
The tool has a single default command; `npm run test:smoke` is the canonical invocation.
|
|
32
|
+
|
|
33
|
+
| Flag | Purpose |
|
|
34
|
+
|-----------------|-----------------------------------------------------------------|
|
|
35
|
+
| `--help, -h` | Print usage and exit 0 |
|
|
36
|
+
| `--root <path>` | Repo root to smoke-test (default: auto-detected from the binary location) |
|
|
37
|
+
| `--port <n>` | HTTP port for the workspace server during the run (default: 4201) |
|
|
38
|
+
|
|
39
|
+
No verbs, no subcommands — this is a single-purpose runner.
|
|
40
|
+
|
|
41
|
+
## Exit codes
|
|
42
|
+
|
|
43
|
+
| Code | Meaning |
|
|
44
|
+
|------|----------------------------------------------------------------------|
|
|
45
|
+
| `0` | All checks passed |
|
|
46
|
+
| `1` | One or more checks failed, or a usage error (bad argument) |
|
|
47
|
+
| `2` | Internal error (uncaught exception in the tool itself) |
|
|
48
|
+
| `3` | IO / transport failure during setup (tempdir, copy, or server launch)|
|
|
49
|
+
|
|
50
|
+
## Operational discipline rules
|
|
51
|
+
|
|
52
|
+
- **No side effects on the source tree.** The suite copies the repo into a temp directory (`rm -rf`'d on exit) and performs every assertion against the copy. The source tree is only read.
|
|
53
|
+
- **Single chokepoint for external effects.** `src/runner.mjs` owns every process spawn, HTTP fetch, and filesystem mutation. Commands and checks delegate to it; no other module may spawn or fetch.
|
|
54
|
+
- **Server lifecycle is bracketed.** The workspace server is launched once per run, killed in `finally`, and never leaks across invocations. If a check throws, cleanup still runs.
|
|
55
|
+
- **HTTP / JSON checks are gated.** If the server fails to come up within the ready-probe budget, downstream HTTP and JSON assertions are skipped (not failed) — matching the legacy behaviour.
|
|
56
|
+
- **Zero npm dependencies.** The tool uses only `node:` built-ins (`util`, `child_process`, `fs/promises`, `path`, `os`, `test`, `assert/strict`) plus the global `fetch`.
|
|
57
|
+
|
|
58
|
+
## Project layout
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
core/tools/smoke/
|
|
62
|
+
bin/smoke # node shebang shim — one line
|
|
63
|
+
package.json # name, version, type: module, no dependencies
|
|
64
|
+
README.md # this file
|
|
65
|
+
src/
|
|
66
|
+
cli.mjs # parseArgs, --help, exit-code translation
|
|
67
|
+
checks.mjs # pure check plan: path, http, json, cli classes
|
|
68
|
+
runner.mjs # external-effects chokepoint (spawn, fetch, fs)
|
|
69
|
+
commands/
|
|
70
|
+
run.mjs # orchestrates copy → launch → check → cleanup
|
|
71
|
+
test/
|
|
72
|
+
checks.test.mjs # plan shape, parity with legacy smoke.sh
|
|
73
|
+
cli.test.mjs # arg parsing and exit-code cases
|
|
74
|
+
run.test.mjs # orchestration via fake runner
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Per-entry rationale:
|
|
78
|
+
|
|
79
|
+
- **`bin/smoke`** — one-line shim; logic lives in `src/cli.mjs`.
|
|
80
|
+
- **`src/cli.mjs`** — the only module that calls `process.exit`. Commands return numbers or throw; this wrapper translates.
|
|
81
|
+
- **`src/checks.mjs`** — pure data + helpers. Defines the ordered plan. No I/O.
|
|
82
|
+
- **`src/runner.mjs`** — chokepoint for every external effect. Tests inject fakes here.
|
|
83
|
+
- **`src/commands/run.mjs`** — the single command that orchestrates the suite.
|
|
84
|
+
- **`test/`** — `node:test` files. No separate config.
|
|
85
|
+
|
|
86
|
+
## Check plan (parity with legacy `test/smoke.sh`)
|
|
87
|
+
|
|
88
|
+
| Section | Count | Class | What |
|
|
89
|
+
|---------|-------|--------------|---------------------------------------------------------------|
|
|
90
|
+
| Step 3 | 1 | `execFile` | `dave.sh` is an executable file |
|
|
91
|
+
| Step 4 | 1 | `file` | `dave.ps1` exists |
|
|
92
|
+
| Step 5 | 33 | `path` | Expected-path existence (roles, retrieval, desk, workspace app, .gitkeeps, top-level docs) |
|
|
93
|
+
| Step 6-7| 1 | `serverReady`| Workspace server becomes reachable on the test port |
|
|
94
|
+
| Step 8 | 7 | `httpStatus` | `/`, `home.html`, `onboarding.html`, `tasks.html`, `knowledge.html`, `secrets.html`, `viewer.html` all return 200 |
|
|
95
|
+
| Step 9 | 3 | `jsonValid` | `/__api/overview`, `/__api/projects`, `/__api/work` return parseable JSON |
|
|
96
|
+
| Step 10-13 | 4 | `cliExit` | `backlink-indexer.mjs --help`, `graph-builder.mjs --help`, `query.mjs --help`, `desk --help` exit 0 |
|
|
97
|
+
| Step 14 | 1 | `vaultExit` | `node core/tools/secrets/bin/secrets` exits 0 or 1 |
|
|
98
|
+
| Step 15 | 1 | `cliShell` | `bash dave.sh --help` exits 0 |
|
|
99
|
+
| **Total** | **52** | | |
|
|
100
|
+
|
|
101
|
+
Labels match the bash `PASS:` lines verbatim — CI log comparisons stay valid.
|
|
102
|
+
|
|
103
|
+
## Tests
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
node --test core/tools/smoke/test/*.test.mjs
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The test suite exercises the plan, the CLI wrapper, and the orchestration layer via a fake runner. The real `runner.mjs` is exercised end-to-end by `npm run test:smoke` against the live repo.
|
|
110
|
+
|
|
111
|
+
## The tooling standard
|
|
112
|
+
|
|
113
|
+
Governed by [`core/knowledge/standards/tooling.md`](../../knowledge/standards/tooling.md). This tool follows sections §1–§16 as written: identity (§1), Node-only (§2), zero-dep (§3), project structure (§4), CLI conventions (§5), exit codes (§6), chokepoint (§7), testing (§8), README-as-contract (§9), operational discipline (§10), JSON camelCase (§11).
|