@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 +7 -2
- package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-taxonomy.md +1 -1
- package/dist/engineering-pa-core/knowledge/knowledge-memory/staging-and-observations.md +3 -3
- package/dist/engineering-pa-scaffold/src/generator.mjs +136 -2
- package/dist/engineering-pa-scaffold/templates/CLAUDE.md.template +2 -2
- package/dist/engineering-pa-scaffold/templates/operator-README.md.template +4 -4
- package/dist/engineering-pa-scaffold/templates/root-CLAUDE.md.template +13 -0
- package/dist/engineering-pa-workspace/app/home.html +7 -7
- package/dist/engineering-pa-workspace/app/onboarding.html +4 -4
- package/dist/engineering-pa-workspace/src/api.mjs +1 -1
- package/dist/engineering-pa-workspace/src/server.mjs +1 -1
- package/docs/installing.md +78 -0
- package/docs/onboarding-solo.md +111 -0
- package/package.json +2 -1
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 [
|
|
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 [
|
|
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.
|
|
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` —
|
|
44
|
+
> `20260705T100000Z_preference.md` — operator likes short posts.
|
|
45
45
|
|
|
46
46
|
Good observation:
|
|
47
|
-
> `
|
|
48
|
-
> Task: drafting a
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
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}
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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">
|
|
506
|
+
<div class="logo">PA</div>
|
|
507
507
|
<h1>Welcome. Your workspace is empty.</h1>
|
|
508
|
-
<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/
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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()
|
|
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: '
|
|
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]
|
|
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.
|
|
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"
|