@stravica-ai/digital-operator-pa 0.1.23 → 0.1.26

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stravica-ai/engineering-pa-cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.5",
4
4
  "description": "Operator-facing CLIs — pa, secrets, scheduler, sync, smoke, launch.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
@@ -49,6 +49,11 @@ Usage:
49
49
  and the excluded amount is shown.
50
50
  [--exclude-stubs] Skip null-domain nodes
51
51
  pa knowledge path <a> <b> Shortest path between two docs
52
+ pa knowledge context Print the effective CLAUDE.md rule
53
+ [--json] variants selected by \`library.mode\`
54
+ (remote-library spec §5.1, §5.2).
55
+ Refuses cleanly on structurally
56
+ invalid REMOTE config.
52
57
  pa knowledge eval [--fixture P] Score the retrieval eval set (hit@1/5,
53
58
  [--out D] orphan gauge, delta vs last run);
54
59
  [--full] persists to
@@ -93,6 +98,10 @@ export async function run(argv) {
93
98
  case 'domain': return await doDomain(rest);
94
99
  case 'orphans': return await doOrphans(rest);
95
100
  case 'path': return await doPath(rest);
101
+ case 'context': {
102
+ const { runContext } = await import('./context.mjs');
103
+ return await runContext(rest);
104
+ }
96
105
  case 'eval': {
97
106
  const { run: runEval } = await import('./eval.mjs');
98
107
  return await runEval(rest);
@@ -0,0 +1,274 @@
1
+ // context.mjs — `pa knowledge context` verb.
2
+ //
3
+ // Prints the CLAUDE.md rule variants that are LIVE for this session,
4
+ // selected by `library.mode` in the merged operator preferences.
5
+ //
6
+ // The two-mode switch is specified in the `@stravica-ai/remote-library`
7
+ // spec §5.1 and §5.2 (build items 14 + 15). Item 14 landed the wiring —
8
+ // `resolveLibraryConfig` + `getLibraryVariant` in `packages/core/src/
9
+ // library-config.mjs` — and the `plan.libraryVariant` seam on
10
+ // `buildSessionPlan`. Item 15 (this file, plus stravica-pa's CLAUDE.md
11
+ // variant markers) closes the loop: agents read the CLAUDE.md variants
12
+ // on boot and invoke `pa knowledge context` to know WHICH is live.
13
+ //
14
+ // Rule-variant TEXT is duplicated between this module and the operator
15
+ // repo's CLAUDE.md. Both sources cite spec §5.2 verbatim. The
16
+ // duplication is a feature: each stands alone; if one drifts, running
17
+ // `pa knowledge context` alongside CLAUDE.md flags the drift visually.
18
+ //
19
+ // Refuse-boot semantics (spec §5.1): a structurally invalid REMOTE
20
+ // config (mode="remote" with missing endpoint/key, or malformed key
21
+ // shape) surfaces the underlying `LibraryConfigError` on stderr and
22
+ // exits 1. `pa knowledge context` is deliberately usable as a
23
+ // diagnostic when the boot path itself is refusing to open — an
24
+ // operator can invoke it AFTER the `pa session` refusal to inspect
25
+ // exactly what the mode-resolver saw.
26
+ //
27
+ // Runtime unreachability of the remote endpoint is NOT surfaced here:
28
+ // this verb never performs a network call. That is deliberate — spec
29
+ // §5.1 rules runtime unreachability non-fatal at boot; probing here
30
+ // would drag the boot doctrine sideways.
31
+
32
+ import { LibraryConfigError, getLibraryVariant, resolveLibraryConfig } from '../../../engineering-pa-core/src/library-config.mjs';
33
+ import { readPreferences } from '../../../engineering-pa-core/src/preferences.mjs';
34
+
35
+ import { getRepoRoot } from '../pa/repo-root.mjs';
36
+
37
+ // --- rule-variant text (spec §5.2 verbatim) ------------------------------
38
+ //
39
+ // Every entry mirrors an existing rule in the operator's
40
+ // `agents/<paName>/CLAUDE.md` under Bucket 4 (Knowledge & memory).
41
+ // `bucket` + `ruleNumber` + `ruleTitle` let the JSON envelope be indexed
42
+ // against the CLAUDE.md file without string-matching the file body.
43
+ // `simple` is the historic wording; the REMOTE deltas come from
44
+ // remote-library spec §5.2.
45
+ export const RULE_VARIANTS = [
46
+ {
47
+ bucket: 4,
48
+ ruleNumber: 2,
49
+ ruleTitle: 'Repo is single source of truth',
50
+ simple: 'Markdown for human-readable, JSON for machine-readable indexes.',
51
+ remote: 'The write path is `library put`. The pulled repo is a read-only projection of the event log. Never edit files inside library repos directly; write via `library put`.',
52
+ },
53
+ {
54
+ bucket: 4,
55
+ ruleNumber: 7,
56
+ ruleTitle: 'The Librarian sweeps staging during distillation',
57
+ simple: 'Each agent stages to its own staging dir; the Librarian routes observations to canonical destinations. Don\'t route observations directly.',
58
+ remote: '`library flush` sweeps local staging into the event log. The service applies the events to the git projection.',
59
+ },
60
+ ];
61
+
62
+ const USAGE = `pa knowledge context — print the effective CLAUDE.md rule variants for this session
63
+
64
+ Usage:
65
+ pa knowledge context Print the live rule variants (human-readable)
66
+ pa knowledge context --format json Emit the same envelope as JSON
67
+
68
+ The variant is selected by \`library.mode\` in the merged operator preferences
69
+ (base file + preferences.local.json overlay). Absent field defaults to "simple"
70
+ per spec §5.1.
71
+
72
+ A structurally invalid REMOTE config (mode="remote" with missing endpoint or
73
+ key, or a malformed key shape) is REFUSED here with the same message the
74
+ \`pa session\` boot path uses — this verb is safe to run as a diagnostic when
75
+ \`pa session\` itself is refusing to open.
76
+
77
+ Runtime endpoint unreachability is not probed here (spec §5.1: runtime
78
+ unreachability is non-fatal at boot; individual \`library\` verbs fail closed
79
+ and alert).
80
+
81
+ Exit codes (tooling standard §6):
82
+ 0 ok | 1 usage/config error | 2 unexpected internal failure
83
+ `;
84
+
85
+ /**
86
+ * Build the envelope for the resolved library variant. Pure: takes an
87
+ * already-resolved config plus the resolved paName, returns the
88
+ * printable / JSON-emittable shape.
89
+ *
90
+ * `paName` is the boot-resolved operator name (from merged preferences,
91
+ * same source `buildSessionPlan` uses). When null (diagnostic call with
92
+ * absent preferences), the rendered path degrades to the `<paName>`
93
+ * placeholder so the diagnostic still emits without lying about which
94
+ * operator's file the variants target.
95
+ *
96
+ * @param {{mode: 'simple'|'remote', remoteEndpoint?: string, remoteKey?: string}} config
97
+ * @param {{paName?: string|null}} [opts]
98
+ * @returns {{
99
+ * verb: 'context',
100
+ * libraryMode: 'simple'|'remote',
101
+ * libraryVariant: 'simple'|'remote',
102
+ * remoteEndpoint: string|null,
103
+ * paName: string|null,
104
+ * agentClaudePath: string,
105
+ * ruleVariants: Array<{bucket:number, ruleNumber:number, ruleTitle:string, effective:string, mode:'simple'|'remote'}>,
106
+ * specReference: string,
107
+ * }}
108
+ */
109
+ export function buildContextEnvelope(config, opts = {}) {
110
+ const variant = getLibraryVariant(config);
111
+ const paName = typeof opts.paName === 'string' && opts.paName.length > 0
112
+ ? opts.paName
113
+ : null;
114
+ const agentClaudePath = `agents/${paName ?? '<paName>'}/CLAUDE.md`;
115
+ return {
116
+ verb: 'context',
117
+ libraryMode: config.mode,
118
+ libraryVariant: variant,
119
+ remoteEndpoint: config.mode === 'remote' ? config.remoteEndpoint : null,
120
+ paName,
121
+ agentClaudePath,
122
+ ruleVariants: RULE_VARIANTS.map((r) => ({
123
+ bucket: r.bucket,
124
+ ruleNumber: r.ruleNumber,
125
+ ruleTitle: r.ruleTitle,
126
+ effective: variant === 'remote' ? r.remote : r.simple,
127
+ mode: variant,
128
+ })),
129
+ specReference: '@stravica-ai/remote-library spec §5.1 (mode switch), §5.2 (rule variants)',
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Human-readable renderer. Emits one block per rule variant so an
135
+ * operator can eyeball which text is live.
136
+ * @param {ReturnType<typeof buildContextEnvelope>} envelope
137
+ * @returns {string}
138
+ */
139
+ export function formatContextTable(envelope) {
140
+ const lines = [];
141
+ lines.push(`library.mode = ${envelope.libraryMode} (variant token: ${envelope.libraryVariant})`);
142
+ if (envelope.libraryMode === 'remote') {
143
+ lines.push(`remoteEndpoint: ${envelope.remoteEndpoint}`);
144
+ }
145
+ lines.push('');
146
+ lines.push(`Effective CLAUDE.md rule variants (${envelope.agentClaudePath}, Bucket 4):`);
147
+ lines.push('');
148
+ for (const r of envelope.ruleVariants) {
149
+ lines.push(` Rule ${r.bucket}.${r.ruleNumber} — ${r.ruleTitle} [${r.mode}]`);
150
+ lines.push(` ${r.effective}`);
151
+ lines.push('');
152
+ }
153
+ lines.push(`Spec: ${envelope.specReference}`);
154
+ lines.push('');
155
+ return lines.join('\n');
156
+ }
157
+
158
+ // --- verb entry ---------------------------------------------------------
159
+
160
+ function parseFlags(args) {
161
+ const flags = {};
162
+ const positional = [];
163
+ for (let i = 0; i < args.length; i += 1) {
164
+ const a = args[i];
165
+ if (a === '-h' || a === '--help') { flags.help = true; continue; }
166
+ if (a === '--json') { flags.format = 'json'; continue; }
167
+ if (a === '--format') {
168
+ const peek = args[i + 1];
169
+ if (peek == null || peek.startsWith('--')) {
170
+ const err = new Error('--format requires an argument (table|json)');
171
+ err.exitCode = 1;
172
+ throw err;
173
+ }
174
+ flags.format = peek;
175
+ i += 1;
176
+ continue;
177
+ }
178
+ if (a.startsWith('--format=')) {
179
+ flags.format = a.slice('--format='.length);
180
+ continue;
181
+ }
182
+ positional.push(a);
183
+ }
184
+ if (positional.length > 0) {
185
+ const err = new Error(`unexpected argument: ${positional[0]}`);
186
+ err.exitCode = 1;
187
+ throw err;
188
+ }
189
+ if (flags.format != null && flags.format !== 'table' && flags.format !== 'json') {
190
+ const err = new Error(`unknown --format: ${flags.format} (expected table | json)`);
191
+ err.exitCode = 1;
192
+ throw err;
193
+ }
194
+ return flags;
195
+ }
196
+
197
+ /**
198
+ * Verb entrypoint. Seams allow tests to inject a fake preferences reader,
199
+ * fake repo-root resolver, and capture streams.
200
+ *
201
+ * @param {string[]} argv args after `context`
202
+ * @param {object} [seam]
203
+ * @param {() => Promise<string>} [seam.getRepoRoot]
204
+ * @param {(root:string) => Promise<object|null>} [seam.readPreferences]
205
+ * @param {NodeJS.WritableStream} [seam.stdout]
206
+ * @param {NodeJS.WritableStream} [seam.stderr]
207
+ */
208
+ export async function runContext(argv, seam = {}) {
209
+ const stdout = seam.stdout ?? process.stdout;
210
+ const stderr = seam.stderr ?? process.stderr;
211
+ const getRoot = seam.getRepoRoot ?? getRepoRoot;
212
+ const readPrefs = seam.readPreferences ?? readPreferences;
213
+
214
+ let flags;
215
+ try {
216
+ flags = parseFlags(argv);
217
+ } catch (err) {
218
+ stderr.write(`[pa knowledge context] ${err.message}\n`);
219
+ stderr.write(USAGE);
220
+ return err.exitCode ?? 1;
221
+ }
222
+
223
+ if (flags.help) {
224
+ stdout.write(USAGE);
225
+ return 0;
226
+ }
227
+
228
+ let repoRoot;
229
+ try {
230
+ repoRoot = await getRoot();
231
+ } catch (err) {
232
+ stderr.write(`[pa knowledge context] ${err.message ?? err}\n`);
233
+ return err.exitCode ?? 2;
234
+ }
235
+
236
+ let prefs;
237
+ try {
238
+ prefs = await readPrefs(repoRoot);
239
+ } catch (err) {
240
+ stderr.write(`[pa knowledge context] failed to read preferences at ${repoRoot}: ${err.message ?? err}\n`);
241
+ return 2;
242
+ }
243
+
244
+ let config;
245
+ try {
246
+ config = resolveLibraryConfig(prefs);
247
+ } catch (err) {
248
+ if (err instanceof LibraryConfigError) {
249
+ stderr.write(`[pa knowledge context] ${err.message}\n`);
250
+ return err.exitCode ?? 1;
251
+ }
252
+ stderr.write(`[pa knowledge context] ${err.message ?? err}\n`);
253
+ return 2;
254
+ }
255
+
256
+ // paName is the boot-resolved operator name. Sourced from the same
257
+ // merged preferences `buildSessionPlan` consumes — no new config, no
258
+ // second read. Absent prefs (readPreferences === null) keeps paName
259
+ // null and the envelope renders the `<paName>` placeholder so the
260
+ // diagnostic remains usable when the boot path itself is refusing.
261
+ const paName = (prefs && typeof prefs.paName === 'string' && prefs.paName.length > 0)
262
+ ? prefs.paName
263
+ : null;
264
+
265
+ const envelope = buildContextEnvelope(config, { paName });
266
+ if (flags.format === 'json') {
267
+ stdout.write(JSON.stringify(envelope, null, 2) + '\n');
268
+ } else {
269
+ stdout.write(formatContextTable(envelope));
270
+ }
271
+ return 0;
272
+ }
273
+
274
+ export { USAGE };
@@ -24,7 +24,7 @@ Usage:
24
24
  pa project <verb> Project state writes (create | status | doc add/rm | list)
25
25
  pa work <verb> Work-item state writes (create | status | list)
26
26
  pa gsc <verb> Google Search Console automation (add-property | verify-via-cf-dns | submit-sitemap | sitemap-status | pull-analytics | list-properties)
27
- pa knowledge <verb> Query the operator's knowledge graph (related | search | domain | orphans | path)
27
+ pa knowledge <verb> Query the operator's knowledge graph (related | search | domain | orphans | path | context)
28
28
  pa research <verb> Deep-research session store (run | list | show | gates | prune | mark | paths)
29
29
  pa autonomy <verb> Per-agent per-task-type approval state (init | get | set | list)
30
30
  pa environment [verb] Session-boot environment cache (default | refresh | extended)
@@ -22,6 +22,11 @@ import { spawn } from 'node:child_process';
22
22
  import { dirname, join, resolve } from 'node:path';
23
23
 
24
24
  import { mergePreferences } from '../../../engineering-pa-core/src/preferences.mjs';
25
+ import {
26
+ LibraryConfigError,
27
+ getLibraryVariant,
28
+ resolveLibraryConfig,
29
+ } from '../../../engineering-pa-core/src/library-config.mjs';
25
30
 
26
31
  /**
27
32
  * Resolve the operator repo root with the priority documented in the brief:
@@ -172,6 +177,28 @@ export async function buildSessionPlan(repoRoot, seam = {}) {
172
177
  );
173
178
  }
174
179
 
180
+ // Item 14: resolve the `library.*` block and select the CLAUDE.md
181
+ // rule-variant token. `resolveLibraryConfig` throws
182
+ // LibraryConfigError on mode=remote misconfiguration (spec §5.1 —
183
+ // refuse to boot the library subsystem, no silent fallback to
184
+ // SIMPLE). Item 15 will consume `libraryVariant` when it renders the
185
+ // effective CLAUDE.md and when `pa knowledge context` prints the
186
+ // resolved wording; the plan carries the token forward so item 15
187
+ // slots content in without changing the wiring here.
188
+ let libraryConfig;
189
+ try {
190
+ libraryConfig = resolveLibraryConfig(merged);
191
+ } catch (err) {
192
+ if (err instanceof LibraryConfigError) {
193
+ throw new SessionError(
194
+ `${err.message} (preferences at ${preferencesPath})`,
195
+ err.exitCode ?? 1,
196
+ );
197
+ }
198
+ throw err;
199
+ }
200
+ const libraryVariant = getLibraryVariant(libraryConfig);
201
+
175
202
  return {
176
203
  repoRoot,
177
204
  preferencesPath,
@@ -179,6 +206,8 @@ export async function buildSessionPlan(repoRoot, seam = {}) {
179
206
  agentDir,
180
207
  command: 'claude',
181
208
  args: ['--dangerously-skip-permissions'],
209
+ libraryConfig,
210
+ libraryVariant,
182
211
  };
183
212
  }
184
213
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stravica-ai/engineering-pa-core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Type-agnostic platform spine — desk CLI, distill, memory-sync, schemas, briefing-contract framework, knowledge engine, scheduler primitives.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
@@ -0,0 +1,122 @@
1
+ // library-config.mjs — resolve + validate the `library.*` block in
2
+ // operator preferences.
3
+ //
4
+ // This module supplies the READ + REFUSE-BOOT half of the two-mode
5
+ // switch specified in `@stravica-ai/remote-library` spec §5.1:
6
+ //
7
+ // - `library.mode` is EXPLICIT (`"simple"` | `"remote"`); never auto-
8
+ // detected. Absent defaults to `"simple"`.
9
+ // - `mode="remote"` with missing/empty `remoteEndpoint` or `remoteKey`
10
+ // REFUSES to boot the library subsystem — no silent fallback to
11
+ // SIMPLE (falling back is a data-loss path).
12
+ //
13
+ // This lands as a token-selection module for build item 14 (see the
14
+ // spec's work-item breakdown §11). The CLAUDE.md variant CONTENT and
15
+ // the `pa knowledge context` verb both key off `getLibraryVariant`
16
+ // and will land in item 15; the wiring here is stable so item 15 slots
17
+ // content into the existing shape without changing this file.
18
+ //
19
+ // The reader is DELIBERATELY pure — it consumes an already-merged
20
+ // preferences object. Callers pair it with `readPreferences` /
21
+ // `readPreferencesSync` from ./preferences.mjs so the overlay-aware
22
+ // path stays a single implementation.
23
+
24
+ /**
25
+ * Default when `library.mode` is absent from preferences.
26
+ * @type {"simple"|"remote"}
27
+ */
28
+ export const DEFAULT_LIBRARY_MODE = 'simple';
29
+
30
+ /**
31
+ * Set of accepted `library.mode` values (spec §5.1).
32
+ */
33
+ const VALID_MODES = new Set(['simple', 'remote']);
34
+
35
+ /**
36
+ * Sentinel raised on invalid `library.*` configuration. Carries a
37
+ * `code` for machine-consumer disambiguation and an `exitCode` so
38
+ * CLI wrappers can surface it without a switch.
39
+ */
40
+ export class LibraryConfigError extends Error {
41
+ /**
42
+ * @param {string} message
43
+ * @param {string} code e.g. 'invalid-mode' | 'remote-config-missing' | 'remote-key-shape'
44
+ * @param {number} [exitCode] defaults to 1 (usage / configuration error)
45
+ */
46
+ constructor(message, code, exitCode = 1) {
47
+ super(message);
48
+ this.name = 'LibraryConfigError';
49
+ this.code = code;
50
+ this.exitCode = exitCode;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Resolve the `library` block from a merged preferences object.
56
+ * Returns `{ mode }` for SIMPLE mode and
57
+ * `{ mode: 'remote', remoteEndpoint, remoteKey }` for REMOTE mode.
58
+ * Throws {@link LibraryConfigError} on invalid shape or on REMOTE
59
+ * mode with missing required fields.
60
+ *
61
+ * @param {object|null} preferences merged preferences (base + overlay)
62
+ * @returns {{mode: 'simple'|'remote', remoteEndpoint?: string, remoteKey?: string}}
63
+ */
64
+ export function resolveLibraryConfig(preferences) {
65
+ const raw =
66
+ preferences && typeof preferences === 'object' && !Array.isArray(preferences)
67
+ ? preferences.library
68
+ : null;
69
+ const block = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
70
+
71
+ const mode = block.mode ?? DEFAULT_LIBRARY_MODE;
72
+
73
+ if (!VALID_MODES.has(mode)) {
74
+ throw new LibraryConfigError(
75
+ `library.mode must be "simple" or "remote", got ${JSON.stringify(mode)}`,
76
+ 'invalid-mode',
77
+ );
78
+ }
79
+
80
+ if (mode === 'simple') {
81
+ return { mode };
82
+ }
83
+
84
+ // REMOTE mode — validate required fields (spec §5.1 refuse-boot).
85
+ const missing = [];
86
+ const endpoint = block.remoteEndpoint;
87
+ const key = block.remoteKey;
88
+ if (typeof endpoint !== 'string' || endpoint.trim() === '') missing.push('library.remoteEndpoint');
89
+ if (typeof key !== 'string' || key.trim() === '') missing.push('library.remoteKey');
90
+ if (missing.length > 0) {
91
+ throw new LibraryConfigError(
92
+ `library.mode="remote" but required field(s) missing/empty: ${missing.join(', ')}. ` +
93
+ `Refusing to boot the library subsystem (spec §5.1: no silent fallback to SIMPLE).`,
94
+ 'remote-config-missing',
95
+ );
96
+ }
97
+
98
+ // Cheap shape check on remoteKey (`<subkeyId>:<secret>`). The server
99
+ // does the authoritative check; catching a paste error early spares a
100
+ // network round-trip and a generic 401.
101
+ if (!/^[^:\s]+:[^\s]+$/.test(key)) {
102
+ throw new LibraryConfigError(
103
+ 'library.remoteKey must be of shape "<subkeyId>:<secret>" (no whitespace, colon separator).',
104
+ 'remote-key-shape',
105
+ );
106
+ }
107
+
108
+ return { mode, remoteEndpoint: endpoint, remoteKey: key };
109
+ }
110
+
111
+ /**
112
+ * Return the CLAUDE.md rule-variant token for a resolved library config.
113
+ * Item 15 keys off this string when composing the effective CLAUDE.md
114
+ * and when `pa knowledge context` prints the resolved wording.
115
+ *
116
+ * @param {{mode: 'simple'|'remote'}} config the value returned by resolveLibraryConfig
117
+ * @returns {'simple'|'remote'}
118
+ */
119
+ export function getLibraryVariant(config) {
120
+ const mode = config?.mode ?? DEFAULT_LIBRARY_MODE;
121
+ return mode === 'remote' ? 'remote' : 'simple';
122
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stravica-ai/engineering-pa-scaffold",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "pa-init scaffolder + onboarding flows (solo, lead, member).",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
@@ -184,6 +184,13 @@ export function buildPreferencesJson(config) {
184
184
  pa: { name: capitalise(config.paName), role: 'PA' },
185
185
  communicationStyle: config.communicationStyle,
186
186
  workspacePort: 4200,
187
+ // `@stravica-ai/remote-library` spec §5.1 — mode is EXPLICIT, never
188
+ // auto-detected. Fresh installs land on SIMPLE (single-operator, one
189
+ // local librarian sweep). Flipping to `"remote"` also requires
190
+ // `remoteEndpoint` and `remoteKey` (see spec §5.1); the `pa session`
191
+ // boot path refuses to launch when `mode="remote"` and either field
192
+ // is missing.
193
+ library: { mode: 'simple' },
187
194
  generatedAt: config.generatedAt,
188
195
  };
189
196
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stravica-ai/digital-operator-pa",
3
- "version": "0.1.23",
3
+ "version": "0.1.26",
4
4
  "description": "Digital Operator PA \u2014 single-bundled public package surface (bins + library) for the platform.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",