@markii/host 0.0.1 → 0.17.0-next.3
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 +20 -2
- package/dist/browser-worker.js +639 -0
- package/dist/browser.d.ts +61 -0
- package/dist/browser.js +172 -0
- package/dist/conformance/host/01-plain-open/expected.json +5 -0
- package/dist/conformance/host/01-plain-open/note.mk.md +8 -0
- package/dist/conformance/host/01-plain-open/scenario.json +6 -0
- package/dist/conformance/host/02-run-manual-grant-accepted/expected.json +16 -0
- package/dist/conformance/host/02-run-manual-grant-accepted/note.mk.md +5 -0
- package/dist/conformance/host/02-run-manual-grant-accepted/scenario.json +14 -0
- package/dist/conformance/host/03-run-manual-grant-refused/expected.json +18 -0
- package/dist/conformance/host/03-run-manual-grant-refused/note.mk.md +5 -0
- package/dist/conformance/host/03-run-manual-grant-refused/scenario.json +14 -0
- package/dist/conformance/host/04-run-auto-write-denied/expected.json +16 -0
- package/dist/conformance/host/04-run-auto-write-denied/note.mk.md +10 -0
- package/dist/conformance/host/04-run-auto-write-denied/scenario.json +13 -0
- package/dist/conformance/host/05-export-html-pack-directive/expected.json +14 -0
- package/dist/conformance/host/05-export-html-pack-directive/note.mk.md +8 -0
- package/dist/conformance/host/05-export-html-pack-directive/scenario.json +6 -0
- package/dist/conformance/host/06-install-pack-then-render/expected.json +18 -0
- package/dist/conformance/host/06-install-pack-then-render/files/ana-1.0.0/pack.json +13 -0
- package/dist/conformance/host/06-install-pack-then-render/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/06-install-pack-then-render/note.mk.md +5 -0
- package/dist/conformance/host/06-install-pack-then-render/scenario.json +15 -0
- package/dist/conformance/host/07-complete-in-directive/expected.json +14 -0
- package/dist/conformance/host/07-complete-in-directive/note.mk.md +3 -0
- package/dist/conformance/host/07-complete-in-directive/scenario.json +6 -0
- package/dist/conformance/host/08-hover-standard-component/expected.json +5 -0
- package/dist/conformance/host/08-hover-standard-component/note.mk.md +5 -0
- package/dist/conformance/host/08-hover-standard-component/scenario.json +6 -0
- package/dist/conformance/host/09-insert-skeleton/expected.json +5 -0
- package/dist/conformance/host/09-insert-skeleton/note.mk.md +4 -0
- package/dist/conformance/host/09-insert-skeleton/scenario.json +6 -0
- package/dist/conformance/host/10-scripts-disabled/expected.json +11 -0
- package/dist/conformance/host/10-scripts-disabled/note.mk.md +5 -0
- package/dist/conformance/host/10-scripts-disabled/scenario.json +9 -0
- package/dist/conformance/host/11-complete-closing-fence/expected.json +5 -0
- package/dist/conformance/host/11-complete-closing-fence/note.mk.md +5 -0
- package/dist/conformance/host/11-complete-closing-fence/scenario.json +12 -0
- package/dist/conformance/host/12-complete-nested-container/expected.json +5 -0
- package/dist/conformance/host/12-complete-nested-container/note.mk.md +5 -0
- package/dist/conformance/host/12-complete-nested-container/scenario.json +12 -0
- package/dist/conformance/host/13-install-pack-declined/expected.json +12 -0
- package/dist/conformance/host/13-install-pack-declined/files/ana-1.0.0/pack.json +13 -0
- package/dist/conformance/host/13-install-pack-declined/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/13-install-pack-declined/note.mk.md +5 -0
- package/dist/conformance/host/13-install-pack-declined/scenario.json +10 -0
- package/dist/conformance/host/14-remove-pack/expected.json +14 -0
- package/dist/conformance/host/14-remove-pack/files/ana-1.0.0/pack.json +13 -0
- package/dist/conformance/host/14-remove-pack/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/14-remove-pack/note.mk.md +5 -0
- package/dist/conformance/host/14-remove-pack/scenario.json +11 -0
- package/dist/conformance/host/15-load-packs-engine-views/expected.json +19 -0
- package/dist/conformance/host/15-load-packs-engine-views/files/duo-1.0.0/pack.json +9 -0
- package/dist/conformance/host/15-load-packs-engine-views/files/duo-1.0.0/webview.js +1 -0
- package/dist/conformance/host/15-load-packs-engine-views/note.mk.md +9 -0
- package/dist/conformance/host/15-load-packs-engine-views/scenario.json +10 -0
- package/dist/conformance/host/16-pack-trust/expected.json +37 -0
- package/dist/conformance/host/16-pack-trust/files/ana-1.0.0/pack.json +12 -0
- package/dist/conformance/host/16-pack-trust/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/16-pack-trust/files/sneaky-1.0.0/pack.json +12 -0
- package/dist/conformance/host/16-pack-trust/files/sneaky-1.0.0/webview.js +1 -0
- package/dist/conformance/host/16-pack-trust/note.mk.md +5 -0
- package/dist/conformance/host/16-pack-trust/scenario.json +26 -0
- package/dist/conformance/host/README.md +221 -0
- package/dist/conformance.d.ts +2 -0
- package/dist/conformance.js +5 -0
- package/dist/diagnostics/render-diagnostics.d.ts +41 -0
- package/dist/diagnostics/render-diagnostics.js +46 -0
- package/dist/export/cascade.d.ts +98 -0
- package/dist/export/cascade.js +159 -0
- package/dist/export/export-zip.d.ts +19 -0
- package/dist/export/export-zip.js +38 -0
- package/dist/export/image-embed.d.ts +126 -0
- package/dist/export/image-embed.js +274 -0
- package/dist/export/note-export.d.ts +332 -0
- package/dist/export/note-export.js +366 -0
- package/dist/export/note-links.d.ts +83 -0
- package/dist/export/note-links.js +241 -0
- package/dist/glue.wasm +0 -0
- package/dist/host/adapter.d.ts +218 -0
- package/dist/host/adapter.js +9 -0
- package/dist/host/cascade-export-behavior.d.ts +120 -0
- package/dist/host/cascade-export-behavior.js +151 -0
- package/dist/host/conformance-runner.d.ts +159 -0
- package/dist/host/conformance-runner.js +632 -0
- package/dist/host/create-host.d.ts +251 -0
- package/dist/host/create-host.js +329 -0
- package/dist/host/editor-behavior.d.ts +153 -0
- package/dist/host/editor-behavior.js +223 -0
- package/dist/host/export/md-plain.d.ts +15 -0
- package/dist/host/export/md-plain.js +125 -0
- package/dist/host/export-behavior.d.ts +111 -0
- package/dist/host/export-behavior.js +257 -0
- package/dist/host/labels.d.ts +23 -0
- package/dist/host/labels.js +32 -0
- package/dist/host/pack-archive.d.ts +30 -0
- package/dist/host/pack-archive.js +62 -0
- package/dist/host/pack-install.d.ts +87 -0
- package/dist/host/pack-install.js +186 -0
- package/dist/host/pack-load.d.ts +71 -0
- package/dist/host/pack-load.js +57 -0
- package/dist/host/pack-remove.d.ts +21 -0
- package/dist/host/pack-remove.js +65 -0
- package/dist/host/pack-trust-behavior.d.ts +79 -0
- package/dist/host/pack-trust-behavior.js +262 -0
- package/dist/host/refresh-interval.d.ts +37 -0
- package/dist/host/refresh-interval.js +59 -0
- package/dist/host/run-behavior.d.ts +88 -0
- package/dist/host/run-behavior.js +189 -0
- package/dist/host/run-diagnostics.d.ts +26 -0
- package/dist/host/run-diagnostics.js +43 -0
- package/dist/host/script-execution.d.ts +72 -0
- package/dist/host/script-execution.js +68 -0
- package/dist/host/terminal-packs.d.ts +39 -0
- package/dist/host/terminal-packs.js +51 -0
- package/dist/html-engine.d.ts +2 -0
- package/dist/html-engine.js +29 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +69 -0
- package/dist/insert/component-catalog.d.ts +23 -0
- package/dist/insert/component-catalog.js +96 -0
- package/dist/node-fs.d.ts +14 -0
- package/dist/node-fs.js +70 -0
- package/dist/node-worker.js +20657 -0
- package/dist/node.d.ts +6 -0
- package/dist/node.js +13 -0
- package/dist/package.json +3 -0
- package/dist/packs/discover.d.ts +119 -0
- package/dist/packs/discover.js +266 -0
- package/dist/packs/pack-diagnostics.d.ts +79 -0
- package/dist/packs/pack-diagnostics.js +103 -0
- package/dist/packs/pack-paths.d.ts +53 -0
- package/dist/packs/pack-paths.js +105 -0
- package/dist/packs/pack-render-registry.d.ts +82 -0
- package/dist/packs/pack-render-registry.js +182 -0
- package/dist/packs/pack-scripts.d.ts +20 -0
- package/dist/packs/pack-scripts.js +96 -0
- package/dist/packs/pack-trust.d.ts +57 -0
- package/dist/packs/pack-trust.js +111 -0
- package/dist/packs/prebuilt.d.ts +49 -0
- package/dist/packs/prebuilt.js +97 -0
- package/dist/path-util.d.ts +24 -0
- package/dist/path-util.js +82 -0
- package/dist/run/browser-isolate.d.ts +45 -0
- package/dist/run/browser-isolate.js +85 -0
- package/dist/run/bundle-document.d.ts +29 -0
- package/dist/run/bundle-document.js +40 -0
- package/dist/run/bundle-run.d.ts +188 -0
- package/dist/run/bundle-run.js +232 -0
- package/dist/run/grant-flow.d.ts +232 -0
- package/dist/run/grant-flow.js +390 -0
- package/dist/run/ip-address.d.ts +41 -0
- package/dist/run/ip-address.js +255 -0
- package/dist/run/isolate.d.ts +59 -0
- package/dist/run/isolate.js +22 -0
- package/dist/run/lua-resolver.d.ts +21 -0
- package/dist/run/lua-resolver.js +63 -0
- package/dist/run/net-bridge-worker.d.ts +26 -0
- package/dist/run/net-bridge-worker.js +66 -0
- package/dist/run/net-bridge.d.ts +56 -0
- package/dist/run/net-bridge.js +59 -0
- package/dist/run/net-pinning.d.ts +82 -0
- package/dist/run/net-pinning.js +137 -0
- package/dist/run/net-provider.d.ts +72 -0
- package/dist/run/net-provider.js +303 -0
- package/dist/run/node-isolate.d.ts +22 -0
- package/dist/run/node-isolate.js +68 -0
- package/dist/run/run-flow.d.ts +186 -0
- package/dist/run/run-flow.js +323 -0
- package/dist/run/run-host.d.ts +107 -0
- package/dist/run/run-host.js +241 -0
- package/dist/run/run-job.d.ts +130 -0
- package/dist/run/run-job.js +279 -0
- package/dist/run/run-progress.d.ts +55 -0
- package/dist/run/run-progress.js +42 -0
- package/dist/run/run-trace.d.ts +44 -0
- package/dist/run/run-trace.js +36 -0
- package/dist/run/script-requirements.d.ts +98 -0
- package/dist/run/script-requirements.js +212 -0
- package/dist/run/snapshot-storage.d.ts +25 -0
- package/dist/run/snapshot-storage.js +31 -0
- package/dist/run/stale-values.d.ts +25 -0
- package/dist/run/stale-values.js +32 -0
- package/dist/run/worker-entry-browser.d.ts +62 -0
- package/dist/run/worker-entry-browser.js +172 -0
- package/dist/run/worker-entry.d.ts +1 -0
- package/dist/run/worker-entry.js +98 -0
- package/dist/values-failure.d.ts +17 -0
- package/dist/values-failure.js +1 -0
- package/dist/values-merge.d.ts +39 -0
- package/dist/values-merge.js +33 -0
- package/package.json +80 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__markiiRegisterPack(() => ({}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "install-pack-declined",
|
|
3
|
+
"invariant": "declining the install consent writes nothing: the pack stays uninstalled and removing it reports that it was never installed",
|
|
4
|
+
"clock": 1700000000000,
|
|
5
|
+
"actions": [
|
|
6
|
+
{ "type": "open" },
|
|
7
|
+
{ "type": "installPack", "archive": "files/ana-1.0.0", "answers": ["deny"] },
|
|
8
|
+
{ "type": "removePack", "namespace": "ana" }
|
|
9
|
+
]
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"outcomes": [
|
|
3
|
+
{ "kind": "opened" },
|
|
4
|
+
{ "kind": "installed", "namespace": "ana", "replaced": false },
|
|
5
|
+
{ "kind": "removed", "namespace": "ana" },
|
|
6
|
+
{ "kind": "not-installed", "namespace": "ana" }
|
|
7
|
+
],
|
|
8
|
+
"diagnostics": [
|
|
9
|
+
"Install pack from file installed pack \"ana\"",
|
|
10
|
+
"Remove pack removed \"ana\"",
|
|
11
|
+
"Remove pack found no installed pack \"ana\""
|
|
12
|
+
],
|
|
13
|
+
"prompts": ["Installing \"ana\" lets its code run inside"]
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__markiiRegisterPack(() => ({}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "remove-pack",
|
|
3
|
+
"invariant": "removing an installed pack deletes its folder; removing it again reports that it is not installed",
|
|
4
|
+
"clock": 1700000000000,
|
|
5
|
+
"actions": [
|
|
6
|
+
{ "type": "open" },
|
|
7
|
+
{ "type": "installPack", "archive": "files/ana-1.0.0", "answers": ["allow"] },
|
|
8
|
+
{ "type": "removePack", "namespace": "ana" },
|
|
9
|
+
{ "type": "removePack", "namespace": "ana" }
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"outcomes": [
|
|
3
|
+
{ "kind": "opened" },
|
|
4
|
+
{ "kind": "installed", "namespace": "duo", "replaced": false },
|
|
5
|
+
{
|
|
6
|
+
"kind": "loaded",
|
|
7
|
+
"namespaces": ["duo"],
|
|
8
|
+
"componentCount": 2,
|
|
9
|
+
"unavailableCount": 1
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"diagnostics": [
|
|
13
|
+
"Install pack from file installed pack \"duo\" from \"files/duo-1.0.0\"",
|
|
14
|
+
"Loaded pack \"duo\" (namespace: duo, 1 component)"
|
|
15
|
+
],
|
|
16
|
+
"prompts": [
|
|
17
|
+
"Installing \"duo\" lets its code run inside"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__markiiRegisterPack(() => ({}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "load-packs-engine-views",
|
|
3
|
+
"invariant": "loading packs reports every installed component and the ones this host's engine has no view for",
|
|
4
|
+
"clock": 1700000000000,
|
|
5
|
+
"actions": [
|
|
6
|
+
{ "type": "open" },
|
|
7
|
+
{ "type": "installPack", "archive": "files/duo-1.0.0", "answers": ["allow"] },
|
|
8
|
+
{ "type": "loadPacks" }
|
|
9
|
+
]
|
|
10
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"outcomes": [
|
|
3
|
+
{ "kind": "opened" },
|
|
4
|
+
{ "kind": "installed", "namespace": "ana", "replaced": false },
|
|
5
|
+
{ "kind": "placed", "namespace": "sneaky" },
|
|
6
|
+
{ "kind": "listed", "enabled": ["ana"], "notEnabled": ["sneaky"] },
|
|
7
|
+
{ "kind": "loaded", "namespaces": ["ana"] },
|
|
8
|
+
{ "kind": "enabled", "namespace": "sneaky" },
|
|
9
|
+
{ "kind": "loaded", "namespaces": ["ana", "sneaky"] },
|
|
10
|
+
{ "kind": "disabled", "namespace": "ana" },
|
|
11
|
+
{ "kind": "listed", "enabled": ["sneaky"], "notEnabled": ["ana"] },
|
|
12
|
+
{ "kind": "loaded", "namespaces": ["sneaky"] },
|
|
13
|
+
{ "kind": "enabled", "namespace": "ana" },
|
|
14
|
+
{ "kind": "removed", "namespace": "sneaky" },
|
|
15
|
+
{ "kind": "listed", "enabled": ["ana"], "notEnabled": [] },
|
|
16
|
+
{ "kind": "not-installed", "namespace": "ghost" }
|
|
17
|
+
],
|
|
18
|
+
"diagnostics": [
|
|
19
|
+
"Install pack from file installed pack \"ana\"",
|
|
20
|
+
"Loaded pack \"ana\" (namespace: ana, 1 component)",
|
|
21
|
+
"Pack \"sneaky\" is present but not enabled on this device; it was not loaded.",
|
|
22
|
+
"Enable pack enabled \"sneaky\"",
|
|
23
|
+
"Loaded pack \"ana\" (namespace: ana, 1 component)",
|
|
24
|
+
"Loaded pack \"sneaky\" (namespace: sneaky, 1 component)",
|
|
25
|
+
"Disable pack disabled \"ana\"",
|
|
26
|
+
"Loaded pack \"sneaky\" (namespace: sneaky, 1 component)",
|
|
27
|
+
"Pack \"ana\" is present but not enabled on this device; it was not loaded.",
|
|
28
|
+
"Enable pack enabled \"ana\"",
|
|
29
|
+
"Remove pack removed \"sneaky\"",
|
|
30
|
+
"Enable pack found no installed pack \"ghost\""
|
|
31
|
+
],
|
|
32
|
+
"prompts": [
|
|
33
|
+
"Installing \"ana\" lets its code run inside",
|
|
34
|
+
"Installing \"sneaky\" lets its code run inside",
|
|
35
|
+
"Installing \"ana\" lets its code run inside"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__markiiRegisterPack(() => ({}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__markiiRegisterPack(() => ({}));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "pack-trust",
|
|
3
|
+
"invariant": "an installed pack folder loads only while this device's trust list names it: a folder that arrives without consent is listed as present and never loaded, and enable, disable, re-enable and remove move the list accordingly",
|
|
4
|
+
"clock": 1700000000000,
|
|
5
|
+
"actions": [
|
|
6
|
+
{ "type": "open" },
|
|
7
|
+
{
|
|
8
|
+
"type": "installPack",
|
|
9
|
+
"archive": "files/ana-1.0.0",
|
|
10
|
+
"answers": ["allow"],
|
|
11
|
+
"requiresTrust": true
|
|
12
|
+
},
|
|
13
|
+
{ "type": "placePack", "archive": "files/sneaky-1.0.0", "namespace": "sneaky" },
|
|
14
|
+
{ "type": "listPacks" },
|
|
15
|
+
{ "type": "loadPacks", "requiresTrust": true },
|
|
16
|
+
{ "type": "enablePack", "namespace": "sneaky", "answers": ["allow"] },
|
|
17
|
+
{ "type": "loadPacks", "requiresTrust": true },
|
|
18
|
+
{ "type": "disablePack", "namespace": "ana" },
|
|
19
|
+
{ "type": "listPacks" },
|
|
20
|
+
{ "type": "loadPacks", "requiresTrust": true },
|
|
21
|
+
{ "type": "enablePack", "namespace": "ana", "answers": ["allow"] },
|
|
22
|
+
{ "type": "removePack", "namespace": "sneaky", "requiresTrust": true },
|
|
23
|
+
{ "type": "listPacks" },
|
|
24
|
+
{ "type": "enablePack", "namespace": "ghost" }
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Host conformance corpus (seed)
|
|
2
|
+
|
|
3
|
+
Language-agnostic scenarios proving that any `HostAdapter` (VS Code,
|
|
4
|
+
Obsidian, the CLI, or a future host) drives `@markii/host`'s shared
|
|
5
|
+
behaviors the same way. Per the repo rule, this directory is plain data:
|
|
6
|
+
no TypeScript. `packages/markii-host/src/host/conformance-runner.ts` is
|
|
7
|
+
the one place that reads it, drives it through a real adapter, and
|
|
8
|
+
compares the outcome.
|
|
9
|
+
|
|
10
|
+
## Directory shape
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
conformance/host/<nn>-<slug>/note.mk.md the note under test
|
|
14
|
+
conformance/host/<nn>-<slug>/scenario.json the ordered actions
|
|
15
|
+
conformance/host/<nn>-<slug>/expected.json the outcomes
|
|
16
|
+
conformance/host/<nn>-<slug>/files/… optional extra inputs
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
A scenario that installs a pack ships its archive as a plain `files/<name>/`
|
|
20
|
+
directory (a `pack.json`, a `webview.js`, and so on) rather than a
|
|
21
|
+
committed `.mkp` binary. The runner zips that directory into archive bytes
|
|
22
|
+
at test time (`zipArchiveDirectory`).
|
|
23
|
+
|
|
24
|
+
## `scenario.json`
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"id": "run-grant-accepted",
|
|
29
|
+
"invariant": "one sentence: what every conforming host must do here",
|
|
30
|
+
"clock": 1700000000000,
|
|
31
|
+
"actions": [
|
|
32
|
+
{ "type": "open" },
|
|
33
|
+
{
|
|
34
|
+
"type": "run",
|
|
35
|
+
"trigger": "manual",
|
|
36
|
+
"answers": ["allow"],
|
|
37
|
+
"simulate": { "name": "total", "value": 3, "requiresHost": "api.example.com" }
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Every action has a `type`. The full set, and the capability each one
|
|
44
|
+
needs, is the runner's own `ACTION_CAPABILITY` map:
|
|
45
|
+
|
|
46
|
+
| action | needs |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `open` | (always supported) |
|
|
49
|
+
| `run` | `isolate` |
|
|
50
|
+
| `exportHtml` | `export-format` (`html`) |
|
|
51
|
+
| `exportAnsi` | `export-format` (`ansi`) |
|
|
52
|
+
| `installPack` | `packs` (and an `installRoot`) |
|
|
53
|
+
| `loadPacks` | `packs` |
|
|
54
|
+
| `removePack` | `packs` (and an `installRoot` plus `removeFolder`) |
|
|
55
|
+
| `placePack` | `pack-trust` |
|
|
56
|
+
| `listPacks` | `pack-trust` |
|
|
57
|
+
| `enablePack` | `pack-trust` |
|
|
58
|
+
| `disablePack` | `pack-trust` |
|
|
59
|
+
| `completeAt` | `editor` |
|
|
60
|
+
| `hoverAt` | `editor` |
|
|
61
|
+
| `insertComponent` | `editor` |
|
|
62
|
+
|
|
63
|
+
`pack-trust` is declared by an adapter whose pack source sets
|
|
64
|
+
`trust: 'device-list'` (and an `installRoot`): installed packs load only
|
|
65
|
+
while this device's trust list names them. `placePack` copies a scenario
|
|
66
|
+
directory into the install root with no consent and no trust entry, the way
|
|
67
|
+
a pack arrives through a file sync. An `installPack`, `loadPacks` or
|
|
68
|
+
`removePack` action may carry `"requiresTrust": true`, which makes the
|
|
69
|
+
runner treat it as a `pack-trust` action, so a scenario built around the
|
|
70
|
+
trust list reports `unsupported` as a whole on a host that trusts its own
|
|
71
|
+
install store.
|
|
72
|
+
|
|
73
|
+
`clock` fixes `adapter.now()` for the whole scenario, so a `RunTrace`
|
|
74
|
+
write is byte-stable.
|
|
75
|
+
|
|
76
|
+
`run` and `installPack` actions carry an optional `answers` array:
|
|
77
|
+
`"allow"`/`"deny"`, consumed by the grant/consent prompts in document
|
|
78
|
+
order across the WHOLE scenario, not just within one action (a scenario
|
|
79
|
+
with two consecutive prompts pulls its second answer from the same
|
|
80
|
+
queue). A prompt asked with no answer left is an ERROR the runner
|
|
81
|
+
reports, never a silent deny: it means the scenario and the
|
|
82
|
+
implementation disagree about how many questions get asked, which is
|
|
83
|
+
exactly the drift this corpus exists to catch.
|
|
84
|
+
|
|
85
|
+
A `run` action's `simulate` field stands in for what a real Lua isolate
|
|
86
|
+
would have produced:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{ "name": "total", "value": 3, "requiresHost": "api.example.com", "requiresManualTier": false }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- `name`: the script/value name the simulated run reports on.
|
|
93
|
+
- `value`: what a successful simulated run stores (default `1`).
|
|
94
|
+
- `requiresHost`: the run reports `capability-denied` unless this host is
|
|
95
|
+
in the run's granted allowlist. The allowlist itself is REAL: the note's
|
|
96
|
+
own script is scanned for `net.*` calls, and the grant flow prompts for
|
|
97
|
+
and persists exactly what it always does. Only the isolate that would
|
|
98
|
+
execute the script is faked.
|
|
99
|
+
- `requiresManualTier`: the run reports `tier-blocked` under any trigger
|
|
100
|
+
but `'manual'`, regardless of grants — the same enforcement the real
|
|
101
|
+
sandbox applies to an effectful call under a read-only trigger.
|
|
102
|
+
|
|
103
|
+
Faking the isolate keeps this corpus fast and deterministic. It proves the
|
|
104
|
+
HOST-LEVEL plumbing — grant prompts, wording, capability declarations,
|
|
105
|
+
trigger forwarding — is identical across hosts. Real sandbox enforcement
|
|
106
|
+
(the tier gate, the net allowlist, the marshal boundary) is
|
|
107
|
+
`conformance/executor/`'s job and is not duplicated here.
|
|
108
|
+
|
|
109
|
+
A `run` action can also carry `"scriptsDisabled": true`. This is not a
|
|
110
|
+
`HostAdapter` capability: the device-local scripts-off switch is decided
|
|
111
|
+
by each app's own call site before it ever reaches the isolate, over the
|
|
112
|
+
shared, host-neutral wording in `@markii/host`'s `script-execution.ts`.
|
|
113
|
+
The runner reproduces that same pre-check here, over the same functions
|
|
114
|
+
and the adapter's own `labels`, so the scenario proves wording parity
|
|
115
|
+
without inventing a capability the contract does not have. When this
|
|
116
|
+
field is set, the action never reaches `host.run` at all.
|
|
117
|
+
|
|
118
|
+
## `expected.json`
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"outcomes": [
|
|
123
|
+
{ "kind": "opened" },
|
|
124
|
+
{ "kind": "ran", "values": { "total": 3 }, "failureKinds": [] },
|
|
125
|
+
{ "kind": "exported", "contains": ["mk-callout"], "excludes": ["<script"] }
|
|
126
|
+
],
|
|
127
|
+
"diagnostics": ["one line per expected diagnostics write, in order"],
|
|
128
|
+
"prompts": ["the message text of each prompt asked, in order"]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`outcomes[i]` corresponds to `actions[i]`. Comparisons are deliberately
|
|
133
|
+
coarse, matching each `kind`:
|
|
134
|
+
|
|
135
|
+
- `ran`: `values` compares the landed, non-error `StoredValue`s by name
|
|
136
|
+
(`{name: value}`); `failureKinds` compares the closed `FailureKind`
|
|
137
|
+
taxonomy only, never a raw message or a timing; an optional `traceOk`
|
|
138
|
+
compares the recorded run trace's `ok` flag.
|
|
139
|
+
- `exported`: `contains`/`excludes` are substrings checked against the
|
|
140
|
+
written file's content, never the whole document — the render corpora
|
|
141
|
+
already pin bytes.
|
|
142
|
+
- `installed`: `namespace` and `replaced`.
|
|
143
|
+
- `declined`: `step` (`'consent'`/`'replace'`, or absent for the
|
|
144
|
+
scripts-disabled synthetic outcome) and `reasonContains`, a substring of
|
|
145
|
+
the user-facing reason.
|
|
146
|
+
- `listed`: `enabled` and `notEnabled`, namespace lists, order-independent.
|
|
147
|
+
- `enabled`, `disabled`, `placed`, `removed`: `namespace`.
|
|
148
|
+
- `loaded`: `namespaces`, order-independent.
|
|
149
|
+
- `completions`: `labels`, checked as "every one of these appears",
|
|
150
|
+
not an exact set (a pack-aware host's catalog is a superset of the
|
|
151
|
+
standard one). Optional `replaceStart`, `replaceEnd`, and `tokenStart`
|
|
152
|
+
compare the column span an accepted item replaces and where filtering
|
|
153
|
+
starts; `fenceEditCount` compares how many fence rewrites travel with an
|
|
154
|
+
accepted container item.
|
|
155
|
+
- `hover`: `contains`, a substring of the hover text. Optional `start` and
|
|
156
|
+
`end` compare the hovered name's columns.
|
|
157
|
+
- every other `kind` (`opened`, `none`, `not-found`, `failed`, `rejected`,
|
|
158
|
+
`reserved`, `cancelled`, `inserted`): `kind` equality is the whole check.
|
|
159
|
+
|
|
160
|
+
An action whose capability the adapter under test does not declare is
|
|
161
|
+
never diffed against `expected.json` at all (see "Capability handling"
|
|
162
|
+
below) — `expected.json` always describes the FULLY CAPABLE host's
|
|
163
|
+
correct behavior, even for a scenario where one real host today has
|
|
164
|
+
nothing to compare it to.
|
|
165
|
+
|
|
166
|
+
`diagnostics` and `prompts` are matched pairwise, in order, by substring
|
|
167
|
+
containment (`actual[i].includes(expected[i])`), with the array LENGTHS
|
|
168
|
+
required to match exactly. Substring containment absorbs a host's own
|
|
169
|
+
sink additions (Obsidian's `[markii] ` console prefix, a device noun
|
|
170
|
+
difference) without the corpus having to spell out three wordings for
|
|
171
|
+
one behavior. Diagnostics lines written by a capability decline itself
|
|
172
|
+
(`declined (<capability> unsupported on <host>): …`) are filtered out of
|
|
173
|
+
the actual list before this comparison, since that line exists only
|
|
174
|
+
because the capability was ABSENT — it is not part of what
|
|
175
|
+
`expected.json` describes.
|
|
176
|
+
|
|
177
|
+
`prompts` is load-bearing: it proves all three hosts ask the same
|
|
178
|
+
questions, worded the same way, in the same order — the single most
|
|
179
|
+
security-relevant parity property in this batch.
|
|
180
|
+
|
|
181
|
+
## Capability handling (the crux)
|
|
182
|
+
|
|
183
|
+
The corpus never encodes per-host knowledge. `ACTION_CAPABILITY`
|
|
184
|
+
(`conformance-runner.ts`) is the one static map from an action's type to
|
|
185
|
+
the capability it needs. When the adapter under test does not declare
|
|
186
|
+
that capability, the runner produces `{ "kind": "unsupported",
|
|
187
|
+
"capability": "<name>" }` for that action and never diffs it against
|
|
188
|
+
`expected.json`. An app's conformance test asserts: for every action
|
|
189
|
+
whose capability this adapter declares, the outcome equals
|
|
190
|
+
`expected.json`'s; for every other action, the outcome is exactly the
|
|
191
|
+
`unsupported` record.
|
|
192
|
+
|
|
193
|
+
This is what lets the CLI, which declares no `editor`,
|
|
194
|
+
run the whole corpus honestly: its result records say `unsupported`
|
|
195
|
+
where it genuinely offers nothing, which is the truth and is visible,
|
|
196
|
+
rather than a skipped test or a faked empty answer.
|
|
197
|
+
|
|
198
|
+
## The sixteen scenarios
|
|
199
|
+
|
|
200
|
+
| id | what it proves |
|
|
201
|
+
|---|---|
|
|
202
|
+
| `01-plain-open` | a note with no scripts and no packs opens, renders, writes no diagnostics |
|
|
203
|
+
| `02-run-manual-grant-accepted` | manual tier, one network host, prompt asked with the canonical wording, grant stored, value lands |
|
|
204
|
+
| `03-run-manual-grant-refused` | the same prompt, refused, no value lands, the run reports on both surfaces |
|
|
205
|
+
| `04-run-auto-write-denied` | an auto trigger is read-only: a write attempt is denied by the tier gate, not by luck |
|
|
206
|
+
| `05-export-html-pack-directive` | a pack directive the host did not load exports as the unknown-component fallback, and the export excludes script machinery |
|
|
207
|
+
| `06-install-pack-then-render` | installing a `.mkp` loads its namespace; a second install of the same namespace asks before replacing |
|
|
208
|
+
| `07-complete-in-directive` | completion inside a directive returns the standard set |
|
|
209
|
+
| `08-hover-standard-component` | hover on a standard component returns its documented attributes |
|
|
210
|
+
| `09-insert-skeleton` | inserting a component applies one edit |
|
|
211
|
+
| `10-scripts-disabled` | the device switch blocks the run before the isolate, and says so on both surfaces |
|
|
212
|
+
| `11-complete-closing-fence` | a bare colon run that closes an open container offers nothing, as `none` rather than a failure |
|
|
213
|
+
| `12-complete-nested-container` | completing a container inside an equal-length container carries the fence edits that keep the pair legal |
|
|
214
|
+
| `13-install-pack-declined` | declining the install consent writes nothing, and removing the never-installed pack reports it |
|
|
215
|
+
| `14-remove-pack` | removing an installed pack deletes it; removing it again reports it is not installed |
|
|
216
|
+
| `15-load-packs-engine-views` | loading packs reports every installed component and, as `unavailable`, the ones this host's engine has no view for |
|
|
217
|
+
| `16-pack-trust` | a folder that arrives without consent is listed as present and never loaded; enable, disable, re-enable and remove move the device trust list; a host without the list reports the whole scenario `unsupported` |
|
|
218
|
+
|
|
219
|
+
See `tmp/W11-phase3.md` for which capabilities each of the three real
|
|
220
|
+
adapters currently declares, and which scenarios are consequently
|
|
221
|
+
`unsupported` on every host today (a reported gap, not a corpus defect).
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { ACTION_CAPABILITY, assertHostScenario, containsInOrder, createAnswerQueue, hostConformanceDir, hostDeclaresCapability, listHostScenarioNames, loadHostScenario, outcomeMismatches, runHostScenario, zipArchiveDirectory, } from './host/conformance-runner.js';
|
|
2
|
+
export type { HostScenario, HostScenarioAction, HostScenarioCapability, HostScenarioExpected, HostScenarioRunResult, LoadedHostScenario, RunSimulation, } from './host/conformance-runner.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @markii/host/conformance: the host conformance runner. Node only (it reads
|
|
2
|
+
// the corpus from disk and drives a real adapter). A host's adapter test
|
|
3
|
+
// imports this to run `conformance/host/` against its own `HostAdapter`.
|
|
4
|
+
// The corpus ships inside the package at `dist/conformance/host/`.
|
|
5
|
+
export { ACTION_CAPABILITY, assertHostScenario, containsInOrder, createAnswerQueue, hostConformanceDir, hostDeclaresCapability, listHostScenarioNames, loadHostScenario, outcomeMismatches, runHostScenario, zipArchiveDirectory, } from './host/conformance-runner.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a render-time diagnostic event becomes a line on a host's
|
|
3
|
+
* diagnostics surface (docs/integration.md's host checklist, item 9).
|
|
4
|
+
*
|
|
5
|
+
* Both renderers report a quiet in-page marker through their `onDiagnostic`
|
|
6
|
+
* render option (`@markii/stdlib`'s `DiagnosticEvent`). The marker alone
|
|
7
|
+
* satisfies half of AGENTS.md's "clean is not silent" rule: the other half
|
|
8
|
+
* is a full diagnostic somewhere a reader can find without opening
|
|
9
|
+
* developer tools. This module turns one event into the line both hosts
|
|
10
|
+
* write, so the VS Code output channel and the Obsidian console cannot word
|
|
11
|
+
* the same finding differently.
|
|
12
|
+
*
|
|
13
|
+
* Node-free, so `../browser.ts` can export it to a browser bundle (the VS
|
|
14
|
+
* Code webview, which is where the React render actually runs).
|
|
15
|
+
*/
|
|
16
|
+
import type { DiagnosticEvent, OnDiagnostic } from '@markii/stdlib';
|
|
17
|
+
/**
|
|
18
|
+
* One diagnostic event as a single line. The event's own `message` is the
|
|
19
|
+
* engine's failure-presentation wording, reused verbatim rather than
|
|
20
|
+
* reworded here; this only adds who it happened to.
|
|
21
|
+
*/
|
|
22
|
+
export declare function renderDiagnosticLine(event: DiagnosticEvent): string;
|
|
23
|
+
/**
|
|
24
|
+
* An `onDiagnostic` callback that writes each DISTINCT line once through
|
|
25
|
+
* `log`. A preview re-renders on every keystroke, and a note with one bad
|
|
26
|
+
* attribute value would otherwise write the same line hundreds of times
|
|
27
|
+
* into a log a reader is supposed to be able to scan. The dedupe is per
|
|
28
|
+
* collector, so a host creates one per note and drops it when the note
|
|
29
|
+
* closes.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createRenderDiagnosticReporter(log: (line: string) => void): OnDiagnostic;
|
|
32
|
+
/**
|
|
33
|
+
* A collector for a host that cannot log during the render itself, such as
|
|
34
|
+
* a webview that has to post its findings to an extension host afterwards.
|
|
35
|
+
* `onDiagnostic` goes to the render; `lines()` is read once the render has
|
|
36
|
+
* returned, already deduped and in the order the renderer found them.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createRenderDiagnosticCollector(): {
|
|
39
|
+
readonly onDiagnostic: OnDiagnostic;
|
|
40
|
+
readonly lines: () => string[];
|
|
41
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** The prefix every render-diagnostic line carries, so a reader can tell it from a pack or run line in the same log. */
|
|
2
|
+
const RENDER_DIAGNOSTIC_PREFIX = 'Render';
|
|
3
|
+
/**
|
|
4
|
+
* One diagnostic event as a single line. The event's own `message` is the
|
|
5
|
+
* engine's failure-presentation wording, reused verbatim rather than
|
|
6
|
+
* reworded here; this only adds who it happened to.
|
|
7
|
+
*/
|
|
8
|
+
export function renderDiagnosticLine(event) {
|
|
9
|
+
const where = event.directive === undefined
|
|
10
|
+
? ''
|
|
11
|
+
: event.attribute === undefined
|
|
12
|
+
? ` in ${event.directive}`
|
|
13
|
+
: ` in ${event.directive}'s ${event.attribute}`;
|
|
14
|
+
return `${RENDER_DIAGNOSTIC_PREFIX}${where}: ${event.message}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* An `onDiagnostic` callback that writes each DISTINCT line once through
|
|
18
|
+
* `log`. A preview re-renders on every keystroke, and a note with one bad
|
|
19
|
+
* attribute value would otherwise write the same line hundreds of times
|
|
20
|
+
* into a log a reader is supposed to be able to scan. The dedupe is per
|
|
21
|
+
* collector, so a host creates one per note and drops it when the note
|
|
22
|
+
* closes.
|
|
23
|
+
*/
|
|
24
|
+
export function createRenderDiagnosticReporter(log) {
|
|
25
|
+
const reported = new Set();
|
|
26
|
+
return (event) => {
|
|
27
|
+
const line = renderDiagnosticLine(event);
|
|
28
|
+
if (reported.has(line))
|
|
29
|
+
return;
|
|
30
|
+
reported.add(line);
|
|
31
|
+
log(line);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A collector for a host that cannot log during the render itself, such as
|
|
36
|
+
* a webview that has to post its findings to an extension host afterwards.
|
|
37
|
+
* `onDiagnostic` goes to the render; `lines()` is read once the render has
|
|
38
|
+
* returned, already deduped and in the order the renderer found them.
|
|
39
|
+
*/
|
|
40
|
+
export function createRenderDiagnosticCollector() {
|
|
41
|
+
const collected = [];
|
|
42
|
+
const onDiagnostic = createRenderDiagnosticReporter((line) => {
|
|
43
|
+
collected.push(line);
|
|
44
|
+
});
|
|
45
|
+
return { onDiagnostic, lines: () => [...collected] };
|
|
46
|
+
}
|