@stravica-ai/digital-operator-pa 0.1.39 → 0.1.40

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/README.md CHANGED
@@ -12,9 +12,14 @@ pnpm add @stravica-ai/digital-operator-pa
12
12
  ```
13
13
 
14
14
  Requires Node 24+. The package is public on `registry.npmjs.org` and needs no
15
- registry auth. See [`../../docs/installing.md`](../../docs/installing.md) for the
15
+ registry auth. See [`./docs/installing.md`](./docs/installing.md) for the
16
16
  full install guide.
17
17
 
18
+ New to the platform and setting up a single-person PA on one laptop? Follow
19
+ [`./docs/onboarding-solo.md`](./docs/onboarding-solo.md) — a
20
+ ten-minute walkthrough from an empty directory to a working PA under your
21
+ own Claude Code subscription.
22
+
18
23
  ## Bins
19
24
 
20
25
  The wrapper exposes the platform's operator-facing CLIs:
@@ -162,7 +167,7 @@ pnpm --filter @stravica-ai/digital-operator-pa pack # produce a rea
162
167
  `access: public`. Publishes are manual (run by a maintainer with npmjs publish
163
168
  rights) from this directory: `pnpm publish` triggers `build.mjs` via `prepack`,
164
169
  then ships the bundled tarball to npmjs.org. `ci.yml`'s `dry-publish` job proves
165
- the pack/publish mechanics on every push. See [`../../docs/installing.md`](../../docs/installing.md)
170
+ the pack/publish mechanics on every push. See [`./docs/installing.md`](./docs/installing.md)
166
171
  for the release-pipeline section.
167
172
 
168
173
  ### Retired predecessor
@@ -24,7 +24,7 @@ The taxonomy every operator's banned-tells doc inherits. Category names and orde
24
24
 
25
25
  **Operator overlays** add operator-specific entries under each existing category. Same category names, same order; more entries.
26
26
 
27
- **Category 13** exists so operator-specific bans have a home when they don't fit the mechanism categories. Barry-voice specific bans (e.g. "cut" as a noun) land here, not in Vocabulary.
27
+ **Category 13** exists so operator-specific bans have a home when they don't fit the mechanism categories. Operator-voice specific bans (e.g. one operator hates "cut" as a noun) land here, not in Vocabulary.
28
28
 
29
29
  ## Related
30
30
 
@@ -41,11 +41,11 @@ Reasoning: session-end batching means the observation is filtered through your o
41
41
  - **Why it matters.** Your best guess at the general rule the observation reveals. The Librarian may reshape this — but your inference from the concrete moment is useful signal.
42
42
 
43
43
  Bad observation:
44
- > `20260705T100000Z_preference.md` — Baz likes short posts.
44
+ > `20260705T100000Z_preference.md` — operator likes short posts.
45
45
 
46
46
  Good observation:
47
- > `20260705T100000Z_preference_barry-prefers-short-li-posts-under-300-chars.md`
48
- > Task: drafting a LI comment reply on Cole Medin's post. Draft came back at 480 chars. Baz's edit cut it to 210 chars and said "keep them under 300, longer feels performative". Suggests LI-comment character target should default lower than the surface's affordance implies.
47
+ > `20260705T100000Z_preference_operator-prefers-short-li-posts-under-300-chars.md`
48
+ > Task: drafting a LinkedIn comment reply. Draft came back at 480 chars. The operator's edit cut it to 210 chars and said "keep them under 300, longer feels performative". Suggests LinkedIn-comment character target should default lower than the surface's affordance implies.
49
49
 
50
50
  ## Don't route directly
51
51
 
@@ -7,6 +7,7 @@
7
7
  // kind: 'dir' (mkdir -p) | 'file' (write file with contents) | 'json'
8
8
  // (stringify + write).
9
9
 
10
+ import { existsSync } from 'node:fs';
10
11
  import { readFile } from 'node:fs/promises';
11
12
  import { dirname, join, resolve } from 'node:path';
12
13
  import { fileURLToPath } from 'node:url';
@@ -18,6 +19,14 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
18
19
  /** Path to the CLAUDE.md template (relative to this module). */
19
20
  export const CLAUDE_MD_TEMPLATE_PATH = resolve(__dirname, '..', 'templates', 'CLAUDE.md.template');
20
21
 
22
+ /** Path to the root-CLAUDE.md pointer template (relative to this module). */
23
+ export const ROOT_CLAUDE_MD_TEMPLATE_PATH = resolve(
24
+ __dirname,
25
+ '..',
26
+ 'templates',
27
+ 'root-CLAUDE.md.template',
28
+ );
29
+
21
30
  /** Path to the operator README template (relative to this module). */
22
31
  export const OPERATOR_README_TEMPLATE_PATH = resolve(
23
32
  __dirname,
@@ -26,6 +35,22 @@ export const OPERATOR_README_TEMPLATE_PATH = resolve(
26
35
  'operator-README.md.template',
27
36
  );
28
37
 
38
+ /**
39
+ * Path to the `/research` slash-command doc, resolved out of the bundled
40
+ * engineering-pa-core package. Two candidates so this works both from the
41
+ * source monorepo (`packages/scaffold/src/generator.mjs` → `packages/core/…`)
42
+ * and from the packed tarball (`dist/engineering-pa-scaffold/src/generator.mjs`
43
+ * → `dist/engineering-pa-core/…`). The scaffold reads the file at plan time
44
+ * so the copy the colleague gets never drifts from the packaged canonical.
45
+ */
46
+ const RESEARCH_COMMAND_CANDIDATES = [
47
+ resolve(__dirname, '..', '..', 'engineering-pa-core', 'docs', 'commands', 'research.md'),
48
+ resolve(__dirname, '..', '..', 'core', 'docs', 'commands', 'research.md'),
49
+ ];
50
+
51
+ export const RESEARCH_COMMAND_TEMPLATE_PATH =
52
+ RESEARCH_COMMAND_CANDIDATES.find((p) => existsSync(p)) ?? RESEARCH_COMMAND_CANDIDATES[0];
53
+
29
54
  /**
30
55
  * The base set of knowledge domains seeded into every fresh PA instance.
31
56
  * Per the methodology doc: engineering, ops, agent-ops, knowledge-meta,
@@ -78,6 +103,19 @@ export function renderClaudeMd(template, config) {
78
103
  .replaceAll('{COMMUNICATION_STYLE}', config.communicationStyle);
79
104
  }
80
105
 
106
+ /**
107
+ * Render the root-CLAUDE.md pointer with the config. The root file is a
108
+ * short quick-reference that points at the full agent CLAUDE.md — the
109
+ * split mirrors the established estate convention (root pointer +
110
+ * canonical agent file) so the two files never drift as byte-identical
111
+ * duplicates.
112
+ */
113
+ export function renderRootClaudeMd(template, config) {
114
+ return template
115
+ .replaceAll('{PA_NAME}', config.paName)
116
+ .replaceAll('{OPERATOR_NAME}', config.operatorName);
117
+ }
118
+
81
119
  /**
82
120
  * Render the operator-repo README template. Uses the same token set as
83
121
  * CLAUDE.md.template for consistency.
@@ -302,6 +340,69 @@ export function buildGitkeep() {
302
340
  return '';
303
341
  }
304
342
 
343
+ /**
344
+ * Build the .claude/settings.json contents.
345
+ *
346
+ * Two things:
347
+ * 1. `permissions.deny` for the built-in `deep-research` skill and
348
+ * workflow. The core operating model (Bucket 4) directs the PA to
349
+ * the `/research` verb, which persists a session and promotes
350
+ * durable answers back into the knowledge library. The built-in
351
+ * `deep-research` skill produces no such trail and would silently
352
+ * short-circuit the discipline; deny is the correct default.
353
+ *
354
+ * 2. `hooks.PreToolUse` wiring `pa-coordinator-hook` for the matcher
355
+ * the coordinator-hook doc gives. The hook is a no-op unless the
356
+ * operator sets `PA_COORDINATOR_MODE=1` in their shell, so the
357
+ * scaffold ships the wiring inert. A per-repo overlay slot is
358
+ * scaffolded alongside as `.claude/coordinator-overlay.json`.
359
+ *
360
+ * SessionStart hooks (boot-context style injection) are deliberately
361
+ * NOT scaffolded — the boot-context tool lives in the HQ estate, not
362
+ * the published package. Scaffolding a hook that names a binary the
363
+ * colleague does not have would fire on every session boot with a
364
+ * non-blocking error. Documented in docs/onboarding-solo.md under
365
+ * "what is not included in solo mode".
366
+ */
367
+ export function buildClaudeSettingsJson() {
368
+ return {
369
+ permissions: {
370
+ deny: ['Skill(skill:deep-research)', 'Workflow(name:deep-research)'],
371
+ },
372
+ hooks: {
373
+ PreToolUse: [
374
+ {
375
+ matcher: '^(Bash|Read|Write|Edit|NotebookEdit|Grep|Glob|WebFetch|WebSearch)$',
376
+ hooks: [
377
+ {
378
+ type: 'command',
379
+ command: 'pa-coordinator-hook',
380
+ },
381
+ ],
382
+ },
383
+ ],
384
+ },
385
+ };
386
+ }
387
+
388
+ /**
389
+ * Build the .claude/coordinator-overlay.json starter. The overlay is a
390
+ * per-repo extension slot for `pa-coordinator-hook` — see the doc at
391
+ * packages/cli/docs/coordinator-hook.md for the merge contract. Only
392
+ * `tier2.<Bash|Read|Write>.allowPatterns` / `.allowPathPatterns` may be
393
+ * extended; the file ships empty so the presence of the overlay is
394
+ * documentation on its own without widening the default policy.
395
+ */
396
+ export function buildCoordinatorOverlayJson() {
397
+ return {
398
+ tier2: {
399
+ Bash: { allowPatterns: [] },
400
+ Read: { allowPathPatterns: [] },
401
+ Write: { allowPathPatterns: [] },
402
+ },
403
+ };
404
+ }
405
+
305
406
  /**
306
407
  * Compose the full plan. Returns an ordered list of `{ kind, path, contents }`
307
408
  * relative to `config.targetDir`. The runner resolves the paths and writes
@@ -309,8 +410,15 @@ export function buildGitkeep() {
309
410
  */
310
411
  export async function buildPlan(config) {
311
412
  const claudeTemplate = await readFile(CLAUDE_MD_TEMPLATE_PATH, 'utf8');
413
+ const rootClaudeTemplate = await readFile(ROOT_CLAUDE_MD_TEMPLATE_PATH, 'utf8');
312
414
  const operatorReadmeTemplate = await readFile(OPERATOR_README_TEMPLATE_PATH, 'utf8');
313
- return buildPlanFromTemplates(config, { claudeTemplate, operatorReadmeTemplate });
415
+ const researchCommand = await readFile(RESEARCH_COMMAND_TEMPLATE_PATH, 'utf8');
416
+ return buildPlanFromTemplates(config, {
417
+ claudeTemplate,
418
+ rootClaudeTemplate,
419
+ operatorReadmeTemplate,
420
+ researchCommand,
421
+ });
314
422
  }
315
423
 
316
424
  /**
@@ -321,6 +429,13 @@ export async function buildPlan(config) {
321
429
  export function buildPlanFromTemplates(config, templates) {
322
430
  const { paName } = config;
323
431
  const claudeMd = renderClaudeMd(templates.claudeTemplate, config);
432
+ // Root-CLAUDE.md is a short pointer to the full agent file. Falling
433
+ // back to the agent file when the pointer template is absent keeps
434
+ // pure-plan tests that only pass `claudeTemplate` working, while the
435
+ // real buildPlan() path always supplies both.
436
+ const rootClaudeMd = templates.rootClaudeTemplate
437
+ ? renderRootClaudeMd(templates.rootClaudeTemplate, config)
438
+ : claudeMd;
324
439
  const readmeMd = renderOperatorReadme(templates.operatorReadmeTemplate, config);
325
440
  const pkg = buildOperatorPackageJson(config);
326
441
  const gitignore = buildGitignore();
@@ -348,17 +463,36 @@ export function buildPlanFromTemplates(config, templates) {
348
463
  'projects',
349
464
  'schedules',
350
465
  '.vault',
466
+ '.claude',
467
+ '.claude/commands',
351
468
  ];
352
469
 
353
470
  const plan = [];
354
471
  for (const d of dirs) plan.push({ kind: 'dir', path: d });
355
472
 
356
- plan.push({ kind: 'file', path: 'CLAUDE.md', contents: claudeMd });
473
+ plan.push({ kind: 'file', path: 'CLAUDE.md', contents: rootClaudeMd });
357
474
  plan.push({ kind: 'file', path: 'README.md', contents: readmeMd });
358
475
  plan.push({ kind: 'json', path: 'package.json', contents: pkg });
359
476
  plan.push({ kind: 'file', path: '.gitignore', contents: gitignore });
360
477
  plan.push({ kind: 'file', path: '.nvmrc', contents: '24\n' });
361
478
 
479
+ plan.push({ kind: 'json', path: '.claude/settings.json', contents: buildClaudeSettingsJson() });
480
+ // /research slash command: rendered from the packaged core doc so the
481
+ // command a colleague gets is exactly what the platform ships. The scaffold
482
+ // never re-authors it, and there is no template to drift.
483
+ if (templates.researchCommand) {
484
+ plan.push({
485
+ kind: 'file',
486
+ path: '.claude/commands/research.md',
487
+ contents: templates.researchCommand,
488
+ });
489
+ }
490
+ plan.push({
491
+ kind: 'json',
492
+ path: '.claude/coordinator-overlay.json',
493
+ contents: buildCoordinatorOverlayJson(),
494
+ });
495
+
362
496
  plan.push({ kind: 'file', path: 'operator/profile/profile.md', contents: profile });
363
497
  plan.push({ kind: 'json', path: 'operator/knowledge/domains.json', contents: domains });
364
498
  plan.push({ kind: 'json', path: 'operator/knowledge/index.json', contents: knowledgeIndex });
@@ -10,7 +10,7 @@ You are a colleague, not a servant. You have opinions and you voice them -- with
10
10
 
11
11
  Your long-term goal is to learn {OPERATOR_NAME}'s judgement so thoroughly that you can operate autonomously on their behalf -- making decisions, managing tasks, running delegated work -- without needing to ask. Every interaction is training data. The measure of progress: how often can you act without escalating? Every question you have to ask that you could have answered is a gap.
12
12
 
13
- **PA operating mode — dispatch-first. This is the defining posture; re-read it every boot.** Your main thread exists for three things only: (1) orchestrating work, (2) keeping the work-trail current (work items, projects, spawn-log, journal, staging), and (3) interacting with {OPERATOR_NAME}. **ALL substantive work goes into a dispatch** — a subagent with a full 8-section brief. Research, writing, code, analysis, multi-file reads, anything that produces a work product: dispatched, not done inline. You lead the team by delegating, not by doing. Keeping the main thread clean is what keeps you available to {OPERATOR_NAME} and stops you burning context on work you could have handed off. The narrow inline exceptions (a one-line edit, a single file read, a status answer) are enumerated in Bucket 3 — treat them as the exception, never the reflex. When unsure: dispatch.
13
+ **PA operating mode. Dispatch-first. This is the defining posture; re-read it every boot.** Your main thread exists for three things only: (1) orchestrating work, (2) keeping the work-trail current (work items, projects, spawn-log, journal, staging), and (3) interacting with {OPERATOR_NAME}. **ALL substantive work goes into a dispatch**: a subagent with a full 8-section brief. Research, writing, code, analysis, multi-file reads, anything that produces a work product: dispatched, not done inline. You lead the team by delegating, not by doing. Keeping the main thread clean is what keeps you available to {OPERATOR_NAME} and stops you burning context on work you could have handed off. The narrow inline exceptions (a one-line edit, a single file read, a status answer) are enumerated in Bucket 3. Treat them as the exception, never the reflex. When unsure: dispatch.
14
14
 
15
15
  **Autonomy envelope.** Per-task-type approval state lives at `agents/{PA_NAME}/autonomy-envelope.md`. Three states: `fullyApproved` (act, don't ask), `checkBeforeCommitting` (draft, get sign-off before durable action), `needsFullSupervision` (do not act; escalate every step). {OPERATOR_NAME} promotes or demotes at any time via `pa autonomy set`. The envelope is the durable record; your judgement calibrates day-to-day, but the envelope is what you check when the reflex is unclear. See `@stravica-ai/engineering-pa-core/docs/autonomy-envelope-tracker.md`.
16
16
 
@@ -193,6 +193,6 @@ Stage observations, update journal, update work items, update spawn-log outcomes
193
193
 
194
194
  All paths are relative to the operator repo root. Resolve via `.session/environment.json:workingDirectory.projectRoot` or a `*_ROOT` env var, never hard-code absolutes.
195
195
 
196
- Symbolic `@stravica-ai/engineering-pa-core/<subpath>` references resolve on disk to `node_modules/@stravica-ai/digital-operator-pa/dist/engineering-pa-core/<subpath>` — the internal packages ship bundled inside the wrapper package, not under their own names in `node_modules`.
196
+ Symbolic `@stravica-ai/engineering-pa-core/<subpath>` references resolve on disk to `node_modules/@stravica-ai/digital-operator-pa/dist/engineering-pa-core/<subpath>`. The internal packages ship bundled inside the wrapper package, not under their own names in `node_modules`.
197
197
 
198
198
  <!-- OPERATOR: add any operator-specific paths that are frequently referenced (a vault path, a scratchpad convention, an integration credentials store). -->
@@ -1,8 +1,8 @@
1
- # {PA_NAME} — operator repo
1
+ # {PA_NAME}: operator repo
2
2
 
3
3
  Personal-assistant instance for {OPERATOR_NAME}, scaffolded with `pa-init`.
4
4
 
5
- This repo holds **only operator content** — your profile, knowledge, work items,
5
+ This repo holds **only operator content**: your profile, knowledge, work items,
6
6
  projects, agent run state, schedules, and secrets. The PA platform code is
7
7
  supplied by the `@stravica-ai/digital-operator-pa` npm package; you never edit it in
8
8
  place.
@@ -17,7 +17,7 @@ place.
17
17
  │ ├── profile/ # operator profile (distilled over time)
18
18
  │ ├── knowledge/ # domain-organised knowledge tree
19
19
  │ └── extensions/ # operator-private extensions (Phase 2+)
20
- ├── agents/{PA_NAME}/ # PA run folder — journal, staging, spawn-log
20
+ ├── agents/{PA_NAME}/ # PA run folder: journal, staging, spawn-log
21
21
  ├── work/ # work items (one JSON per item)
22
22
  ├── projects/ # projects (one folder per project)
23
23
  ├── schedules/ # scheduled-task definitions
@@ -28,7 +28,7 @@ place.
28
28
 
29
29
  ```bash
30
30
  pnpm install
31
- pnpm status # alias for `pa status` — boot-time sanity check
31
+ pnpm status # alias for `pa status`, a boot-time sanity check
32
32
  ```
33
33
 
34
34
  Then launch your PA via Claude Code in this repo; it reads `CLAUDE.md`
@@ -0,0 +1,13 @@
1
+ # {PA_NAME}
2
+
3
+ Personal assistant platform instance for {OPERATOR_NAME}. See `agents/{PA_NAME}/CLAUDE.md` for the full operating instructions. That file is the source of truth for how {PA_NAME} works and is the one Claude Code loads when you start a session from the agent directory.
4
+
5
+ ## Quick reference
6
+
7
+ - Work items: `work/w-YYYY-MM-DD-NNN.json`
8
+ - Projects: `projects/{id}/project.json`
9
+ - Operator content: `operator/`
10
+ - Agent run folder: `agents/{PA_NAME}/`
11
+ - Platform package: installed as an npm dependency (`@stravica-ai/digital-operator-pa`); invoke tooling via `pnpm exec <bin>` (`pa`, `desk`, `secrets`, `distill`, etc.)
12
+ - Workspace: `pnpm exec pa workspace start` then http://localhost:4200
13
+ - Onboarding guide: `node_modules/@stravica-ai/digital-operator-pa/docs/onboarding-solo.md`
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Home — Dave</title>
6
+ <title>Home</title>
7
7
  <script>(function(){try{var t=localStorage.getItem('dave.theme');document.documentElement.dataset.theme=(t==='light'||t==='dark')?t:'dark';}catch(_){document.documentElement.dataset.theme='dark';}})();</script>
8
8
  <link rel="stylesheet" href="/core/tools/workspace/app/assets/theme.css">
9
9
  <script src="/core/tools/workspace/app/assets/theme.js" defer></script>
@@ -503,11 +503,11 @@
503
503
  <!-- ═════════ SPARSE / FRESH FORK LAYOUT ═════════ -->
504
504
  <div class="sparse-layout">
505
505
  <div class="hero">
506
- <div class="logo">D</div>
506
+ <div class="logo">PA</div>
507
507
  <h1>Welcome. Your workspace is empty.</h1>
508
- <p>Dave is your personal assistant — a learned, on-repo AI colleague that tracks your projects, runs your team of sub-agents, and gets sharper the more you talk to it. There's nothing here yet because nothing's been set up. That takes about five minutes.</p>
508
+ <p>Your PA is a learned, on-repo AI colleague that tracks your projects, runs your team of sub-agents, and gets sharper the more you talk to it. There's nothing here yet because nothing's been set up. That takes about five minutes.</p>
509
509
  <a class="cta" href="/onboarding.html" target="_top">Start onboarding →</a>
510
- <a class="cta secondary" href="https://github.com/Stravica/dave" target="_blank" rel="noopener">Read the docs</a>
510
+ <a class="cta secondary" href="https://github.com/Stravica/digital-operator-pa" target="_blank" rel="noopener">Read the docs</a>
511
511
  </div>
512
512
 
513
513
  <div class="next-steps">
@@ -521,7 +521,7 @@
521
521
  <div class="step">
522
522
  <div class="idx">02 ○</div>
523
523
  <div>
524
- <div class="title">Tell Dave who you are <a class="go" href="/onboarding.html" target="_top">go →</a></div>
524
+ <div class="title">Tell your PA who you are <a class="go" href="/onboarding.html" target="_top">go →</a></div>
525
525
  <div class="desc">Name, role, skills, purpose. Five fields, two minutes. This populates your profile and configures your PA.</div>
526
526
  </div>
527
527
  </div>
@@ -529,14 +529,14 @@
529
529
  <div class="idx">03 ○</div>
530
530
  <div>
531
531
  <div class="title">Name your PA <a class="go" href="/onboarding.html" target="_top">go →</a></div>
532
- <div class="desc">The assistant has a name and a personality. Mine is Dave. Yours could be Jeeves, Max, Hal, whatever fits.</div>
532
+ <div class="desc">The assistant has a name and a personality. Yours could be Jeeves, Max, Hal, Alex, whatever fits.</div>
533
533
  </div>
534
534
  </div>
535
535
  <div class="step">
536
536
  <div class="idx">04 ○</div>
537
537
  <div>
538
538
  <div class="title">Open your first project <a class="go" onclick="nav('/projects.html')">go →</a></div>
539
- <div class="desc">Once onboarded, create a project. Dave will track it, open work items against it, and route dispatches to specialists.</div>
539
+ <div class="desc">Once onboarded, create a project. Your PA will track it, open work items against it, and route dispatches to specialists.</div>
540
540
  </div>
541
541
  </div>
542
542
  <div class="step">
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Welcome to Dave</title>
6
+ <title>Welcome to your PA</title>
7
7
  <script>(function(){try{var t=localStorage.getItem('dave.theme');document.documentElement.dataset.theme=(t==='light'||t==='dark')?t:'dark';}catch(_){document.documentElement.dataset.theme='dark';}})();</script>
8
8
  <link rel="stylesheet" href="/core/tools/workspace/app/assets/theme.css">
9
9
  <script src="/core/tools/workspace/app/assets/theme.js" defer></script>
@@ -58,7 +58,7 @@
58
58
  <div id="global-banner"></div>
59
59
  <div class="onboard-card">
60
60
  <div class="logo">D</div>
61
- <h1>Welcome to Dave</h1>
61
+ <h1>Welcome to your PA</h1>
62
62
  <p class="description">Let's set up your personal assistant. This takes about a minute.</p>
63
63
  <form id="onboard-form" autocomplete="off">
64
64
  <div class="form-group">
@@ -84,7 +84,7 @@
84
84
  <hr class="divider">
85
85
  <div class="form-group">
86
86
  <label class="form-label">Name your PA <span class="required">*</span></label>
87
- <input type="text" id="pa-name" name="paName" required value="Dave" placeholder="e.g. Alex, Sam, Max">
87
+ <input type="text" id="pa-name" name="paName" required placeholder="e.g. Alex, Sam, Max">
88
88
  </div>
89
89
  <div class="form-group">
90
90
  <label class="form-label">Communication style</label>
@@ -567,7 +567,7 @@
567
567
  role: document.getElementById('owner-role').value.trim(),
568
568
  skills: document.getElementById('owner-skills').value.trim(),
569
569
  purpose: document.getElementById('owner-goals').value.trim(),
570
- paName: document.getElementById('pa-name').value.trim() || 'Dave',
570
+ paName: document.getElementById('pa-name').value.trim(),
571
571
  communicationStyle: cs === 'custom' ? document.getElementById('custom-style').value.trim() || 'custom' : cs,
572
572
  taskManagement: tt === 'other' ? document.getElementById('other-tracker').value.trim() || 'other' : tt,
573
573
  };
@@ -37,7 +37,7 @@ export function handleApi(req, res, url, repoRoot, deps = {}) {
37
37
  // changes) instead of silently skipping.
38
38
  if (method === 'GET' && pathname === '/__api/identity') {
39
39
  sendJson(res, 200, {
40
- server: 'dave-workspace',
40
+ server: 'digital-operator-pa-workspace',
41
41
  repoRoot: repoRoot,
42
42
  pid: process.pid,
43
43
  startedAt: SERVER_STARTED_AT,
@@ -644,7 +644,7 @@ if (isMainModule) (async function () {
644
644
  if (!IS_LOOPBACK_BIND) {
645
645
  warnAlways('[workspace] WARNING: bound to ' + host + ':' + port + ' — reachable from other hosts. Set WORKSPACE_HOST=127.0.0.1 or omit --host to restore loopback-only.');
646
646
  }
647
- log('[workspace] Dave Workspace running at ' + url + ' (bind ' + host + ')');
647
+ log('[workspace] Workspace running at ' + url + ' (bind ' + host + ')');
648
648
  log('[workspace] Serving from: ' + REPO_ROOT);
649
649
  if (EXT_DIR) log('[workspace] Extensions: ' + EXT_DIR.replace(REPO_ROOT + '/', ''));
650
650
  log('[workspace] Idle timeout: ' + (noTimeout ? 'disabled (persistent)' : timeoutMinutes + ' minutes'));
@@ -0,0 +1,78 @@
1
+ # Installing `@stravica-ai/digital-operator-pa`
2
+
3
+ `@stravica-ai/digital-operator-pa` is published to the **public npm registry**
4
+ (`registry.npmjs.org`). It is a public package, so **no registry authentication is
5
+ required to install it**: a plain `pnpm add` works on any host.
6
+
7
+ ## Prerequisites
8
+
9
+ - **Node.js 24+** (current active LTS).
10
+ - **pnpm 10+** (the wrapper is tested with pnpm but `npm`/`yarn` also work).
11
+
12
+ No PAT, `~/.npmrc`, or org-membership step is needed for install. (The `@stravica-ai`
13
+ scope resolves to npmjs.org by default; you only need an `~/.npmrc` entry if you have
14
+ previously pointed that scope somewhere else.)
15
+
16
+ ## Step 1: install in a project
17
+
18
+ In your operator-repo (or a fresh directory):
19
+
20
+ ```sh
21
+ pnpm add @stravica-ai/digital-operator-pa
22
+ ```
23
+
24
+ Smoke-test:
25
+
26
+ ```sh
27
+ pnpm exec pa launch --help # exit 0
28
+ pnpm exec pa --help # exit 0
29
+ pnpm exec desk --help # exit 0
30
+ ```
31
+
32
+ ## What the wrapper ships
33
+
34
+ `@stravica-ai/digital-operator-pa` is a **single-bundled** package. One install gives
35
+ you:
36
+
37
+ - All operator-facing bins: `pa`, `desk`, `launch`, `estate-sync`, `sync`, `secrets`,
38
+ `scheduler`, `smoke`, `distill`, `memory-sync`, `migrate-inspect`, `pa-init`,
39
+ `slice`, `research`, `pa-coordinator-hook`.
40
+ - All internal platform code (core spine, runbook validator, workspace server,
41
+ scaffold templates, role packs, optional core-extensions), bundled inside
42
+ the tarball at `dist/<package-name>/`. The internal packages stay
43
+ `private: true` in the monorepo and are never individually published.
44
+
45
+ ## Troubleshooting
46
+
47
+ - **`404 Not Found`**: usually the `@stravica-ai` scope is routed to the wrong
48
+ registry. Confirm you do **not** have a stale
49
+ `@stravica-ai:registry=https://npm.pkg.github.com` line in your `~/.npmrc`; the
50
+ scope should resolve to `https://registry.npmjs.org` (the default). Older setups
51
+ pointed this scope at GitHub Packages. Remove that line.
52
+ - **`Could not resolve dependency` for `@stravica-ai/engineering-pa-core`**
53
+ (or any other `engineering-pa-*` internal). The wrapper bundles those
54
+ internally and does not declare them as runtime deps; you should never
55
+ see this in normal use. If it appears, the wrapper's `dist/` was likely
56
+ stripped during install. Re-run `pnpm add @stravica-ai/digital-operator-pa`
57
+ with `--force`.
58
+
59
+ > **Historical note.** The predecessor package `@stravica/engineering-pa` lived on
60
+ > **GitHub Packages** and needed a `read:packages` PAT. The current
61
+ > `@stravica-ai/digital-operator-pa` bundle is public on npmjs.org, so that auth step
62
+ > no longer applies.
63
+
64
+ ## Release pipeline (for maintainers)
65
+
66
+ Publishing is **manual**, from `packages/engineering-pa`, and targets npmjs.org via the
67
+ package's `publishConfig` (`registry.npmjs.org`, `access: public`):
68
+
69
+ ```sh
70
+ cd packages/engineering-pa
71
+ pnpm publish # runs the prepack build.mjs, then publishes the bundled tarball
72
+ ```
73
+
74
+ `ci.yml`'s `dry-publish` job runs `pnpm dry-publish` (`build.mjs` + `pnpm publish
75
+ --dry-run`) on every push to prove the pack/publish mechanics, and a follow-up job
76
+ re-installs the packed tarball into a clean consumer directory and exercises the bins.
77
+ The actual publish is run by a maintainer with npmjs publish rights once CI is green
78
+ on `main`.
@@ -0,0 +1,111 @@
1
+ # Onboarding: solo PA
2
+
3
+ Ten minutes end to end. This guide takes you from an empty directory to a working single-person PA on your own laptop, running under your own Claude Code subscription.
4
+
5
+ ## 0. Prerequisites
6
+
7
+ You need Node.js 24 or newer, pnpm, git, and the Claude Code CLI signed in to your own subscription. macOS example:
8
+
9
+ ```sh
10
+ brew install node@24 pnpm git
11
+ sudo npm install -g @anthropic-ai/claude-code # or: curl -fsSL https://claude.ai/install.sh | sh
12
+ claude # follow the interactive login, then Ctrl-C once you see the prompt
13
+ ```
14
+
15
+ Linux and WSL are equivalent. Install Node 24 through your platform's normal channel.
16
+
17
+ ## 1. Scaffold the PA
18
+
19
+ ```sh
20
+ mkdir ~/pa-bootstrap && cd ~/pa-bootstrap
21
+ pnpm init -y
22
+ pnpm add @stravica-ai/digital-operator-pa
23
+ pnpm exec pa-init --mode=solo --name=<pa-name> --operator=<your-name> \
24
+ --target=$HOME/<pa-name>-instance --non-interactive
25
+ cd $HOME/<pa-name>-instance
26
+ pnpm install
27
+ git add -A && git commit -m "scaffold"
28
+ ```
29
+
30
+ Pick a `<pa-name>` in lowercase kebab-case (`alex`, `sam`, `hal-9000`). It becomes the agent directory (`agents/<pa-name>/`) and shows up in every log line.
31
+
32
+ ## 2. Sanity-check the install
33
+
34
+ ```sh
35
+ pnpm exec pa environment
36
+ pnpm exec pa status
37
+ pnpm exec pa knowledge context # first line: library.mode = simple (variant token: simple)
38
+ ```
39
+
40
+ `pa environment` populates `.session/environment.json` with the machine's Node, pnpm, git, and workspace state. `pa status` prints the installed platform version. `pa knowledge context` confirms the local library is in SIMPLE mode (no remote services).
41
+
42
+ ## 3. Start the workspace
43
+
44
+ ```sh
45
+ pnpm exec pa workspace start # opens http://localhost:4200
46
+ ```
47
+
48
+ The workspace serves a viewer, a home page, and an onboarding form. Long notes from your PA land here rather than in chat.
49
+
50
+ ## 4. Start your first session
51
+
52
+ ```sh
53
+ pnpm exec pa session
54
+ ```
55
+
56
+ That changes directory into `agents/<pa-name>/` and execs `claude`. Your PA reads its own `CLAUDE.md`, the operator profile, and the autonomy envelope, then greets you.
57
+
58
+ ## 5. First project and first work item
59
+
60
+ Inside the session, ask your PA to open a project. It will call `pa project create` and `pa work create` on your behalf. If you would rather run them yourself:
61
+
62
+ ```sh
63
+ pnpm exec pa project create my-first-project --name "..." --category chore
64
+ pnpm exec pa work create --title "..."
65
+ pnpm exec desk overview # read-only view of what is in flight
66
+ ```
67
+
68
+ ## What you get
69
+
70
+ - A generic personal-assistant operating model rendered into your own `agents/<pa-name>/CLAUDE.md` (with a short root pointer at `CLAUDE.md`). Seven buckets, dispatch-first, autonomy envelope.
71
+ - The `pa` CLI: `status`, `session`, `workspace`, `project`, `work`, `knowledge`, `research`, `autonomy`, `environment`, `agent`, `lint`, `launch`, `gsc`.
72
+ - The read-only `desk` CLI: overview, today, projects, work.
73
+ - A local workspace server on `http://localhost:4200`.
74
+ - A SIMPLE-mode local knowledge library: `pa knowledge search / related / domain / orphans / path / context`, seeded with the five base domains.
75
+ - Self-learning loop primitives: `agents/<pa-name>/staging/`, `journal.md`, `next-session.md`, `spawn-log.json`, autonomy envelope, and the Librarian distillation sweep via `pnpm exec distill run`.
76
+ - The `research` CLI with the light / normal / deep session store persisted under `.cache/research/`.
77
+ - Scheduler (cron on Linux, launchd on macOS): `pnpm exec scheduler --help`.
78
+ - Secrets vault (SOPS + age) if you opt in: `pnpm exec secrets --help`.
79
+ - `.claude/settings.json` with the `pa-coordinator-hook` wired in as a `PreToolUse` hook (inert until you export `PA_COORDINATOR_MODE=1`) and `deep-research` denied at the permission layer (the CLAUDE.md points you at the `/research` verb instead, which persists a session and promotes durable answers back into your library).
80
+ - The `/research` slash command scaffolded to `.claude/commands/research.md`, rendered from the bundled core doc, so the verb is directly available in your PA's Claude Code session.
81
+
82
+ ## What is not included in solo mode
83
+
84
+ - **`SessionStart` boot-context hook.** In some estates a `SessionStart` hook injects a live workState block (a desk overview tail, spawn-log tail, distillation health) at the top of every session. That hook is not in this package. If you want it, write your own `SessionStart` hook in `.claude/settings.json`. The coordinator-hook doc at `node_modules/@stravica-ai/digital-operator-pa/dist/engineering-pa-cli/docs/coordinator-hook.md` shows the settings.json shape.
85
+ - **Team modes.** `pa-init --mode=lead` and `--mode=member` exit with "not implemented". The SIMPLE-mode local library is single-operator by design. When team mode lands, the migration will be a fresh install with a knowledge / extension / vault import, not an in-place upgrade of a solo install.
86
+ - **Remote knowledge library.** The `remote` library mode requires a service on a persistent host, an age keypair, and a tunnel. Solo mode stays SIMPLE and runs entirely on your one laptop.
87
+ - **HQ-specialised roles.** The bundled role set is the core seven (`pa`, `agent-ops`, `dispatch-briefer`, `librarian`, `system-admin`, `tool-developer`, `writer`) plus `product-engineer` from the engineering types pack. Other tier-ladder roles (`web-developer`, `rcf-lite-engineer`, `rcf-engineer`) and estate-specific extensions like `site-cloner`, `seo-*`, `infographic-designer`, `linkedin-writer` are not shipped.
88
+ - **Content publishing tool, Cloudflare / GSC live integrations, cross-host memory sync.** Out of scope for solo. Those all assume a multi-machine estate.
89
+
90
+ ## Known first-run friction
91
+
92
+ - **`LIBRARY_KNOWLEDGE_EXTRA_ROOTS`.** If this env var is set in your shell (unlikely on a fresh laptop), unset it before running `pa knowledge`. Set, it silently merges other knowledge trees into your local graph.
93
+ - **`pa workspace stop`** on a machine that had the workspace daemon installed refuses and points you at the `launchctl unload` or `systemctl --user stop` command in its own error message. `pa workspace restart` is the intended path.
94
+ - **`pa work create --status planned` is ignored on create.** The item lands as `draft`. Use `pa work status <id> planned` as a second step.
95
+ - **Start sessions via `pnpm exec pa session`.** The coordinator hook (`pa-coordinator-hook`) is wired into `.claude/settings.json` as a bare bin name. `pnpm exec pa session` prepends `node_modules/.bin` to `PATH` before launching `claude`, which resolves the hook cleanly. If you launch `claude` directly from `agents/<pa-name>/` without `pnpm exec` in front, the hook resolves to nothing (silent no-op, safe but inert). Prefer the `pa session` entry point, or alias it as your PA name.
96
+ - **CLAUDE.md updates.** Every `pnpm update @stravica-ai/digital-operator-pa` may bring platform operating-model changes into the CLAUDE.md template. The scaffold rendered your CLAUDE.md once, at `pa-init` time; subsequent template updates do not overwrite your file. Pin the package version and read the CHANGELOG before you upgrade.
97
+
98
+ ## Where things live
99
+
100
+ | What | Where |
101
+ |---|---|
102
+ | Root pointer | `CLAUDE.md` |
103
+ | Full operating instructions | `agents/<pa-name>/CLAUDE.md` |
104
+ | Operator profile | `operator/profile/profile.md` |
105
+ | Preferences | `operator/config/preferences.json` |
106
+ | Autonomy envelope | `agents/<pa-name>/autonomy-envelope.md` |
107
+ | Work items | `work/w-YYYY-MM-DD-<author>-NNN.json` (<author> is your PA name, e.g. `w-2026-09-16-alex-001`) |
108
+ | Projects | `projects/{id}/project.json` |
109
+ | Session environment | `.session/environment.json` |
110
+ | Claude Code settings | `.claude/settings.json` |
111
+ | Coordinator-hook overlay | `.claude/coordinator-overlay.json` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stravica-ai/digital-operator-pa",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "description": "Digital Operator PA — single-bundled public package surface (bins + library) for the platform.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
@@ -30,6 +30,7 @@
30
30
  "index.mjs",
31
31
  "bin",
32
32
  "dist",
33
+ "docs",
33
34
  "templates",
34
35
  "README.md",
35
36
  "LICENSE"