@ted-galago/wave-cli 0.1.19 → 0.1.22
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 +71 -2
- package/dist/index.cjs +265 -33
- package/dist/index.js +265 -33
- package/package.json +1 -1
- package/scripts/verify-dev-api.mjs +286 -0
package/README.md
CHANGED
|
@@ -120,6 +120,7 @@ wave markdown-tree resolve --tool-key projects --node-key tasks --parent-id 123
|
|
|
120
120
|
wave markdown-tree children --tool-key directory --node-key members --record-id 67
|
|
121
121
|
wave markdown-tree subtree --tool-key knowledge --node-key knowledge --content-type processes --depth 2
|
|
122
122
|
wave osmd tree
|
|
123
|
+
wave osmd search "Wave Tools" --scope combined --limit 10
|
|
123
124
|
wave osmd read "projects/Wave Tools"
|
|
124
125
|
wave osmd children "projects/Wave Tools"
|
|
125
126
|
wave osmd status "projects/Wave Tools/.agent/notes.md" --parent-ref "projects/Wave Tools"
|
|
@@ -132,6 +133,8 @@ wave osmd wiki read log.md
|
|
|
132
133
|
wave osmd wiki init
|
|
133
134
|
wave osmd wiki create index.md --content "# Agent Wiki"
|
|
134
135
|
wave osmd wiki update "Agent Wiki/index.md" --file ./agent-wiki-index.md
|
|
136
|
+
wave osmd wiki create "concepts/customer-health.md" --content "# Customer Health"
|
|
137
|
+
wave osmd wiki update "decisions/use-agent-wiki.md" --content "# Use Agent Wiki"
|
|
135
138
|
wave osmd wiki append-log --content "Observed durable event"
|
|
136
139
|
wave find "Ted"
|
|
137
140
|
wave open "Ted Martinez"
|
|
@@ -307,6 +310,7 @@ The `osmd` command group is the write-capable agent interface for canonical OSMD
|
|
|
307
310
|
Commands:
|
|
308
311
|
|
|
309
312
|
- `wave osmd tree [--depth <n>] [--tree-view]`
|
|
313
|
+
- `wave osmd search "<query>" [--scope os-only|agent-overlay-only|agent-wiki-only|combined] [--limit <n>]`
|
|
310
314
|
- `wave osmd read <path> [--parent-ref <canonicalPath>]`
|
|
311
315
|
- `wave osmd children [path] [--parent-ref <canonicalPath>] [--source canonical_osmd|agent_overlay|agent_wiki]`
|
|
312
316
|
- `wave osmd status <path> [--parent-ref <canonicalPath>]`
|
|
@@ -326,6 +330,7 @@ Commands:
|
|
|
326
330
|
GraphQL mapping:
|
|
327
331
|
|
|
328
332
|
- `osmd status` / `osmd agent status` / `osmd wiki status` -> `agentMarkdownStatus`
|
|
333
|
+
- `osmd search` -> `osMdSearch`
|
|
329
334
|
- `osmd read` / `osmd agent read` / `osmd wiki read` -> `agentMarkdownFile`
|
|
330
335
|
- `osmd children` / `osmd wiki children` -> `agentMarkdownChildren`
|
|
331
336
|
- `osmd agent init` -> `initAgentMarkdown`
|
|
@@ -342,13 +347,16 @@ Path and permission rules:
|
|
|
342
347
|
- `.agent` first slice supports only `notes.md`.
|
|
343
348
|
- `osmd agent init <parent-ref>` is idempotent for default `.agent` files.
|
|
344
349
|
- Agent Wiki index paths may be `index.md` or `Agent Wiki/index.md`; the CLI normalizes these to `Agent Wiki/index.md`.
|
|
350
|
+
- Controlled Agent Wiki page paths may be `concepts/<name>.md`, `playbooks/<name>.md`, `decisions/<name>.md`, `org-summaries/<name>.md`, or the same forms prefixed with `Agent Wiki/`.
|
|
345
351
|
- Agent Wiki log paths may be `log.md` or `Agent Wiki/log.md`; the CLI normalizes these to `Agent Wiki/log.md`.
|
|
346
|
-
- Agent Wiki
|
|
352
|
+
- Agent Wiki agents should use `index.md` for broad writable wiki memory, controlled folders for durable typed pages, and `log.md` for append-only event memory.
|
|
347
353
|
- Agent Wiki `init` initializes backend-owned system files, including append-only `log.md`, through `initAgentMarkdown` at path `Agent Wiki`.
|
|
348
|
-
- Agent Wiki `create` and `update` support
|
|
354
|
+
- Agent Wiki `create` and `update` support `index.md`, `concepts/*.md`, `playbooks/*.md`, `decisions/*.md`, and `org-summaries/*.md`; `log.md` cannot be created or overwritten by these commands.
|
|
349
355
|
- Agent Wiki `append-log` supports only `log.md` and calls status first before appending.
|
|
350
356
|
- The CLI uses backend GraphQL metadata directly and does not derive S3 paths, SHA paths, or backend storage conventions.
|
|
351
357
|
- Atlas should inspect `path`, `source`, `access`, `owner`, `parentRef`, `exists`, `canCreate`, `canUpdate`, `canAppend`, `wikiRole`, `formatVersion`, `suggestedAction`, and `errorCode`.
|
|
358
|
+
- `osmd search` scopes map to backend `source` values: `os-only` -> `canonical_osmd`, `agent-overlay-only` -> `agent_overlay`, `agent-wiki-only` -> `agent_wiki`, and `combined` -> backend merged search.
|
|
359
|
+
- `osmd search` returns backend candidates with `path`, `source`, `access`, `owner`, `wikiRole`, `formatVersion`, `parentRef`, `exists`, `agentChildrenAllowed`, `title`, `label`, `snippet`, `rank`, `matchReason`, `toolKey`, `nodeKey`, and `nodeKind` where the backend provides them.
|
|
352
360
|
- Reads never create files.
|
|
353
361
|
- Create/update/append-log flows call status first and inspect `exists`, `canCreate`, `canUpdate`, `canAppend`, `suggestedAction`, and `errorCode`.
|
|
354
362
|
- `create` fails when `exists` is true.
|
|
@@ -356,6 +364,7 @@ Path and permission rules:
|
|
|
356
364
|
- `append-log` fails unless status reports `exists: true`, `access: "append_only"`, and `canAppend: true`.
|
|
357
365
|
- When `Agent Wiki/log.md` is missing and status reports `suggestedAction: "init"`, `append-log` returns a JSON error telling Atlas to run `wave osmd wiki init`.
|
|
358
366
|
- Missing `Agent Wiki/index.md` is create-ready when status returns `exists: false`, `canCreate: true`, `canUpdate: false`, and `suggestedAction: "create"`.
|
|
367
|
+
- Missing controlled pages are create-ready when backend status returns `exists: false`, `canCreate: true`, `canUpdate: false`, and `suggestedAction: "create"`.
|
|
359
368
|
|
|
360
369
|
Atlas Agent Wiki log flow:
|
|
361
370
|
|
|
@@ -377,6 +386,22 @@ wave osmd wiki read index.md
|
|
|
377
386
|
wave osmd wiki update index.md --content "# Agent Wiki\n\n## Entity Notes\n\n- directory/Wave Tools Team -> .agent/notes.md"
|
|
378
387
|
```
|
|
379
388
|
|
|
389
|
+
Create or update controlled Agent Wiki pages. Atlas should call `status` first, then choose `create` or `update` from backend `canCreate`, `canUpdate`, and `suggestedAction`:
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
wave osmd wiki status concepts/customer-health.md
|
|
393
|
+
wave osmd wiki create concepts/customer-health.md --content "# Customer Health\n\nDurable definition and usage notes."
|
|
394
|
+
|
|
395
|
+
wave osmd wiki status decisions/use-agent-wiki.md
|
|
396
|
+
wave osmd wiki update decisions/use-agent-wiki.md --content "# Use Agent Wiki\n\nDecision: store broad agent memory in controlled Agent Wiki pages."
|
|
397
|
+
|
|
398
|
+
wave osmd wiki status playbooks/customer-review.md
|
|
399
|
+
wave osmd wiki create playbooks/customer-review.md --content "# Customer Review\n\n1. Read the customer summary.\n2. Review recent notes.\n3. Append the maintenance log."
|
|
400
|
+
|
|
401
|
+
wave osmd wiki status org-summaries/galago.md
|
|
402
|
+
wave osmd wiki update org-summaries/galago.md --content "# Galago\n\nCurrent durable organization summary."
|
|
403
|
+
```
|
|
404
|
+
|
|
380
405
|
Append a parseable log entry. Use a stable fenced block so Atlas or backend jobs can parse the chronology later:
|
|
381
406
|
|
|
382
407
|
````bash
|
|
@@ -429,6 +454,44 @@ OSMD command envelopes keep the global CLI envelope and put the file metadata di
|
|
|
429
454
|
}
|
|
430
455
|
```
|
|
431
456
|
|
|
457
|
+
Merged OSMD search keeps the same envelope and returns backend-ranked candidates:
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
{
|
|
461
|
+
"ok": true,
|
|
462
|
+
"command": "osmd.search",
|
|
463
|
+
"status": 200,
|
|
464
|
+
"data": {
|
|
465
|
+
"query": "Wave Tools",
|
|
466
|
+
"scope": "combined",
|
|
467
|
+
"count": 3,
|
|
468
|
+
"candidates": [
|
|
469
|
+
{
|
|
470
|
+
"path": "directory/Wave Tools Team/.agent/notes.md",
|
|
471
|
+
"source": "agent_overlay",
|
|
472
|
+
"access": "read_write",
|
|
473
|
+
"owner": "atlas",
|
|
474
|
+
"wikiRole": "notes",
|
|
475
|
+
"formatVersion": "agent_markdown_v1",
|
|
476
|
+
"parentRef": "directory/Wave Tools Team",
|
|
477
|
+
"exists": true,
|
|
478
|
+
"agentChildrenAllowed": false,
|
|
479
|
+
"title": "notes.md",
|
|
480
|
+
"label": "notes.md",
|
|
481
|
+
"snippet": "...",
|
|
482
|
+
"rank": 1,
|
|
483
|
+
"matchReason": "content",
|
|
484
|
+
"toolKey": "agent_overlay",
|
|
485
|
+
"nodeKey": "notes",
|
|
486
|
+
"nodeKind": "agent_overlay_file"
|
|
487
|
+
}
|
|
488
|
+
]
|
|
489
|
+
},
|
|
490
|
+
"error": null,
|
|
491
|
+
"meta": { "requestId": "req_125" }
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
432
495
|
On write preflight errors, `data` contains the status metadata and `error.suggestedAction` mirrors backend guidance:
|
|
433
496
|
|
|
434
497
|
```json
|
|
@@ -482,6 +545,12 @@ These wrap backend-owned markdown-tree primitives:
|
|
|
482
545
|
Discovery, ranking, canonical paths, and narrowing are backend-owned.
|
|
483
546
|
An empty `find` result (`candidates: []`) means no evidence for that exact query/scope, not confirmed global absence.
|
|
484
547
|
`markdownTreeFind` remains canonical-focused. Agent overlay and Agent Wiki files are discoverable through `osmd tree`, `osmd children`, and `osmd status`, not through `find`.
|
|
548
|
+
Use `wave osmd search "<query>" --scope combined` when Atlas needs merged canonical OSMD, `.agent`, and Agent Wiki search. Use narrower scopes for targeted memory lookup:
|
|
549
|
+
|
|
550
|
+
- `--scope os-only` searches canonical OSMD only.
|
|
551
|
+
- `--scope agent-overlay-only` searches entity-specific `.agent` files.
|
|
552
|
+
- `--scope agent-wiki-only` searches broad Agent Wiki files, including `index.md`, controlled pages, and append-only `log.md`.
|
|
553
|
+
- `--scope combined` searches the backend merged OSMD surface.
|
|
485
554
|
|
|
486
555
|
Ambiguity contract:
|
|
487
556
|
|
package/dist/index.cjs
CHANGED
|
@@ -6143,10 +6143,26 @@ var agentMarkdownErrorCodeSchema = import_zod16.z.enum([
|
|
|
6143
6143
|
var agentMarkdownErrorCodeFieldSchema = agentMarkdownErrorCodeSchema.nullable().catch(null);
|
|
6144
6144
|
var nonEmptyString3 = import_zod16.z.string().min(1);
|
|
6145
6145
|
var nonNegativeInt3 = import_zod16.z.coerce.number().int().min(0);
|
|
6146
|
+
var positiveInt = import_zod16.z.coerce.number().int().min(1);
|
|
6146
6147
|
var supportedAgentOverlayFile = "notes.md";
|
|
6147
6148
|
var supportedWikiIndexFile = "index.md";
|
|
6148
6149
|
var supportedWikiLogFile = "log.md";
|
|
6150
|
+
var supportedWikiControlledFolders = [
|
|
6151
|
+
"concepts",
|
|
6152
|
+
"playbooks",
|
|
6153
|
+
"decisions",
|
|
6154
|
+
"org-summaries"
|
|
6155
|
+
];
|
|
6156
|
+
var supportedWikiControlledPatterns = supportedWikiControlledFolders.map(
|
|
6157
|
+
(folder) => `${folder}/*.md`
|
|
6158
|
+
);
|
|
6149
6159
|
var agentOverlayFileSchema = import_zod16.z.enum([supportedAgentOverlayFile]);
|
|
6160
|
+
var osmdSearchScopeSchema = import_zod16.z.enum([
|
|
6161
|
+
"os-only",
|
|
6162
|
+
"agent-overlay-only",
|
|
6163
|
+
"agent-wiki-only",
|
|
6164
|
+
"combined"
|
|
6165
|
+
]);
|
|
6150
6166
|
var agentMarkdownFileSchema = import_zod16.z.object({
|
|
6151
6167
|
path: import_zod16.z.string(),
|
|
6152
6168
|
source: sourceSchema,
|
|
@@ -6178,6 +6194,47 @@ var agentMarkdownMutationDataSchema = import_zod16.z.union([
|
|
|
6178
6194
|
agentMarkdownFileSchema,
|
|
6179
6195
|
import_zod16.z.object({ files: agentMarkdownFilesSchema })
|
|
6180
6196
|
]);
|
|
6197
|
+
var osmdSearchCandidateSchema = import_zod16.z.preprocess(
|
|
6198
|
+
normalizeAgentMarkdownJsonKeys,
|
|
6199
|
+
import_zod16.z.object({
|
|
6200
|
+
path: import_zod16.z.string(),
|
|
6201
|
+
source: sourceSchema,
|
|
6202
|
+
access: accessSchema,
|
|
6203
|
+
owner: ownerSchema,
|
|
6204
|
+
wikiRole: import_zod16.z.string().nullable().optional(),
|
|
6205
|
+
formatVersion: import_zod16.z.string().nullable().optional(),
|
|
6206
|
+
parentRef: import_zod16.z.string().nullable().optional(),
|
|
6207
|
+
exists: import_zod16.z.boolean(),
|
|
6208
|
+
agentChildrenAllowed: import_zod16.z.boolean(),
|
|
6209
|
+
title: import_zod16.z.string(),
|
|
6210
|
+
label: import_zod16.z.string(),
|
|
6211
|
+
snippet: import_zod16.z.string().nullable().optional(),
|
|
6212
|
+
rank: import_zod16.z.number().int(),
|
|
6213
|
+
matchReason: import_zod16.z.string().nullable().optional(),
|
|
6214
|
+
toolKey: import_zod16.z.string().nullable().optional(),
|
|
6215
|
+
nodeKey: import_zod16.z.string().nullable().optional(),
|
|
6216
|
+
nodeKind: import_zod16.z.string().nullable().optional()
|
|
6217
|
+
}).transform((value) => ({
|
|
6218
|
+
...value,
|
|
6219
|
+
wikiRole: value.wikiRole ?? null,
|
|
6220
|
+
formatVersion: value.formatVersion ?? null,
|
|
6221
|
+
parentRef: value.parentRef ?? null,
|
|
6222
|
+
snippet: value.snippet ?? null,
|
|
6223
|
+
matchReason: value.matchReason ?? null,
|
|
6224
|
+
toolKey: value.toolKey ?? null,
|
|
6225
|
+
nodeKey: value.nodeKey ?? null,
|
|
6226
|
+
nodeKind: value.nodeKind ?? null
|
|
6227
|
+
}))
|
|
6228
|
+
);
|
|
6229
|
+
var osmdSearchResultSchema = import_zod16.z.preprocess(
|
|
6230
|
+
normalizeAgentMarkdownJsonKeys,
|
|
6231
|
+
import_zod16.z.object({
|
|
6232
|
+
query: import_zod16.z.string(),
|
|
6233
|
+
scope: import_zod16.z.string(),
|
|
6234
|
+
count: import_zod16.z.number().int().min(0),
|
|
6235
|
+
candidates: import_zod16.z.array(osmdSearchCandidateSchema)
|
|
6236
|
+
})
|
|
6237
|
+
);
|
|
6181
6238
|
var mutationPayloadSchema = import_zod16.z.object({
|
|
6182
6239
|
ok: import_zod16.z.boolean(),
|
|
6183
6240
|
status: import_zod16.z.number(),
|
|
@@ -6229,6 +6286,30 @@ var AGENT_MARKDOWN_FILE_SELECTION = `{
|
|
|
6229
6286
|
content
|
|
6230
6287
|
url
|
|
6231
6288
|
}`;
|
|
6289
|
+
var OSMD_SEARCH_SELECTION = `{
|
|
6290
|
+
query
|
|
6291
|
+
scope
|
|
6292
|
+
count
|
|
6293
|
+
candidates {
|
|
6294
|
+
path
|
|
6295
|
+
source
|
|
6296
|
+
access
|
|
6297
|
+
owner
|
|
6298
|
+
wikiRole
|
|
6299
|
+
formatVersion
|
|
6300
|
+
parentRef
|
|
6301
|
+
exists
|
|
6302
|
+
agentChildrenAllowed
|
|
6303
|
+
title
|
|
6304
|
+
label
|
|
6305
|
+
snippet
|
|
6306
|
+
rank
|
|
6307
|
+
matchReason
|
|
6308
|
+
toolKey
|
|
6309
|
+
nodeKey
|
|
6310
|
+
nodeKind
|
|
6311
|
+
}
|
|
6312
|
+
}`;
|
|
6232
6313
|
var MUTATION_RESULT_SELECTION = "{ ok status errorCode data errors }";
|
|
6233
6314
|
var AGENT_JSON_KEY_ALIASES = {
|
|
6234
6315
|
can_create: "canCreate",
|
|
@@ -6239,7 +6320,11 @@ var AGENT_JSON_KEY_ALIASES = {
|
|
|
6239
6320
|
parent_ref: "parentRef",
|
|
6240
6321
|
agent_children_allowed: "agentChildrenAllowed",
|
|
6241
6322
|
suggested_action: "suggestedAction",
|
|
6242
|
-
error_code: "errorCode"
|
|
6323
|
+
error_code: "errorCode",
|
|
6324
|
+
match_reason: "matchReason",
|
|
6325
|
+
tool_key: "toolKey",
|
|
6326
|
+
node_key: "nodeKey",
|
|
6327
|
+
node_kind: "nodeKind"
|
|
6243
6328
|
};
|
|
6244
6329
|
function isSupportedAgentMarkdownFile(file) {
|
|
6245
6330
|
if (file.source !== "agent_overlay") {
|
|
@@ -6391,6 +6476,22 @@ async function requestAgentMarkdownChildren(params) {
|
|
|
6391
6476
|
schema: agentMarkdownFilesSchema
|
|
6392
6477
|
});
|
|
6393
6478
|
}
|
|
6479
|
+
async function requestOsmdSearch(params) {
|
|
6480
|
+
return requestOsmdQuery({
|
|
6481
|
+
command: params.command,
|
|
6482
|
+
operationName: "OsMdSearch",
|
|
6483
|
+
runtimeOptions: params.runtimeOptions,
|
|
6484
|
+
field: "os_md_search",
|
|
6485
|
+
variables: {
|
|
6486
|
+
organization_id: params.organizationId,
|
|
6487
|
+
query: params.query,
|
|
6488
|
+
source: backendSearchSourceForScope(params.scope),
|
|
6489
|
+
limit: params.limit
|
|
6490
|
+
},
|
|
6491
|
+
selectionSet: OSMD_SEARCH_SELECTION,
|
|
6492
|
+
schema: osmdSearchResultSchema
|
|
6493
|
+
});
|
|
6494
|
+
}
|
|
6394
6495
|
async function runAgentMarkdownMutation(params) {
|
|
6395
6496
|
const result = await graphqlRequest({
|
|
6396
6497
|
config: getConfig(params.runtimeOptions),
|
|
@@ -6448,41 +6549,113 @@ function normalizeAgentFilePath(file) {
|
|
|
6448
6549
|
}
|
|
6449
6550
|
return `.agent/${parsed.data}`;
|
|
6450
6551
|
}
|
|
6451
|
-
function
|
|
6452
|
-
|
|
6552
|
+
function formatHumanList(items) {
|
|
6553
|
+
if (items.length <= 1) {
|
|
6554
|
+
return items[0] ?? "";
|
|
6555
|
+
}
|
|
6556
|
+
if (items.length === 2) {
|
|
6557
|
+
return `${items[0]} and ${items[1]}`;
|
|
6558
|
+
}
|
|
6559
|
+
return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
|
|
6560
|
+
}
|
|
6561
|
+
function supportedWikiPathsMessage(options = {}) {
|
|
6562
|
+
const allowed = allowedWikiPathLabels(options);
|
|
6563
|
+
return `Agent Wiki file commands support only ${formatHumanList(allowed)} in this CLI slice.`;
|
|
6564
|
+
}
|
|
6565
|
+
function allowedWikiPathLabels(options = {}) {
|
|
6566
|
+
const allowIndex = options.allowIndex ?? true;
|
|
6567
|
+
const allowLog = options.allowLog ?? true;
|
|
6568
|
+
const allowControlledPages = options.allowControlledPages ?? true;
|
|
6569
|
+
const labels = [];
|
|
6570
|
+
if (options.allowRoot) {
|
|
6571
|
+
labels.push("Agent Wiki");
|
|
6572
|
+
}
|
|
6573
|
+
if (allowIndex) {
|
|
6574
|
+
labels.push(supportedWikiIndexFile);
|
|
6575
|
+
}
|
|
6576
|
+
if (allowLog) {
|
|
6577
|
+
labels.push(supportedWikiLogFile);
|
|
6578
|
+
}
|
|
6579
|
+
if (allowControlledPages) {
|
|
6580
|
+
labels.push(...supportedWikiControlledPatterns);
|
|
6581
|
+
}
|
|
6582
|
+
if (options.allowControlledFolders) {
|
|
6583
|
+
labels.push(...supportedWikiControlledFolders);
|
|
6584
|
+
}
|
|
6585
|
+
return labels;
|
|
6586
|
+
}
|
|
6587
|
+
function rejectUnsupportedWikiPath(options) {
|
|
6588
|
+
throw new CliError({
|
|
6589
|
+
message: supportedWikiPathsMessage(options),
|
|
6590
|
+
kind: "invalid_args",
|
|
6591
|
+
status: 400,
|
|
6592
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
6593
|
+
details: { supportedPaths: allowedWikiPathLabels(options) }
|
|
6594
|
+
});
|
|
6595
|
+
}
|
|
6596
|
+
function isControlledWikiFolder(value) {
|
|
6597
|
+
return supportedWikiControlledFolders.includes(
|
|
6598
|
+
value
|
|
6599
|
+
);
|
|
6600
|
+
}
|
|
6601
|
+
function isMarkdownLeafFileName(value) {
|
|
6602
|
+
return value.endsWith(".md") && value.length > ".md".length;
|
|
6453
6603
|
}
|
|
6454
6604
|
function normalizeWikiPath(path, options = {}) {
|
|
6455
|
-
const
|
|
6605
|
+
const normalizedOptions = {
|
|
6606
|
+
allowIndex: options.allowIndex ?? true,
|
|
6607
|
+
allowLog: options.allowLog ?? true,
|
|
6608
|
+
allowControlledPages: options.allowControlledPages ?? true,
|
|
6609
|
+
allowRoot: options.allowRoot ?? false,
|
|
6610
|
+
allowControlledFolders: options.allowControlledFolders ?? false
|
|
6611
|
+
};
|
|
6456
6612
|
const trimmed = nonEmptyString3.parse(path).trim().replace(/^\/+/, "");
|
|
6457
6613
|
if (trimmed.localeCompare("Agent Wiki", void 0, { sensitivity: "accent" }) === 0) {
|
|
6458
|
-
if (
|
|
6614
|
+
if (normalizedOptions.allowRoot) {
|
|
6459
6615
|
return "Agent Wiki";
|
|
6460
6616
|
}
|
|
6461
|
-
|
|
6462
|
-
message: supportedWikiFilesMessage(supportedFiles),
|
|
6463
|
-
kind: "invalid_args",
|
|
6464
|
-
status: 400,
|
|
6465
|
-
exitCode: EXIT_CODES.invalidArgs,
|
|
6466
|
-
details: { supportedFiles }
|
|
6467
|
-
});
|
|
6617
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6468
6618
|
}
|
|
6469
6619
|
const fileName = trimmed.toLowerCase().startsWith("agent wiki/") ? trimmed.slice("Agent Wiki/".length) : trimmed;
|
|
6470
|
-
if (
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6620
|
+
if (fileName.includes("\\") || fileName.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
6621
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6622
|
+
}
|
|
6623
|
+
if (fileName === supportedWikiIndexFile) {
|
|
6624
|
+
if (normalizedOptions.allowIndex) {
|
|
6625
|
+
return `Agent Wiki/${fileName}`;
|
|
6626
|
+
}
|
|
6627
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6628
|
+
}
|
|
6629
|
+
if (fileName === supportedWikiLogFile) {
|
|
6630
|
+
if (normalizedOptions.allowLog) {
|
|
6631
|
+
return `Agent Wiki/${fileName}`;
|
|
6632
|
+
}
|
|
6633
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6634
|
+
}
|
|
6635
|
+
if (isControlledWikiFolder(fileName)) {
|
|
6636
|
+
if (normalizedOptions.allowControlledFolders) {
|
|
6637
|
+
return `Agent Wiki/${fileName}`;
|
|
6638
|
+
}
|
|
6639
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6640
|
+
}
|
|
6641
|
+
const parts = fileName.split("/");
|
|
6642
|
+
if (parts.length === 2 && isControlledWikiFolder(parts[0] ?? "") && isMarkdownLeafFileName(parts[1] ?? "")) {
|
|
6643
|
+
if (normalizedOptions.allowControlledPages) {
|
|
6644
|
+
return `Agent Wiki/${fileName}`;
|
|
6645
|
+
}
|
|
6646
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6478
6647
|
}
|
|
6479
|
-
return
|
|
6648
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6480
6649
|
}
|
|
6481
|
-
function
|
|
6482
|
-
return normalizeWikiPath(path, {
|
|
6650
|
+
function normalizeWikiWritablePath(path) {
|
|
6651
|
+
return normalizeWikiPath(path, { allowLog: false });
|
|
6483
6652
|
}
|
|
6484
6653
|
function normalizeWikiLogPath(path = supportedWikiLogFile) {
|
|
6485
|
-
return normalizeWikiPath(path, {
|
|
6654
|
+
return normalizeWikiPath(path, {
|
|
6655
|
+
allowIndex: false,
|
|
6656
|
+
allowLog: true,
|
|
6657
|
+
allowControlledPages: false
|
|
6658
|
+
});
|
|
6486
6659
|
}
|
|
6487
6660
|
function parseOptionalParentRef(value) {
|
|
6488
6661
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
@@ -6503,6 +6676,46 @@ function parseOptionalSource(value) {
|
|
|
6503
6676
|
}
|
|
6504
6677
|
return parsed.data;
|
|
6505
6678
|
}
|
|
6679
|
+
function parseOsmdSearchScope(value) {
|
|
6680
|
+
const raw = typeof value === "string" && value.trim() !== "" ? value.trim() : "combined";
|
|
6681
|
+
const parsed = osmdSearchScopeSchema.safeParse(raw);
|
|
6682
|
+
if (!parsed.success) {
|
|
6683
|
+
throw new CliError({
|
|
6684
|
+
message: "Invalid OSMD search scope. Use os-only, agent-overlay-only, agent-wiki-only, or combined.",
|
|
6685
|
+
kind: "invalid_args",
|
|
6686
|
+
status: 400,
|
|
6687
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
6688
|
+
details: { supportedScopes: osmdSearchScopeSchema.options }
|
|
6689
|
+
});
|
|
6690
|
+
}
|
|
6691
|
+
return parsed.data;
|
|
6692
|
+
}
|
|
6693
|
+
function backendSearchSourceForScope(scope) {
|
|
6694
|
+
if (scope === "os-only") {
|
|
6695
|
+
return "canonical_osmd";
|
|
6696
|
+
}
|
|
6697
|
+
if (scope === "agent-overlay-only") {
|
|
6698
|
+
return "agent_overlay";
|
|
6699
|
+
}
|
|
6700
|
+
if (scope === "agent-wiki-only") {
|
|
6701
|
+
return "agent_wiki";
|
|
6702
|
+
}
|
|
6703
|
+
return "combined";
|
|
6704
|
+
}
|
|
6705
|
+
function parseSearchLimit(value) {
|
|
6706
|
+
const raw = value === void 0 || value === null || value === "" ? "10" : value;
|
|
6707
|
+
const parsed = positiveInt.safeParse(raw);
|
|
6708
|
+
if (!parsed.success) {
|
|
6709
|
+
throw new CliError({
|
|
6710
|
+
message: "Invalid OSMD search limit. Use a positive integer.",
|
|
6711
|
+
kind: "invalid_args",
|
|
6712
|
+
status: 400,
|
|
6713
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
6714
|
+
details: { issues: parsed.error.issues }
|
|
6715
|
+
});
|
|
6716
|
+
}
|
|
6717
|
+
return parsed.data;
|
|
6718
|
+
}
|
|
6506
6719
|
function parseDepth(value) {
|
|
6507
6720
|
if (value === void 0 || value === null || value === "") {
|
|
6508
6721
|
return 1;
|
|
@@ -6792,7 +7005,7 @@ function registerOsmdCommands(program) {
|
|
|
6792
7005
|
})
|
|
6793
7006
|
});
|
|
6794
7007
|
});
|
|
6795
|
-
osmd.command("children [path]").description("List backend-supported agent markdown children
|
|
7008
|
+
osmd.command("children [path]").description("List backend-supported agent markdown children").option("--parent-ref <parentRef>", "Canonical OSMD parent ref for .agent files").option("--source <source>", "Filter by canonical_osmd, agent_overlay, or agent_wiki").action(async (path, opts, cmd) => {
|
|
6796
7009
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
6797
7010
|
const result = await requestAgentMarkdownChildren({
|
|
6798
7011
|
command: "osmd.children",
|
|
@@ -6811,6 +7024,25 @@ function registerOsmdCommands(program) {
|
|
|
6811
7024
|
})
|
|
6812
7025
|
});
|
|
6813
7026
|
});
|
|
7027
|
+
osmd.command("search <query>").description("Search merged OSMD, .agent overlays, and Agent Wiki through backend OSMD search").option("--scope <scope>", "os-only, agent-overlay-only, agent-wiki-only, or combined", "combined").option("--limit <limit>", "Maximum number of results", "10").action(async (query, opts, cmd) => {
|
|
7028
|
+
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
7029
|
+
const result = await requestOsmdSearch({
|
|
7030
|
+
command: "osmd.search",
|
|
7031
|
+
runtimeOptions,
|
|
7032
|
+
organizationId,
|
|
7033
|
+
query: nonEmptyString3.parse(query).trim(),
|
|
7034
|
+
scope: parseOsmdSearchScope(opts.scope),
|
|
7035
|
+
limit: parseSearchLimit(opts.limit)
|
|
7036
|
+
});
|
|
7037
|
+
return printEnvelopeAndExit({
|
|
7038
|
+
envelope: buildSuccessEnvelope({
|
|
7039
|
+
command: "osmd.search",
|
|
7040
|
+
status: result.status,
|
|
7041
|
+
data: result.data,
|
|
7042
|
+
requestId: result.requestId
|
|
7043
|
+
})
|
|
7044
|
+
});
|
|
7045
|
+
});
|
|
6814
7046
|
const agent = osmd.command("agent").description(".agent overlay memory attached to canonical OSMD parents; supports notes.md");
|
|
6815
7047
|
agent.command("status <parent-ref> <file>").description("Show .agent notes.md metadata without creating files").action(async (parentRef, file, _opts, cmd) => {
|
|
6816
7048
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
@@ -6898,7 +7130,7 @@ function registerOsmdCommands(program) {
|
|
|
6898
7130
|
});
|
|
6899
7131
|
}
|
|
6900
7132
|
);
|
|
6901
|
-
const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; supports index.md and append-only log.md");
|
|
7133
|
+
const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; supports index.md, controlled pages, and append-only log.md");
|
|
6902
7134
|
wiki.command("init").description("Idempotently initialize Agent Wiki system files").action(async function() {
|
|
6903
7135
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(this);
|
|
6904
7136
|
return runAgentMarkdownMutation({
|
|
@@ -6912,7 +7144,7 @@ function registerOsmdCommands(program) {
|
|
|
6912
7144
|
}
|
|
6913
7145
|
});
|
|
6914
7146
|
});
|
|
6915
|
-
wiki.command("status <path>").description("Show Agent Wiki index.md
|
|
7147
|
+
wiki.command("status <path>").description("Show Agent Wiki index.md, log.md, or controlled page metadata without creating files").action(async (path, _opts, cmd) => {
|
|
6916
7148
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
6917
7149
|
const result = await requestAgentMarkdownStatus({
|
|
6918
7150
|
command: "osmd.wiki.status",
|
|
@@ -6929,7 +7161,7 @@ function registerOsmdCommands(program) {
|
|
|
6929
7161
|
})
|
|
6930
7162
|
});
|
|
6931
7163
|
});
|
|
6932
|
-
wiki.command("read <path>").description("Read Agent Wiki index.md
|
|
7164
|
+
wiki.command("read <path>").description("Read Agent Wiki index.md, log.md, or controlled pages without creating files").action(async (path, _opts, cmd) => {
|
|
6933
7165
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
6934
7166
|
const result = await requestAgentMarkdownFile({
|
|
6935
7167
|
command: "osmd.wiki.read",
|
|
@@ -6952,7 +7184,7 @@ function registerOsmdCommands(program) {
|
|
|
6952
7184
|
command: "osmd.wiki.children",
|
|
6953
7185
|
runtimeOptions,
|
|
6954
7186
|
organizationId,
|
|
6955
|
-
path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path, { allowRoot: true }) : "Agent Wiki",
|
|
7187
|
+
path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path, { allowRoot: true, allowControlledFolders: true }) : "Agent Wiki",
|
|
6956
7188
|
source: "agent_wiki"
|
|
6957
7189
|
});
|
|
6958
7190
|
return printEnvelopeAndExit({
|
|
@@ -6965,7 +7197,7 @@ function registerOsmdCommands(program) {
|
|
|
6965
7197
|
});
|
|
6966
7198
|
});
|
|
6967
7199
|
addContentOptions(
|
|
6968
|
-
wiki.command("create <path>").description("Create Agent Wiki index.md after status/permission preflight")
|
|
7200
|
+
wiki.command("create <path>").description("Create Agent Wiki index.md or controlled pages after status/permission preflight")
|
|
6969
7201
|
).action(async (path, opts, cmd) => {
|
|
6970
7202
|
const globals = cmd.optsWithGlobals();
|
|
6971
7203
|
const content = await resolveContentInput(opts, globals);
|
|
@@ -6975,12 +7207,12 @@ function registerOsmdCommands(program) {
|
|
|
6975
7207
|
action: "create",
|
|
6976
7208
|
runtimeOptions,
|
|
6977
7209
|
organizationId,
|
|
6978
|
-
path:
|
|
7210
|
+
path: normalizeWikiWritablePath(path),
|
|
6979
7211
|
content
|
|
6980
7212
|
});
|
|
6981
7213
|
});
|
|
6982
7214
|
addContentOptions(
|
|
6983
|
-
wiki.command("update <path>").description("Update Agent Wiki index.md after status/permission preflight")
|
|
7215
|
+
wiki.command("update <path>").description("Update Agent Wiki index.md or controlled pages after status/permission preflight")
|
|
6984
7216
|
).action(async (path, opts, cmd) => {
|
|
6985
7217
|
const globals = cmd.optsWithGlobals();
|
|
6986
7218
|
const content = await resolveContentInput(opts, globals);
|
|
@@ -6990,7 +7222,7 @@ function registerOsmdCommands(program) {
|
|
|
6990
7222
|
action: "update",
|
|
6991
7223
|
runtimeOptions,
|
|
6992
7224
|
organizationId,
|
|
6993
|
-
path:
|
|
7225
|
+
path: normalizeWikiWritablePath(path),
|
|
6994
7226
|
content
|
|
6995
7227
|
});
|
|
6996
7228
|
});
|
package/dist/index.js
CHANGED
|
@@ -6142,10 +6142,26 @@ var agentMarkdownErrorCodeSchema = z16.enum([
|
|
|
6142
6142
|
var agentMarkdownErrorCodeFieldSchema = agentMarkdownErrorCodeSchema.nullable().catch(null);
|
|
6143
6143
|
var nonEmptyString3 = z16.string().min(1);
|
|
6144
6144
|
var nonNegativeInt3 = z16.coerce.number().int().min(0);
|
|
6145
|
+
var positiveInt = z16.coerce.number().int().min(1);
|
|
6145
6146
|
var supportedAgentOverlayFile = "notes.md";
|
|
6146
6147
|
var supportedWikiIndexFile = "index.md";
|
|
6147
6148
|
var supportedWikiLogFile = "log.md";
|
|
6149
|
+
var supportedWikiControlledFolders = [
|
|
6150
|
+
"concepts",
|
|
6151
|
+
"playbooks",
|
|
6152
|
+
"decisions",
|
|
6153
|
+
"org-summaries"
|
|
6154
|
+
];
|
|
6155
|
+
var supportedWikiControlledPatterns = supportedWikiControlledFolders.map(
|
|
6156
|
+
(folder) => `${folder}/*.md`
|
|
6157
|
+
);
|
|
6148
6158
|
var agentOverlayFileSchema = z16.enum([supportedAgentOverlayFile]);
|
|
6159
|
+
var osmdSearchScopeSchema = z16.enum([
|
|
6160
|
+
"os-only",
|
|
6161
|
+
"agent-overlay-only",
|
|
6162
|
+
"agent-wiki-only",
|
|
6163
|
+
"combined"
|
|
6164
|
+
]);
|
|
6149
6165
|
var agentMarkdownFileSchema = z16.object({
|
|
6150
6166
|
path: z16.string(),
|
|
6151
6167
|
source: sourceSchema,
|
|
@@ -6177,6 +6193,47 @@ var agentMarkdownMutationDataSchema = z16.union([
|
|
|
6177
6193
|
agentMarkdownFileSchema,
|
|
6178
6194
|
z16.object({ files: agentMarkdownFilesSchema })
|
|
6179
6195
|
]);
|
|
6196
|
+
var osmdSearchCandidateSchema = z16.preprocess(
|
|
6197
|
+
normalizeAgentMarkdownJsonKeys,
|
|
6198
|
+
z16.object({
|
|
6199
|
+
path: z16.string(),
|
|
6200
|
+
source: sourceSchema,
|
|
6201
|
+
access: accessSchema,
|
|
6202
|
+
owner: ownerSchema,
|
|
6203
|
+
wikiRole: z16.string().nullable().optional(),
|
|
6204
|
+
formatVersion: z16.string().nullable().optional(),
|
|
6205
|
+
parentRef: z16.string().nullable().optional(),
|
|
6206
|
+
exists: z16.boolean(),
|
|
6207
|
+
agentChildrenAllowed: z16.boolean(),
|
|
6208
|
+
title: z16.string(),
|
|
6209
|
+
label: z16.string(),
|
|
6210
|
+
snippet: z16.string().nullable().optional(),
|
|
6211
|
+
rank: z16.number().int(),
|
|
6212
|
+
matchReason: z16.string().nullable().optional(),
|
|
6213
|
+
toolKey: z16.string().nullable().optional(),
|
|
6214
|
+
nodeKey: z16.string().nullable().optional(),
|
|
6215
|
+
nodeKind: z16.string().nullable().optional()
|
|
6216
|
+
}).transform((value) => ({
|
|
6217
|
+
...value,
|
|
6218
|
+
wikiRole: value.wikiRole ?? null,
|
|
6219
|
+
formatVersion: value.formatVersion ?? null,
|
|
6220
|
+
parentRef: value.parentRef ?? null,
|
|
6221
|
+
snippet: value.snippet ?? null,
|
|
6222
|
+
matchReason: value.matchReason ?? null,
|
|
6223
|
+
toolKey: value.toolKey ?? null,
|
|
6224
|
+
nodeKey: value.nodeKey ?? null,
|
|
6225
|
+
nodeKind: value.nodeKind ?? null
|
|
6226
|
+
}))
|
|
6227
|
+
);
|
|
6228
|
+
var osmdSearchResultSchema = z16.preprocess(
|
|
6229
|
+
normalizeAgentMarkdownJsonKeys,
|
|
6230
|
+
z16.object({
|
|
6231
|
+
query: z16.string(),
|
|
6232
|
+
scope: z16.string(),
|
|
6233
|
+
count: z16.number().int().min(0),
|
|
6234
|
+
candidates: z16.array(osmdSearchCandidateSchema)
|
|
6235
|
+
})
|
|
6236
|
+
);
|
|
6180
6237
|
var mutationPayloadSchema = z16.object({
|
|
6181
6238
|
ok: z16.boolean(),
|
|
6182
6239
|
status: z16.number(),
|
|
@@ -6228,6 +6285,30 @@ var AGENT_MARKDOWN_FILE_SELECTION = `{
|
|
|
6228
6285
|
content
|
|
6229
6286
|
url
|
|
6230
6287
|
}`;
|
|
6288
|
+
var OSMD_SEARCH_SELECTION = `{
|
|
6289
|
+
query
|
|
6290
|
+
scope
|
|
6291
|
+
count
|
|
6292
|
+
candidates {
|
|
6293
|
+
path
|
|
6294
|
+
source
|
|
6295
|
+
access
|
|
6296
|
+
owner
|
|
6297
|
+
wikiRole
|
|
6298
|
+
formatVersion
|
|
6299
|
+
parentRef
|
|
6300
|
+
exists
|
|
6301
|
+
agentChildrenAllowed
|
|
6302
|
+
title
|
|
6303
|
+
label
|
|
6304
|
+
snippet
|
|
6305
|
+
rank
|
|
6306
|
+
matchReason
|
|
6307
|
+
toolKey
|
|
6308
|
+
nodeKey
|
|
6309
|
+
nodeKind
|
|
6310
|
+
}
|
|
6311
|
+
}`;
|
|
6231
6312
|
var MUTATION_RESULT_SELECTION = "{ ok status errorCode data errors }";
|
|
6232
6313
|
var AGENT_JSON_KEY_ALIASES = {
|
|
6233
6314
|
can_create: "canCreate",
|
|
@@ -6238,7 +6319,11 @@ var AGENT_JSON_KEY_ALIASES = {
|
|
|
6238
6319
|
parent_ref: "parentRef",
|
|
6239
6320
|
agent_children_allowed: "agentChildrenAllowed",
|
|
6240
6321
|
suggested_action: "suggestedAction",
|
|
6241
|
-
error_code: "errorCode"
|
|
6322
|
+
error_code: "errorCode",
|
|
6323
|
+
match_reason: "matchReason",
|
|
6324
|
+
tool_key: "toolKey",
|
|
6325
|
+
node_key: "nodeKey",
|
|
6326
|
+
node_kind: "nodeKind"
|
|
6242
6327
|
};
|
|
6243
6328
|
function isSupportedAgentMarkdownFile(file) {
|
|
6244
6329
|
if (file.source !== "agent_overlay") {
|
|
@@ -6390,6 +6475,22 @@ async function requestAgentMarkdownChildren(params) {
|
|
|
6390
6475
|
schema: agentMarkdownFilesSchema
|
|
6391
6476
|
});
|
|
6392
6477
|
}
|
|
6478
|
+
async function requestOsmdSearch(params) {
|
|
6479
|
+
return requestOsmdQuery({
|
|
6480
|
+
command: params.command,
|
|
6481
|
+
operationName: "OsMdSearch",
|
|
6482
|
+
runtimeOptions: params.runtimeOptions,
|
|
6483
|
+
field: "os_md_search",
|
|
6484
|
+
variables: {
|
|
6485
|
+
organization_id: params.organizationId,
|
|
6486
|
+
query: params.query,
|
|
6487
|
+
source: backendSearchSourceForScope(params.scope),
|
|
6488
|
+
limit: params.limit
|
|
6489
|
+
},
|
|
6490
|
+
selectionSet: OSMD_SEARCH_SELECTION,
|
|
6491
|
+
schema: osmdSearchResultSchema
|
|
6492
|
+
});
|
|
6493
|
+
}
|
|
6393
6494
|
async function runAgentMarkdownMutation(params) {
|
|
6394
6495
|
const result = await graphqlRequest({
|
|
6395
6496
|
config: getConfig(params.runtimeOptions),
|
|
@@ -6447,41 +6548,113 @@ function normalizeAgentFilePath(file) {
|
|
|
6447
6548
|
}
|
|
6448
6549
|
return `.agent/${parsed.data}`;
|
|
6449
6550
|
}
|
|
6450
|
-
function
|
|
6451
|
-
|
|
6551
|
+
function formatHumanList(items) {
|
|
6552
|
+
if (items.length <= 1) {
|
|
6553
|
+
return items[0] ?? "";
|
|
6554
|
+
}
|
|
6555
|
+
if (items.length === 2) {
|
|
6556
|
+
return `${items[0]} and ${items[1]}`;
|
|
6557
|
+
}
|
|
6558
|
+
return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
|
|
6559
|
+
}
|
|
6560
|
+
function supportedWikiPathsMessage(options = {}) {
|
|
6561
|
+
const allowed = allowedWikiPathLabels(options);
|
|
6562
|
+
return `Agent Wiki file commands support only ${formatHumanList(allowed)} in this CLI slice.`;
|
|
6563
|
+
}
|
|
6564
|
+
function allowedWikiPathLabels(options = {}) {
|
|
6565
|
+
const allowIndex = options.allowIndex ?? true;
|
|
6566
|
+
const allowLog = options.allowLog ?? true;
|
|
6567
|
+
const allowControlledPages = options.allowControlledPages ?? true;
|
|
6568
|
+
const labels = [];
|
|
6569
|
+
if (options.allowRoot) {
|
|
6570
|
+
labels.push("Agent Wiki");
|
|
6571
|
+
}
|
|
6572
|
+
if (allowIndex) {
|
|
6573
|
+
labels.push(supportedWikiIndexFile);
|
|
6574
|
+
}
|
|
6575
|
+
if (allowLog) {
|
|
6576
|
+
labels.push(supportedWikiLogFile);
|
|
6577
|
+
}
|
|
6578
|
+
if (allowControlledPages) {
|
|
6579
|
+
labels.push(...supportedWikiControlledPatterns);
|
|
6580
|
+
}
|
|
6581
|
+
if (options.allowControlledFolders) {
|
|
6582
|
+
labels.push(...supportedWikiControlledFolders);
|
|
6583
|
+
}
|
|
6584
|
+
return labels;
|
|
6585
|
+
}
|
|
6586
|
+
function rejectUnsupportedWikiPath(options) {
|
|
6587
|
+
throw new CliError({
|
|
6588
|
+
message: supportedWikiPathsMessage(options),
|
|
6589
|
+
kind: "invalid_args",
|
|
6590
|
+
status: 400,
|
|
6591
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
6592
|
+
details: { supportedPaths: allowedWikiPathLabels(options) }
|
|
6593
|
+
});
|
|
6594
|
+
}
|
|
6595
|
+
function isControlledWikiFolder(value) {
|
|
6596
|
+
return supportedWikiControlledFolders.includes(
|
|
6597
|
+
value
|
|
6598
|
+
);
|
|
6599
|
+
}
|
|
6600
|
+
function isMarkdownLeafFileName(value) {
|
|
6601
|
+
return value.endsWith(".md") && value.length > ".md".length;
|
|
6452
6602
|
}
|
|
6453
6603
|
function normalizeWikiPath(path, options = {}) {
|
|
6454
|
-
const
|
|
6604
|
+
const normalizedOptions = {
|
|
6605
|
+
allowIndex: options.allowIndex ?? true,
|
|
6606
|
+
allowLog: options.allowLog ?? true,
|
|
6607
|
+
allowControlledPages: options.allowControlledPages ?? true,
|
|
6608
|
+
allowRoot: options.allowRoot ?? false,
|
|
6609
|
+
allowControlledFolders: options.allowControlledFolders ?? false
|
|
6610
|
+
};
|
|
6455
6611
|
const trimmed = nonEmptyString3.parse(path).trim().replace(/^\/+/, "");
|
|
6456
6612
|
if (trimmed.localeCompare("Agent Wiki", void 0, { sensitivity: "accent" }) === 0) {
|
|
6457
|
-
if (
|
|
6613
|
+
if (normalizedOptions.allowRoot) {
|
|
6458
6614
|
return "Agent Wiki";
|
|
6459
6615
|
}
|
|
6460
|
-
|
|
6461
|
-
message: supportedWikiFilesMessage(supportedFiles),
|
|
6462
|
-
kind: "invalid_args",
|
|
6463
|
-
status: 400,
|
|
6464
|
-
exitCode: EXIT_CODES.invalidArgs,
|
|
6465
|
-
details: { supportedFiles }
|
|
6466
|
-
});
|
|
6616
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6467
6617
|
}
|
|
6468
6618
|
const fileName = trimmed.toLowerCase().startsWith("agent wiki/") ? trimmed.slice("Agent Wiki/".length) : trimmed;
|
|
6469
|
-
if (
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6619
|
+
if (fileName.includes("\\") || fileName.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
6620
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6621
|
+
}
|
|
6622
|
+
if (fileName === supportedWikiIndexFile) {
|
|
6623
|
+
if (normalizedOptions.allowIndex) {
|
|
6624
|
+
return `Agent Wiki/${fileName}`;
|
|
6625
|
+
}
|
|
6626
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6627
|
+
}
|
|
6628
|
+
if (fileName === supportedWikiLogFile) {
|
|
6629
|
+
if (normalizedOptions.allowLog) {
|
|
6630
|
+
return `Agent Wiki/${fileName}`;
|
|
6631
|
+
}
|
|
6632
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6633
|
+
}
|
|
6634
|
+
if (isControlledWikiFolder(fileName)) {
|
|
6635
|
+
if (normalizedOptions.allowControlledFolders) {
|
|
6636
|
+
return `Agent Wiki/${fileName}`;
|
|
6637
|
+
}
|
|
6638
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6639
|
+
}
|
|
6640
|
+
const parts = fileName.split("/");
|
|
6641
|
+
if (parts.length === 2 && isControlledWikiFolder(parts[0] ?? "") && isMarkdownLeafFileName(parts[1] ?? "")) {
|
|
6642
|
+
if (normalizedOptions.allowControlledPages) {
|
|
6643
|
+
return `Agent Wiki/${fileName}`;
|
|
6644
|
+
}
|
|
6645
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6477
6646
|
}
|
|
6478
|
-
return
|
|
6647
|
+
return rejectUnsupportedWikiPath(normalizedOptions);
|
|
6479
6648
|
}
|
|
6480
|
-
function
|
|
6481
|
-
return normalizeWikiPath(path, {
|
|
6649
|
+
function normalizeWikiWritablePath(path) {
|
|
6650
|
+
return normalizeWikiPath(path, { allowLog: false });
|
|
6482
6651
|
}
|
|
6483
6652
|
function normalizeWikiLogPath(path = supportedWikiLogFile) {
|
|
6484
|
-
return normalizeWikiPath(path, {
|
|
6653
|
+
return normalizeWikiPath(path, {
|
|
6654
|
+
allowIndex: false,
|
|
6655
|
+
allowLog: true,
|
|
6656
|
+
allowControlledPages: false
|
|
6657
|
+
});
|
|
6485
6658
|
}
|
|
6486
6659
|
function parseOptionalParentRef(value) {
|
|
6487
6660
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
@@ -6502,6 +6675,46 @@ function parseOptionalSource(value) {
|
|
|
6502
6675
|
}
|
|
6503
6676
|
return parsed.data;
|
|
6504
6677
|
}
|
|
6678
|
+
function parseOsmdSearchScope(value) {
|
|
6679
|
+
const raw = typeof value === "string" && value.trim() !== "" ? value.trim() : "combined";
|
|
6680
|
+
const parsed = osmdSearchScopeSchema.safeParse(raw);
|
|
6681
|
+
if (!parsed.success) {
|
|
6682
|
+
throw new CliError({
|
|
6683
|
+
message: "Invalid OSMD search scope. Use os-only, agent-overlay-only, agent-wiki-only, or combined.",
|
|
6684
|
+
kind: "invalid_args",
|
|
6685
|
+
status: 400,
|
|
6686
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
6687
|
+
details: { supportedScopes: osmdSearchScopeSchema.options }
|
|
6688
|
+
});
|
|
6689
|
+
}
|
|
6690
|
+
return parsed.data;
|
|
6691
|
+
}
|
|
6692
|
+
function backendSearchSourceForScope(scope) {
|
|
6693
|
+
if (scope === "os-only") {
|
|
6694
|
+
return "canonical_osmd";
|
|
6695
|
+
}
|
|
6696
|
+
if (scope === "agent-overlay-only") {
|
|
6697
|
+
return "agent_overlay";
|
|
6698
|
+
}
|
|
6699
|
+
if (scope === "agent-wiki-only") {
|
|
6700
|
+
return "agent_wiki";
|
|
6701
|
+
}
|
|
6702
|
+
return "combined";
|
|
6703
|
+
}
|
|
6704
|
+
function parseSearchLimit(value) {
|
|
6705
|
+
const raw = value === void 0 || value === null || value === "" ? "10" : value;
|
|
6706
|
+
const parsed = positiveInt.safeParse(raw);
|
|
6707
|
+
if (!parsed.success) {
|
|
6708
|
+
throw new CliError({
|
|
6709
|
+
message: "Invalid OSMD search limit. Use a positive integer.",
|
|
6710
|
+
kind: "invalid_args",
|
|
6711
|
+
status: 400,
|
|
6712
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
6713
|
+
details: { issues: parsed.error.issues }
|
|
6714
|
+
});
|
|
6715
|
+
}
|
|
6716
|
+
return parsed.data;
|
|
6717
|
+
}
|
|
6505
6718
|
function parseDepth(value) {
|
|
6506
6719
|
if (value === void 0 || value === null || value === "") {
|
|
6507
6720
|
return 1;
|
|
@@ -6791,7 +7004,7 @@ function registerOsmdCommands(program) {
|
|
|
6791
7004
|
})
|
|
6792
7005
|
});
|
|
6793
7006
|
});
|
|
6794
|
-
osmd.command("children [path]").description("List backend-supported agent markdown children
|
|
7007
|
+
osmd.command("children [path]").description("List backend-supported agent markdown children").option("--parent-ref <parentRef>", "Canonical OSMD parent ref for .agent files").option("--source <source>", "Filter by canonical_osmd, agent_overlay, or agent_wiki").action(async (path, opts, cmd) => {
|
|
6795
7008
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
6796
7009
|
const result = await requestAgentMarkdownChildren({
|
|
6797
7010
|
command: "osmd.children",
|
|
@@ -6810,6 +7023,25 @@ function registerOsmdCommands(program) {
|
|
|
6810
7023
|
})
|
|
6811
7024
|
});
|
|
6812
7025
|
});
|
|
7026
|
+
osmd.command("search <query>").description("Search merged OSMD, .agent overlays, and Agent Wiki through backend OSMD search").option("--scope <scope>", "os-only, agent-overlay-only, agent-wiki-only, or combined", "combined").option("--limit <limit>", "Maximum number of results", "10").action(async (query, opts, cmd) => {
|
|
7027
|
+
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
7028
|
+
const result = await requestOsmdSearch({
|
|
7029
|
+
command: "osmd.search",
|
|
7030
|
+
runtimeOptions,
|
|
7031
|
+
organizationId,
|
|
7032
|
+
query: nonEmptyString3.parse(query).trim(),
|
|
7033
|
+
scope: parseOsmdSearchScope(opts.scope),
|
|
7034
|
+
limit: parseSearchLimit(opts.limit)
|
|
7035
|
+
});
|
|
7036
|
+
return printEnvelopeAndExit({
|
|
7037
|
+
envelope: buildSuccessEnvelope({
|
|
7038
|
+
command: "osmd.search",
|
|
7039
|
+
status: result.status,
|
|
7040
|
+
data: result.data,
|
|
7041
|
+
requestId: result.requestId
|
|
7042
|
+
})
|
|
7043
|
+
});
|
|
7044
|
+
});
|
|
6813
7045
|
const agent = osmd.command("agent").description(".agent overlay memory attached to canonical OSMD parents; supports notes.md");
|
|
6814
7046
|
agent.command("status <parent-ref> <file>").description("Show .agent notes.md metadata without creating files").action(async (parentRef, file, _opts, cmd) => {
|
|
6815
7047
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
@@ -6897,7 +7129,7 @@ function registerOsmdCommands(program) {
|
|
|
6897
7129
|
});
|
|
6898
7130
|
}
|
|
6899
7131
|
);
|
|
6900
|
-
const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; supports index.md and append-only log.md");
|
|
7132
|
+
const wiki = osmd.command("wiki").description("Agent Wiki files writable by agents; supports index.md, controlled pages, and append-only log.md");
|
|
6901
7133
|
wiki.command("init").description("Idempotently initialize Agent Wiki system files").action(async function() {
|
|
6902
7134
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(this);
|
|
6903
7135
|
return runAgentMarkdownMutation({
|
|
@@ -6911,7 +7143,7 @@ function registerOsmdCommands(program) {
|
|
|
6911
7143
|
}
|
|
6912
7144
|
});
|
|
6913
7145
|
});
|
|
6914
|
-
wiki.command("status <path>").description("Show Agent Wiki index.md
|
|
7146
|
+
wiki.command("status <path>").description("Show Agent Wiki index.md, log.md, or controlled page metadata without creating files").action(async (path, _opts, cmd) => {
|
|
6915
7147
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
6916
7148
|
const result = await requestAgentMarkdownStatus({
|
|
6917
7149
|
command: "osmd.wiki.status",
|
|
@@ -6928,7 +7160,7 @@ function registerOsmdCommands(program) {
|
|
|
6928
7160
|
})
|
|
6929
7161
|
});
|
|
6930
7162
|
});
|
|
6931
|
-
wiki.command("read <path>").description("Read Agent Wiki index.md
|
|
7163
|
+
wiki.command("read <path>").description("Read Agent Wiki index.md, log.md, or controlled pages without creating files").action(async (path, _opts, cmd) => {
|
|
6932
7164
|
const { organizationId, runtimeOptions } = await resolveOsmdContext(cmd);
|
|
6933
7165
|
const result = await requestAgentMarkdownFile({
|
|
6934
7166
|
command: "osmd.wiki.read",
|
|
@@ -6951,7 +7183,7 @@ function registerOsmdCommands(program) {
|
|
|
6951
7183
|
command: "osmd.wiki.children",
|
|
6952
7184
|
runtimeOptions,
|
|
6953
7185
|
organizationId,
|
|
6954
|
-
path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path, { allowRoot: true }) : "Agent Wiki",
|
|
7186
|
+
path: typeof path === "string" && path.trim() !== "" ? normalizeWikiPath(path, { allowRoot: true, allowControlledFolders: true }) : "Agent Wiki",
|
|
6955
7187
|
source: "agent_wiki"
|
|
6956
7188
|
});
|
|
6957
7189
|
return printEnvelopeAndExit({
|
|
@@ -6964,7 +7196,7 @@ function registerOsmdCommands(program) {
|
|
|
6964
7196
|
});
|
|
6965
7197
|
});
|
|
6966
7198
|
addContentOptions(
|
|
6967
|
-
wiki.command("create <path>").description("Create Agent Wiki index.md after status/permission preflight")
|
|
7199
|
+
wiki.command("create <path>").description("Create Agent Wiki index.md or controlled pages after status/permission preflight")
|
|
6968
7200
|
).action(async (path, opts, cmd) => {
|
|
6969
7201
|
const globals = cmd.optsWithGlobals();
|
|
6970
7202
|
const content = await resolveContentInput(opts, globals);
|
|
@@ -6974,12 +7206,12 @@ function registerOsmdCommands(program) {
|
|
|
6974
7206
|
action: "create",
|
|
6975
7207
|
runtimeOptions,
|
|
6976
7208
|
organizationId,
|
|
6977
|
-
path:
|
|
7209
|
+
path: normalizeWikiWritablePath(path),
|
|
6978
7210
|
content
|
|
6979
7211
|
});
|
|
6980
7212
|
});
|
|
6981
7213
|
addContentOptions(
|
|
6982
|
-
wiki.command("update <path>").description("Update Agent Wiki index.md after status/permission preflight")
|
|
7214
|
+
wiki.command("update <path>").description("Update Agent Wiki index.md or controlled pages after status/permission preflight")
|
|
6983
7215
|
).action(async (path, opts, cmd) => {
|
|
6984
7216
|
const globals = cmd.optsWithGlobals();
|
|
6985
7217
|
const content = await resolveContentInput(opts, globals);
|
|
@@ -6989,7 +7221,7 @@ function registerOsmdCommands(program) {
|
|
|
6989
7221
|
action: "update",
|
|
6990
7222
|
runtimeOptions,
|
|
6991
7223
|
organizationId,
|
|
6992
|
-
path:
|
|
7224
|
+
path: normalizeWikiWritablePath(path),
|
|
6993
7225
|
content
|
|
6994
7226
|
});
|
|
6995
7227
|
});
|
package/package.json
CHANGED
|
@@ -1330,6 +1330,124 @@ function runOsmdLiveVerification() {
|
|
|
1330
1330
|
);
|
|
1331
1331
|
}
|
|
1332
1332
|
|
|
1333
|
+
const controlledWikiSearchTerm = `CLI live controlled wiki ${verifyStamp}`;
|
|
1334
|
+
const controlledWikiPages = [
|
|
1335
|
+
{
|
|
1336
|
+
path: `concepts/cli-live-concept-${verifyStamp}.md`,
|
|
1337
|
+
fullPath: `Agent Wiki/concepts/cli-live-concept-${verifyStamp}.md`,
|
|
1338
|
+
wikiRole: "concept",
|
|
1339
|
+
title: "concept"
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
path: `playbooks/cli-live-playbook-${verifyStamp}.md`,
|
|
1343
|
+
fullPath: `Agent Wiki/playbooks/cli-live-playbook-${verifyStamp}.md`,
|
|
1344
|
+
wikiRole: "playbook",
|
|
1345
|
+
title: "playbook"
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
path: `decisions/cli-live-decision-${verifyStamp}.md`,
|
|
1349
|
+
fullPath: `Agent Wiki/decisions/cli-live-decision-${verifyStamp}.md`,
|
|
1350
|
+
wikiRole: "decision",
|
|
1351
|
+
title: "decision"
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
path: `org-summaries/cli-live-org-summary-${verifyStamp}.md`,
|
|
1355
|
+
fullPath: `Agent Wiki/org-summaries/cli-live-org-summary-${verifyStamp}.md`,
|
|
1356
|
+
wikiRole: "org_summary",
|
|
1357
|
+
title: "org_summary"
|
|
1358
|
+
}
|
|
1359
|
+
];
|
|
1360
|
+
|
|
1361
|
+
for (const page of controlledWikiPages) {
|
|
1362
|
+
const controlledStatus = runWave(["osmd", "wiki", "status", page.path], env);
|
|
1363
|
+
results.push(controlledStatus);
|
|
1364
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1365
|
+
lines: osmdVerificationLines,
|
|
1366
|
+
label: `osmd.wiki status controlled ${page.title}`,
|
|
1367
|
+
result: controlledStatus,
|
|
1368
|
+
ok:
|
|
1369
|
+
controlledStatus.parsed?.ok === true &&
|
|
1370
|
+
controlledStatus.parsed?.data?.path === page.fullPath &&
|
|
1371
|
+
controlledStatus.parsed?.data?.source === "agent_wiki" &&
|
|
1372
|
+
controlledStatus.parsed?.data?.access === "read_write" &&
|
|
1373
|
+
controlledStatus.parsed?.data?.wikiRole === page.wikiRole &&
|
|
1374
|
+
controlledStatus.parsed?.data?.formatVersion === "agent_markdown_v1" &&
|
|
1375
|
+
controlledStatus.parsed?.data?.exists === false &&
|
|
1376
|
+
controlledStatus.parsed?.data?.canCreate === true &&
|
|
1377
|
+
controlledStatus.parsed?.data?.canUpdate === false &&
|
|
1378
|
+
controlledStatus.parsed?.data?.canAppend === false &&
|
|
1379
|
+
controlledStatus.parsed?.data?.suggestedAction === "create",
|
|
1380
|
+
reason: "agent_wiki_controlled_status"
|
|
1381
|
+
});
|
|
1382
|
+
|
|
1383
|
+
const createContent = `# CLI Live ${page.title}\n\n${controlledWikiSearchTerm} create ${page.title}`;
|
|
1384
|
+
const controlledCreate = runWave(["osmd", "wiki", "create", page.path, "--content", createContent], env);
|
|
1385
|
+
results.push(controlledCreate);
|
|
1386
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1387
|
+
lines: osmdVerificationLines,
|
|
1388
|
+
label: `osmd.wiki create controlled ${page.title}`,
|
|
1389
|
+
result: controlledCreate,
|
|
1390
|
+
ok:
|
|
1391
|
+
controlledCreate.parsed?.ok === true &&
|
|
1392
|
+
controlledCreate.parsed?.data?.path === page.fullPath &&
|
|
1393
|
+
controlledCreate.parsed?.data?.source === "agent_wiki" &&
|
|
1394
|
+
controlledCreate.parsed?.data?.wikiRole === page.wikiRole &&
|
|
1395
|
+
controlledCreate.parsed?.data?.formatVersion === "agent_markdown_v1" &&
|
|
1396
|
+
controlledCreate.parsed?.data?.exists === true &&
|
|
1397
|
+
controlledCreate.parsed?.data?.canUpdate === true &&
|
|
1398
|
+
controlledCreate.parsed?.data?.canAppend === false &&
|
|
1399
|
+
controlledCreate.parsed?.data?.content === createContent,
|
|
1400
|
+
reason: "agent_wiki_controlled_create"
|
|
1401
|
+
});
|
|
1402
|
+
|
|
1403
|
+
const updateContent = `# CLI Live ${page.title}\n\n${controlledWikiSearchTerm} update ${page.title}`;
|
|
1404
|
+
const controlledUpdate = runWave(["osmd", "wiki", "update", page.path, "--content", updateContent], env);
|
|
1405
|
+
results.push(controlledUpdate);
|
|
1406
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1407
|
+
lines: osmdVerificationLines,
|
|
1408
|
+
label: `osmd.wiki update controlled ${page.title}`,
|
|
1409
|
+
result: controlledUpdate,
|
|
1410
|
+
ok:
|
|
1411
|
+
controlledUpdate.parsed?.ok === true &&
|
|
1412
|
+
controlledUpdate.parsed?.data?.path === page.fullPath &&
|
|
1413
|
+
controlledUpdate.parsed?.data?.source === "agent_wiki" &&
|
|
1414
|
+
controlledUpdate.parsed?.data?.wikiRole === page.wikiRole &&
|
|
1415
|
+
controlledUpdate.parsed?.data?.formatVersion === "agent_markdown_v1" &&
|
|
1416
|
+
controlledUpdate.parsed?.data?.exists === true &&
|
|
1417
|
+
controlledUpdate.parsed?.data?.canUpdate === true &&
|
|
1418
|
+
controlledUpdate.parsed?.data?.canAppend === false &&
|
|
1419
|
+
controlledUpdate.parsed?.data?.content === updateContent,
|
|
1420
|
+
reason: "agent_wiki_controlled_update"
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const logUpdateRejected = runWave(["osmd", "wiki", "update", "log.md", "--content", "verify forbidden"], env);
|
|
1425
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1426
|
+
lines: osmdVerificationLines,
|
|
1427
|
+
label: "osmd.wiki update rejects log locally",
|
|
1428
|
+
result: logUpdateRejected,
|
|
1429
|
+
ok:
|
|
1430
|
+
logUpdateRejected.parsed?.ok === false &&
|
|
1431
|
+
logUpdateRejected.parsed?.status === 400 &&
|
|
1432
|
+
logUpdateRejected.parsed?.error?.code === "invalid_args",
|
|
1433
|
+
reason: "agent_wiki_log_update_local_reject"
|
|
1434
|
+
});
|
|
1435
|
+
|
|
1436
|
+
const arbitraryWikiRejected = runWave(
|
|
1437
|
+
["osmd", "wiki", "create", "random/cli-live-random.md", "--content", "verify forbidden"],
|
|
1438
|
+
env
|
|
1439
|
+
);
|
|
1440
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1441
|
+
lines: osmdVerificationLines,
|
|
1442
|
+
label: "osmd.wiki create rejects arbitrary wiki path locally",
|
|
1443
|
+
result: arbitraryWikiRejected,
|
|
1444
|
+
ok:
|
|
1445
|
+
arbitraryWikiRejected.parsed?.ok === false &&
|
|
1446
|
+
arbitraryWikiRejected.parsed?.status === 400 &&
|
|
1447
|
+
arbitraryWikiRejected.parsed?.error?.code === "invalid_args",
|
|
1448
|
+
reason: "agent_wiki_arbitrary_path_local_reject"
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1333
1451
|
const parentRef = resolveOsmdAgentParentRef();
|
|
1334
1452
|
if (!parentRef) {
|
|
1335
1453
|
osmdVerificationLines.push(
|
|
@@ -1392,6 +1510,174 @@ function runOsmdLiveVerification() {
|
|
|
1392
1510
|
reason: "agent_overlay_update"
|
|
1393
1511
|
});
|
|
1394
1512
|
|
|
1513
|
+
const searchCandidates = (result) => firstArrayValue(result.parsed, [["data", "candidates"]]);
|
|
1514
|
+
const hasOwn = (candidate, key) => Object.prototype.hasOwnProperty.call(candidate ?? {}, key);
|
|
1515
|
+
const hasSearchMetadata = (candidate, expectedSource) =>
|
|
1516
|
+
candidate &&
|
|
1517
|
+
typeof candidate.path === "string" &&
|
|
1518
|
+
candidate.source === expectedSource &&
|
|
1519
|
+
typeof candidate.access === "string" &&
|
|
1520
|
+
typeof candidate.owner === "string" &&
|
|
1521
|
+
hasOwn(candidate, "wikiRole") &&
|
|
1522
|
+
hasOwn(candidate, "formatVersion") &&
|
|
1523
|
+
hasOwn(candidate, "parentRef") &&
|
|
1524
|
+
typeof candidate.exists === "boolean";
|
|
1525
|
+
|
|
1526
|
+
const canonicalSearch = runWave(["osmd", "search", "Wave Tools", "--scope", "os-only", "--limit", "5"], env);
|
|
1527
|
+
results.push(canonicalSearch);
|
|
1528
|
+
const canonicalSearchCandidates = searchCandidates(canonicalSearch);
|
|
1529
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1530
|
+
lines: osmdVerificationLines,
|
|
1531
|
+
label: "osmd.search canonical results include OS metadata",
|
|
1532
|
+
result: canonicalSearch,
|
|
1533
|
+
ok:
|
|
1534
|
+
canonicalSearch.parsed?.ok === true &&
|
|
1535
|
+
canonicalSearch.parsed?.command === "osmd.search" &&
|
|
1536
|
+
typeof canonicalSearch.parsed?.meta?.requestId === "string" &&
|
|
1537
|
+
canonicalSearch.parsed?.data?.scope === "canonical_osmd" &&
|
|
1538
|
+
canonicalSearchCandidates.some(
|
|
1539
|
+
(candidate) =>
|
|
1540
|
+
hasSearchMetadata(candidate, "canonical_osmd") &&
|
|
1541
|
+
candidate.access === "read_only" &&
|
|
1542
|
+
candidate.owner === "system"
|
|
1543
|
+
),
|
|
1544
|
+
reason: "osmd_search_canonical"
|
|
1545
|
+
});
|
|
1546
|
+
|
|
1547
|
+
const wikiSearch = runWave(["osmd", "search", "Agent Wiki", "--scope", "agent-wiki-only", "--limit", "10"], env);
|
|
1548
|
+
results.push(wikiSearch);
|
|
1549
|
+
const wikiSearchCandidates = searchCandidates(wikiSearch);
|
|
1550
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1551
|
+
lines: osmdVerificationLines,
|
|
1552
|
+
label: "osmd.search Agent Wiki results include index and log metadata",
|
|
1553
|
+
result: wikiSearch,
|
|
1554
|
+
ok:
|
|
1555
|
+
wikiSearch.parsed?.ok === true &&
|
|
1556
|
+
wikiSearch.parsed?.data?.scope === "agent_wiki" &&
|
|
1557
|
+
wikiSearchCandidates.some(
|
|
1558
|
+
(candidate) =>
|
|
1559
|
+
hasSearchMetadata(candidate, "agent_wiki") &&
|
|
1560
|
+
candidate.path === "Agent Wiki/index.md" &&
|
|
1561
|
+
candidate.wikiRole === "index"
|
|
1562
|
+
) &&
|
|
1563
|
+
wikiSearchCandidates.some(
|
|
1564
|
+
(candidate) =>
|
|
1565
|
+
hasSearchMetadata(candidate, "agent_wiki") &&
|
|
1566
|
+
candidate.path === "Agent Wiki/log.md" &&
|
|
1567
|
+
candidate.wikiRole === "log" &&
|
|
1568
|
+
candidate.access === "append_only"
|
|
1569
|
+
),
|
|
1570
|
+
reason: "osmd_search_agent_wiki"
|
|
1571
|
+
});
|
|
1572
|
+
|
|
1573
|
+
const controlledWikiSearch = runWave(
|
|
1574
|
+
["osmd", "search", controlledWikiSearchTerm, "--scope", "agent-wiki-only", "--limit", "10"],
|
|
1575
|
+
env
|
|
1576
|
+
);
|
|
1577
|
+
results.push(controlledWikiSearch);
|
|
1578
|
+
const controlledWikiSearchCandidates = searchCandidates(controlledWikiSearch);
|
|
1579
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1580
|
+
lines: osmdVerificationLines,
|
|
1581
|
+
label: "osmd.search Agent Wiki controlled pages",
|
|
1582
|
+
result: controlledWikiSearch,
|
|
1583
|
+
ok:
|
|
1584
|
+
controlledWikiSearch.parsed?.ok === true &&
|
|
1585
|
+
controlledWikiSearch.parsed?.data?.scope === "agent_wiki" &&
|
|
1586
|
+
controlledWikiPages.every((page) =>
|
|
1587
|
+
controlledWikiSearchCandidates.some(
|
|
1588
|
+
(candidate) =>
|
|
1589
|
+
hasSearchMetadata(candidate, "agent_wiki") &&
|
|
1590
|
+
candidate.path === page.fullPath &&
|
|
1591
|
+
candidate.wikiRole === page.wikiRole &&
|
|
1592
|
+
candidate.access === "read_write"
|
|
1593
|
+
)
|
|
1594
|
+
),
|
|
1595
|
+
reason: "osmd_search_agent_wiki_controlled_pages"
|
|
1596
|
+
});
|
|
1597
|
+
|
|
1598
|
+
const controlledCombinedSearch = runWave(
|
|
1599
|
+
["osmd", "search", controlledWikiSearchTerm, "--scope", "combined", "--limit", "10"],
|
|
1600
|
+
env
|
|
1601
|
+
);
|
|
1602
|
+
results.push(controlledCombinedSearch);
|
|
1603
|
+
const controlledCombinedSearchCandidates = searchCandidates(controlledCombinedSearch);
|
|
1604
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1605
|
+
lines: osmdVerificationLines,
|
|
1606
|
+
label: "osmd.search combined includes controlled Agent Wiki pages",
|
|
1607
|
+
result: controlledCombinedSearch,
|
|
1608
|
+
ok:
|
|
1609
|
+
controlledCombinedSearch.parsed?.ok === true &&
|
|
1610
|
+
controlledCombinedSearch.parsed?.data?.scope === "combined" &&
|
|
1611
|
+
controlledWikiPages.some((page) =>
|
|
1612
|
+
controlledCombinedSearchCandidates.some(
|
|
1613
|
+
(candidate) =>
|
|
1614
|
+
hasSearchMetadata(candidate, "agent_wiki") &&
|
|
1615
|
+
candidate.path === page.fullPath &&
|
|
1616
|
+
candidate.wikiRole === page.wikiRole
|
|
1617
|
+
)
|
|
1618
|
+
),
|
|
1619
|
+
reason: "osmd_search_combined_controlled_pages"
|
|
1620
|
+
});
|
|
1621
|
+
|
|
1622
|
+
const logSearch = runWave(
|
|
1623
|
+
["osmd", "search", `CLI live verify log ${verifyStamp}`, "--scope", "agent-wiki-only", "--limit", "5"],
|
|
1624
|
+
env
|
|
1625
|
+
);
|
|
1626
|
+
results.push(logSearch);
|
|
1627
|
+
const logSearchCandidates = searchCandidates(logSearch);
|
|
1628
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1629
|
+
lines: osmdVerificationLines,
|
|
1630
|
+
label: "osmd.search Agent Wiki log content result",
|
|
1631
|
+
result: logSearch,
|
|
1632
|
+
ok:
|
|
1633
|
+
logSearch.parsed?.ok === true &&
|
|
1634
|
+
logSearchCandidates.some(
|
|
1635
|
+
(candidate) =>
|
|
1636
|
+
hasSearchMetadata(candidate, "agent_wiki") &&
|
|
1637
|
+
candidate.path === "Agent Wiki/log.md" &&
|
|
1638
|
+
candidate.wikiRole === "log"
|
|
1639
|
+
),
|
|
1640
|
+
reason: "osmd_search_agent_wiki_log"
|
|
1641
|
+
});
|
|
1642
|
+
|
|
1643
|
+
const notesSearch = runWave(
|
|
1644
|
+
["osmd", "search", notesContent, "--scope", "agent-overlay-only", "--limit", "5"],
|
|
1645
|
+
env
|
|
1646
|
+
);
|
|
1647
|
+
results.push(notesSearch);
|
|
1648
|
+
const notesSearchCandidates = searchCandidates(notesSearch);
|
|
1649
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1650
|
+
lines: osmdVerificationLines,
|
|
1651
|
+
label: "osmd.search agent overlay notes content result",
|
|
1652
|
+
result: notesSearch,
|
|
1653
|
+
ok:
|
|
1654
|
+
notesSearch.parsed?.ok === true &&
|
|
1655
|
+
notesSearch.parsed?.data?.scope === "agent_overlay" &&
|
|
1656
|
+
notesSearchCandidates.some(
|
|
1657
|
+
(candidate) =>
|
|
1658
|
+
hasSearchMetadata(candidate, "agent_overlay") &&
|
|
1659
|
+
candidate.path.endsWith("/.agent/notes.md") &&
|
|
1660
|
+
candidate.wikiRole === "notes" &&
|
|
1661
|
+
candidate.parentRef === parentRef
|
|
1662
|
+
),
|
|
1663
|
+
reason: "osmd_search_agent_overlay_notes"
|
|
1664
|
+
});
|
|
1665
|
+
|
|
1666
|
+
const combinedSearch = runWave(["osmd", "search", "Wave", "--scope", "combined", "--limit", "3"], env);
|
|
1667
|
+
results.push(combinedSearch);
|
|
1668
|
+
osmdVerificationFailures += recordExactCheck({
|
|
1669
|
+
lines: osmdVerificationLines,
|
|
1670
|
+
label: "osmd.search combined scope returns stable envelope",
|
|
1671
|
+
result: combinedSearch,
|
|
1672
|
+
ok:
|
|
1673
|
+
combinedSearch.parsed?.ok === true &&
|
|
1674
|
+
combinedSearch.parsed?.command === "osmd.search" &&
|
|
1675
|
+
combinedSearch.parsed?.data?.scope === "combined" &&
|
|
1676
|
+
Array.isArray(combinedSearch.parsed?.data?.candidates) &&
|
|
1677
|
+
typeof combinedSearch.parsed?.meta?.requestId === "string",
|
|
1678
|
+
reason: "osmd_search_combined"
|
|
1679
|
+
});
|
|
1680
|
+
|
|
1395
1681
|
}
|
|
1396
1682
|
|
|
1397
1683
|
runOsmdLiveVerification();
|