@sentropic/h2a 0.85.25 → 0.87.0
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/bin.js +51 -2
- package/dist/bin.js.map +1 -1
- package/dist/cli-command-map.d.ts +119 -0
- package/dist/cli-command-map.d.ts.map +1 -0
- package/dist/cli-command-map.js +396 -0
- package/dist/cli-command-map.js.map +1 -0
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli-contract.js +39 -1
- package/dist/cli-contract.js.map +1 -1
- package/dist/cli.d.ts +25 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +356 -7
- package/dist/cli.js.map +1 -1
- package/dist/identity.d.ts +37 -3
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -0
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime/enrollment/ceremony.d.ts +542 -0
- package/dist/runtime/enrollment/ceremony.d.ts.map +1 -0
- package/dist/runtime/enrollment/ceremony.js +777 -0
- package/dist/runtime/enrollment/ceremony.js.map +1 -0
- package/dist/runtime/enrollment/index.d.ts +16 -0
- package/dist/runtime/enrollment/index.d.ts.map +1 -0
- package/dist/runtime/enrollment/index.js +16 -0
- package/dist/runtime/enrollment/index.js.map +1 -0
- package/dist/runtime/feed/descriptors.d.ts +261 -0
- package/dist/runtime/feed/descriptors.d.ts.map +1 -0
- package/dist/runtime/feed/descriptors.js +425 -0
- package/dist/runtime/feed/descriptors.js.map +1 -0
- package/dist/runtime/feed/index.d.ts +12 -0
- package/dist/runtime/feed/index.d.ts.map +1 -0
- package/dist/runtime/feed/index.js +12 -0
- package/dist/runtime/feed/index.js.map +1 -0
- package/dist/runtime/identity/index.d.ts +3 -3
- package/dist/runtime/identity/index.d.ts.map +1 -1
- package/dist/runtime/identity/index.js +2 -2
- package/dist/runtime/identity/index.js.map +1 -1
- package/dist/runtime/identity/live.d.ts +68 -0
- package/dist/runtime/identity/live.d.ts.map +1 -1
- package/dist/runtime/identity/live.js +78 -2
- package/dist/runtime/identity/live.js.map +1 -1
- package/dist/runtime/identity/readers.d.ts +89 -5
- package/dist/runtime/identity/readers.d.ts.map +1 -1
- package/dist/runtime/identity/readers.js +242 -33
- package/dist/runtime/identity/readers.js.map +1 -1
- package/dist/runtime/local-files/presence.d.ts +16 -1
- package/dist/runtime/local-files/presence.d.ts.map +1 -1
- package/dist/runtime/local-files/presence.js +32 -20
- package/dist/runtime/local-files/presence.js.map +1 -1
- package/dist/runtime/loop/index.d.ts +5 -0
- package/dist/runtime/loop/index.d.ts.map +1 -1
- package/dist/runtime/loop/index.js +48 -5
- package/dist/runtime/loop/index.js.map +1 -1
- package/dist/runtime/mcp/agent-launch.d.ts +15 -1
- package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
- package/dist/runtime/mcp/agent-launch.js +45 -4
- package/dist/runtime/mcp/agent-launch.js.map +1 -1
- package/dist/runtime/mcp/index.d.ts +1 -1
- package/dist/runtime/mcp/index.d.ts.map +1 -1
- package/dist/runtime/mcp/index.js +1 -1
- package/dist/runtime/mcp/index.js.map +1 -1
- package/dist/runtime/mcp/server.d.ts +3 -1
- package/dist/runtime/mcp/server.d.ts.map +1 -1
- package/dist/runtime/mcp/server.js +7 -2
- package/dist/runtime/mcp/server.js.map +1 -1
- package/dist/runtime/mcp/sessions.d.ts +19 -0
- package/dist/runtime/mcp/sessions.d.ts.map +1 -1
- package/dist/runtime/mcp/sessions.js +44 -2
- package/dist/runtime/mcp/sessions.js.map +1 -1
- package/dist/runtime/mcp/stdio.d.ts +8 -0
- package/dist/runtime/mcp/stdio.d.ts.map +1 -1
- package/dist/runtime/mcp/stdio.js +42 -0
- package/dist/runtime/mcp/stdio.js.map +1 -1
- package/dist/runtime/mcp-registry/broker.d.ts +175 -0
- package/dist/runtime/mcp-registry/broker.d.ts.map +1 -0
- package/dist/runtime/mcp-registry/broker.js +203 -0
- package/dist/runtime/mcp-registry/broker.js.map +1 -0
- package/dist/runtime/mcp-registry/broker.typecheck.d.ts +2 -0
- package/dist/runtime/mcp-registry/broker.typecheck.d.ts.map +1 -0
- package/dist/runtime/mcp-registry/broker.typecheck.js +48 -0
- package/dist/runtime/mcp-registry/broker.typecheck.js.map +1 -0
- package/dist/runtime/mirror/accept.d.ts +43 -5
- package/dist/runtime/mirror/accept.d.ts.map +1 -1
- package/dist/runtime/mirror/accept.js +55 -7
- package/dist/runtime/mirror/accept.js.map +1 -1
- package/dist/runtime/mirror/build.d.ts +23 -4
- package/dist/runtime/mirror/build.d.ts.map +1 -1
- package/dist/runtime/mirror/build.js +34 -4
- package/dist/runtime/mirror/build.js.map +1 -1
- package/dist/runtime/mirror/index.d.ts +3 -0
- package/dist/runtime/mirror/index.d.ts.map +1 -1
- package/dist/runtime/mirror/index.js +3 -0
- package/dist/runtime/mirror/index.js.map +1 -1
- package/dist/runtime/mirror/ingest.d.ts +109 -0
- package/dist/runtime/mirror/ingest.d.ts.map +1 -0
- package/dist/runtime/mirror/ingest.js +117 -0
- package/dist/runtime/mirror/ingest.js.map +1 -0
- package/dist/runtime/mirror/push-daemon.d.ts +376 -0
- package/dist/runtime/mirror/push-daemon.d.ts.map +1 -0
- package/dist/runtime/mirror/push-daemon.js +644 -0
- package/dist/runtime/mirror/push-daemon.js.map +1 -0
- package/dist/runtime/mirror/sanitize.d.ts +477 -0
- package/dist/runtime/mirror/sanitize.d.ts.map +1 -0
- package/dist/runtime/mirror/sanitize.js +625 -0
- package/dist/runtime/mirror/sanitize.js.map +1 -0
- package/dist/runtime/mirror/serve.d.ts.map +1 -1
- package/dist/runtime/mirror/serve.js +104 -24
- package/dist/runtime/mirror/serve.js.map +1 -1
- package/dist/runtime/reporting/report-ai.d.ts.map +1 -1
- package/dist/runtime/reporting/report-ai.js +1 -0
- package/dist/runtime/reporting/report-ai.js.map +1 -1
- package/dist/runtime/reporting/stdin.d.ts +2 -0
- package/dist/runtime/reporting/stdin.d.ts.map +1 -0
- package/dist/runtime/reporting/stdin.js +8 -0
- package/dist/runtime/reporting/stdin.js.map +1 -0
- package/dist/status-surface.d.ts +167 -0
- package/dist/status-surface.d.ts.map +1 -0
- package/dist/status-surface.js +670 -0
- package/dist/status-surface.js.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/vendor/harness/skills/manifest.d.ts.map +1 -1
- package/dist/vendor/harness/skills/manifest.js +2 -0
- package/dist/vendor/harness/skills/manifest.js.map +1 -1
- package/focus-app/client/_app/immutable/assets/{0.BdzHFb9q.css → 0.CgEVz9YW.css} +1 -1
- package/focus-app/client/_app/immutable/assets/0.CgEVz9YW.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/0.CgEVz9YW.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css +1 -0
- package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css +1 -0
- package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css +1 -0
- package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{Cj6wo28J.js → 1NK_OeRJ.js} +1 -1
- package/focus-app/client/_app/immutable/chunks/1NK_OeRJ.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/1NK_OeRJ.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{Bs3f1UbD.js → B1veta3r.js} +2 -2
- package/focus-app/client/_app/immutable/chunks/B1veta3r.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/B1veta3r.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{DEmooz0s.js → BZ4lcC0v.js} +1 -1
- package/focus-app/client/_app/immutable/chunks/BZ4lcC0v.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/BZ4lcC0v.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js +2 -0
- package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js +1 -0
- package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DIljKPJN.js +1 -0
- package/focus-app/client/_app/immutable/chunks/DIljKPJN.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DIljKPJN.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/iXQate3J.js +2 -0
- package/focus-app/client/_app/immutable/chunks/iXQate3J.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/iXQate3J.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{ZxFklh9T.js → kCE9wz0g.js} +1 -1
- package/focus-app/client/_app/immutable/chunks/kCE9wz0g.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/kCE9wz0g.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js +1 -0
- package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js +2 -0
- package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js +1 -0
- package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js.br +2 -0
- package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js +5 -0
- package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js +1 -0
- package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js +1 -0
- package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js +12 -0
- package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js.gz +0 -0
- package/focus-app/client/_app/version.json +1 -1
- package/focus-app/client/_app/version.json.br +0 -0
- package/focus-app/client/_app/version.json.gz +0 -0
- package/focus-app/h2a-focus.json +108 -80
- package/focus-app/handler.js +7 -7
- package/focus-app/index.js +7 -7
- package/focus-app/server/chunks/chunks/AppShell.js-6Pi87dO0.js +1353 -0
- package/focus-app/server/chunks/chunks/AppShell.js-6Pi87dO0.js.map +1 -0
- package/focus-app/server/chunks/chunks/agent-memory-dossier.js-nmFG_rgx.js +1036 -0
- package/focus-app/server/chunks/chunks/agent-memory-dossier.js-nmFG_rgx.js.map +1 -0
- package/focus-app/server/chunks/chunks/{exports.js-DUTkELZq.js → exports.js-CdqPbjm1.js} +3 -3
- package/focus-app/server/chunks/chunks/{exports.js-DUTkELZq.js.map → exports.js-CdqPbjm1.js.map} +1 -1
- package/focus-app/server/chunks/chunks/h2a-bus.js-bLEJ_Adi.js +233 -0
- package/focus-app/server/chunks/chunks/h2a-bus.js-bLEJ_Adi.js.map +1 -0
- package/focus-app/server/chunks/chunks/{index.js-Di21TltP.js → index.js-laGHLarB.js} +5 -2
- package/focus-app/server/chunks/chunks/index.js-laGHLarB.js.map +1 -0
- package/focus-app/server/chunks/chunks/{internal.js-33vbd70h.js → internal.js-C6T8nHkl.js} +4 -4
- package/focus-app/server/chunks/chunks/{internal.js-33vbd70h.js.map → internal.js-C6T8nHkl.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{root.js-DO1m-gJA.js → root.js-CtVQOgDw.js} +2 -2
- package/focus-app/server/chunks/chunks/{root.js-DO1m-gJA.js.map → root.js-CtVQOgDw.js.map} +1 -1
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-j0NNcOSZ.js → _server.ts.js-hrbMnsV0.js} +13 -42
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-hrbMnsV0.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/_server.ts.js-Dw4odGdV.js +138 -0
- package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/_server.ts.js-Dw4odGdV.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/_server.ts.js-BLjYv7vg.js +41 -0
- package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/_server.ts.js-BLjYv7vg.js.map +1 -0
- package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-Dj3sETSX.js → error.svelte.js-RbeaNF5a.js} +4 -4
- package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-Dj3sETSX.js.map → error.svelte.js-RbeaNF5a.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-BoLsbuC2.js → _layout.svelte.js-e1E_I04z.js} +2 -2
- package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-BoLsbuC2.js.map → _layout.svelte.js-e1E_I04z.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/{_page.svelte.js-QDldMYhk.js → _page.svelte.js-DbaEG23x.js} +31 -1373
- package/focus-app/server/chunks/entries/pages/_page.svelte.js-DbaEG23x.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.server.ts.js-CFC-wn6U.js +88 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.server.ts.js-CFC-wn6U.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.svelte.js-BpR26NMa.js +1574 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.svelte.js-BpR26NMa.js.map +1 -0
- package/focus-app/server/chunks/{handler-Cp_5hLyY.js → handler-Be3dyNi0.js} +3 -3
- package/focus-app/server/chunks/{handler-Cp_5hLyY.js.map → handler-Be3dyNi0.js.map} +1 -1
- package/focus-app/server/chunks/{index.js-CBh7Wjqp.js → index.js-siUxMMnK.js} +3 -3
- package/focus-app/server/chunks/{index.js-CBh7Wjqp.js.map → index.js-siUxMMnK.js.map} +1 -1
- package/focus-app/server/chunks/manifest.js-CXJqSHHn.js +78 -0
- package/focus-app/server/chunks/manifest.js-CXJqSHHn.js.map +1 -0
- package/focus-app/server/chunks/nodes/0.js-leU6sfRR.js +9 -0
- package/focus-app/server/chunks/nodes/{0.js-4wlmdsk8.js.map → 0.js-leU6sfRR.js.map} +1 -1
- package/focus-app/server/chunks/nodes/1.js-os6QXm6B.js +9 -0
- package/focus-app/server/chunks/nodes/{1.js-B-LpY-lC.js.map → 1.js-os6QXm6B.js.map} +1 -1
- package/focus-app/server/chunks/nodes/2.js-DAaLjh93.js +19 -0
- package/focus-app/server/chunks/nodes/2.js-DAaLjh93.js.map +1 -0
- package/focus-app/server/chunks/nodes/3.js-Cmgi6Uy0.js +18 -0
- package/focus-app/server/chunks/nodes/3.js-Cmgi6Uy0.js.map +1 -0
- package/package.json +5 -5
- package/skills/h2a-run/SKILL.md +100 -0
- package/skills/harness/SKILL.md +3 -1
- package/skills/harness/review/SKILL.md +99 -8
- package/skills/harness/security/SKILL.md +55 -0
- package/skills/harness/track-report/SKILL.md +103 -0
- package/skills/harness/using-harness/SKILL.md +3 -1
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.br +0 -2
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css +0 -1
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js +0 -1
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js +0 -2
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js +0 -2
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js +0 -1
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js +0 -2
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js +0 -1
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.br +0 -2
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js +0 -5
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js +0 -1
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js +0 -1
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.gz +0 -0
- package/focus-app/server/chunks/chunks/index.js-Di21TltP.js.map +0 -1
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-j0NNcOSZ.js.map +0 -1
- package/focus-app/server/chunks/entries/pages/_page.svelte.js-QDldMYhk.js.map +0 -1
- package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js +0 -56
- package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js.map +0 -1
- package/focus-app/server/chunks/nodes/0.js-4wlmdsk8.js +0 -9
- package/focus-app/server/chunks/nodes/1.js-B-LpY-lC.js +0 -9
- package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js +0 -19
- package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js.map +0 -1
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* h2a → sentropic session-exposure feed — DESCRIPTOR BUILDERS (P1, step 1).
|
|
3
|
+
*
|
|
4
|
+
* Implements Part A of the ratified contract
|
|
5
|
+
* `docs/superpowers/specs/2026-07-24-h2a-feed-contract-for-sentropic.md`
|
|
6
|
+
* (RATIFIED by the sentropic architect, 2026-07-24, with three binding
|
|
7
|
+
* conditions accepted). Sentropic owns the multi-tenant gateway, the 39-auth
|
|
8
|
+
* broker and the UI panel; this module is h2a's own surface only.
|
|
9
|
+
*
|
|
10
|
+
* Everything here is PURE: presence records + registrations in, opaque
|
|
11
|
+
* descriptors out. No I/O, no network, no auth, no push, and never a clock —
|
|
12
|
+
* `asOf` is always injected by the caller, so every derivation is
|
|
13
|
+
* deterministic and unit-testable.
|
|
14
|
+
*
|
|
15
|
+
* Governing rule of the contract, enforced structurally in this module:
|
|
16
|
+
* *if a field can't be shown safely in a browser, it doesn't belong in the
|
|
17
|
+
* feed.* No message bodies, no negotiation content, no keys or tokens, and no
|
|
18
|
+
* filesystem path — `workspaceLabel` reads `H2AWorkspaceRef.label` and NEVER
|
|
19
|
+
* `.path` or `launchContext.cwd` (Part A, "Opacity boundary", non-negotiable).
|
|
20
|
+
*
|
|
21
|
+
* NOT wired into the hosted MCP handlers yet: that is step 5 of the P1 plan and
|
|
22
|
+
* is gated on the architecture lane's per-principal root partition (Part C).
|
|
23
|
+
*/
|
|
24
|
+
import { H2A_ROLES, H2A_SESSION_DEFAULT_EXPIRY_MS, deriveConnectionConfidence, isSessionExpired, sanitizeDeclaredCapabilities } from "@sentropic/h2a";
|
|
25
|
+
/**
|
|
26
|
+
* The single "not declared" sentinel for every string field whose source may be
|
|
27
|
+
* absent. Safe precisely because it can never collide with a real value: no
|
|
28
|
+
* workspace label, host hint or `H2A_ROLES` member is the literal `unknown`, so
|
|
29
|
+
* a consumer can always tell an undeclared field from an asserted one, and a
|
|
30
|
+
* row is NEVER dropped to hide one (a dropped row would be a false negative on
|
|
31
|
+
* presence, and would collide with the ratified "empty arrays = nothing
|
|
32
|
+
* enrolled" semantic). Architect ruling, 2026-07-25.
|
|
33
|
+
*/
|
|
34
|
+
const UNKNOWN = "unknown";
|
|
35
|
+
/**
|
|
36
|
+
* AN EMPTY COLLECTION ON THE WIRE IS A FACTUAL CLAIM — "there is nothing" — so
|
|
37
|
+
* it must be produced by code that actually ESTABLISHED that fact. A default
|
|
38
|
+
* cannot establish a fact.
|
|
39
|
+
*
|
|
40
|
+
* That is why nothing in this module reaches the wire through `?? []`, `|| []`
|
|
41
|
+
* or an equivalent tail: a DEFAULTED empty array is indistinguishable from an
|
|
42
|
+
* errored read, a silently-empty query, and a lookup that was never performed.
|
|
43
|
+
* Every empty value below is a named constant returned from an explicit branch,
|
|
44
|
+
* and an *unread* source is a THROWN ERROR rather than an empty feed. (Amendment
|
|
45
|
+
* accepted by the architect, 2026-07-25, raised by the sentropic auth lane; it
|
|
46
|
+
* governs this feed as well as the binding resolver. Same discipline as
|
|
47
|
+
* `isoOrUnknown`/`nonEmpty` for scalars, extended to collections.)
|
|
48
|
+
*/
|
|
49
|
+
const NO_COUNTERPART_SOURCE_IN_P1 = Object.freeze([]);
|
|
50
|
+
/** Nothing was declared: absent registration, or the field is absent/empty. */
|
|
51
|
+
const NOTHING_DECLARED = Object.freeze([]);
|
|
52
|
+
/**
|
|
53
|
+
* Whether ANY counterpart source is wired into this build.
|
|
54
|
+
*
|
|
55
|
+
* P1: none exists — no h2a structure records "who is this session is in contact
|
|
56
|
+
* with", and negotiations are not mirrored (contract Gaps §2; EVO-13 scopes
|
|
57
|
+
* `h2a_conflict_posture` out until they are). Typed `boolean` deliberately so
|
|
58
|
+
* both branches of {@link counterpartsOpaqueRefsFor} stay reachable to the type
|
|
59
|
+
* checker.
|
|
60
|
+
*/
|
|
61
|
+
const COUNTERPART_SOURCE_WIRED = false;
|
|
62
|
+
/**
|
|
63
|
+
* `counterpartsOpaqueRefs` for one session, from an EXPLICIT branch.
|
|
64
|
+
*
|
|
65
|
+
* The empty list is P1's answer to a question we can actually answer: there is
|
|
66
|
+
* no source at all, so "no counterparts" is established rather than assumed.
|
|
67
|
+
* When a source IS wired, its derivation must be added ABOVE the throw — the
|
|
68
|
+
* empty case must never become reachable by falling through, because from that
|
|
69
|
+
* point on an empty list would mean "we did not look" while claiming "there are
|
|
70
|
+
* none".
|
|
71
|
+
*/
|
|
72
|
+
function counterpartsOpaqueRefsFor() {
|
|
73
|
+
if (!COUNTERPART_SOURCE_WIRED)
|
|
74
|
+
return NO_COUNTERPART_SOURCE_IN_P1;
|
|
75
|
+
throw new Error("h2a feed: a counterpart source is wired but no derivation is implemented — " +
|
|
76
|
+
"refusing to emit an empty counterpart list that would read as 'no counterparts'");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Guard a collection the caller was supposed to have READ.
|
|
80
|
+
*
|
|
81
|
+
* A missing array is not an empty one: it means the read never happened or it
|
|
82
|
+
* failed. Rendering that as an empty feed would tell the owner "you have no
|
|
83
|
+
* agents" on the strength of a broken read, so fail loudly instead. This is the
|
|
84
|
+
* one place the pure builders can enforce the distinction, since the read itself
|
|
85
|
+
* happens in the caller.
|
|
86
|
+
*/
|
|
87
|
+
function requireRead(value, source) {
|
|
88
|
+
if (!Array.isArray(value)) {
|
|
89
|
+
throw new Error(`h2a feed: ${source} was not read (got ${value === undefined ? "undefined" : typeof value}) — ` +
|
|
90
|
+
"an unread source must never render as an empty feed");
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The instance's declared display list, from an explicit branch on whether a
|
|
96
|
+
* declaration exists at all — never a `?? []` tail.
|
|
97
|
+
*/
|
|
98
|
+
function declaredCapabilitiesOf(registration) {
|
|
99
|
+
if (registration === undefined)
|
|
100
|
+
return NOTHING_DECLARED;
|
|
101
|
+
if (registration.declaredCapabilities === undefined)
|
|
102
|
+
return NOTHING_DECLARED;
|
|
103
|
+
// Present: ALLOWLIST it (intersection with the closed vocabulary). An empty
|
|
104
|
+
// result here is also a fact — every value offered was outside the vocabulary.
|
|
105
|
+
return sanitizeDeclaredCapabilities(registration.declaredCapabilities);
|
|
106
|
+
}
|
|
107
|
+
function parseIso(value) {
|
|
108
|
+
if (typeof value !== "string")
|
|
109
|
+
return undefined;
|
|
110
|
+
const at = Date.parse(value);
|
|
111
|
+
return Number.isNaN(at) ? undefined : at;
|
|
112
|
+
}
|
|
113
|
+
function heartbeatMs(session) {
|
|
114
|
+
return parseIso(session.heartbeatAt) ?? 0;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A present, non-empty string, or `undefined`.
|
|
118
|
+
*
|
|
119
|
+
* Used by every fallback chain in this module so `""` behaves like absence
|
|
120
|
+
* everywhere. Without it the `'unknown'` sentinel is defeated by an empty
|
|
121
|
+
* string: `h2a connect --name ""` writes `registration.name === ""`, and a `??`
|
|
122
|
+
* chain would happily emit that as the displayName.
|
|
123
|
+
*/
|
|
124
|
+
function nonEmpty(value) {
|
|
125
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The ONLY reader of a workspace reference in this module — the whole ref
|
|
129
|
+
* reaches exactly this function, which returns `label` and nothing else.
|
|
130
|
+
* `H2AWorkspaceRef.path` and `H2ALaunchContext.cwd` are filesystem paths,
|
|
131
|
+
* excluded from the feed by design, and this single choke point is what makes
|
|
132
|
+
* that exclusion structural rather than a review-time hope.
|
|
133
|
+
*
|
|
134
|
+
* The claim is only true while it is literally the only reader: an earlier
|
|
135
|
+
* revision of this file also read `workspace?.host` directly at the instance
|
|
136
|
+
* builder, which made the comment overstate the guarantee. Do not add a second
|
|
137
|
+
* reader; extend this one.
|
|
138
|
+
*/
|
|
139
|
+
function labelOf(workspace) {
|
|
140
|
+
return nonEmpty(workspace?.label);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Validate a declared role against `H2A_ROLES` at the READ boundary.
|
|
144
|
+
*
|
|
145
|
+
* Anything unrecognized — `'SUPERADMIN'`, `''`, a non-string — becomes
|
|
146
|
+
* `'unknown'`. This is the Q1 ruling applied to the read path: never emit a
|
|
147
|
+
* value outside the declared union, no matter which writer produced the
|
|
148
|
+
* registry row.
|
|
149
|
+
*/
|
|
150
|
+
function sanitizeRole(role) {
|
|
151
|
+
if (typeof role !== "string")
|
|
152
|
+
return UNKNOWN;
|
|
153
|
+
return H2A_ROLES.includes(role) ? role : UNKNOWN;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Emit a timestamp only if it actually parses as one; otherwise the sentinel.
|
|
157
|
+
* The contract types these fields as ISO 8601, so arbitrary text must not pass
|
|
158
|
+
* through into them.
|
|
159
|
+
*/
|
|
160
|
+
function isoOrUnknown(value) {
|
|
161
|
+
return parseIso(value) === undefined ? UNKNOWN : value;
|
|
162
|
+
}
|
|
163
|
+
/** Sessions of one instance, most recent heartbeat first. */
|
|
164
|
+
function sessionsOfInstance(sessions, instanceId) {
|
|
165
|
+
return sessions
|
|
166
|
+
.filter((session) => session.instance === instanceId)
|
|
167
|
+
.sort((a, b) => heartbeatMs(b) - heartbeatMs(a));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Session state per the contract's code block. Reuses h2a's existing
|
|
171
|
+
* primitives — the 90s keepalive window that already gates
|
|
172
|
+
* `h2a_discover_sessions`, and WP-F connection confidence. Nothing about
|
|
173
|
+
* freshness is reimplemented here.
|
|
174
|
+
*/
|
|
175
|
+
export function deriveSessionState(session, asOf) {
|
|
176
|
+
if (session.state === "closed" || session.state === "expired")
|
|
177
|
+
return "closed";
|
|
178
|
+
if (isSessionExpired(session, { now: asOf, expiryMs: H2A_SESSION_DEFAULT_EXPIRY_MS })) {
|
|
179
|
+
return "closed";
|
|
180
|
+
}
|
|
181
|
+
const confidence = deriveConnectionConfidence(session, { now: asOf });
|
|
182
|
+
// "idle-uncertain" and "unknown" both read as idle: the process lives but the
|
|
183
|
+
// MCP channel has carried no proven traffic.
|
|
184
|
+
return confidence === "active" ? "open" : "idle";
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Liveness per the contract's code block. Same two primitives as
|
|
188
|
+
* {@link deriveSessionState}, plus the one distinction `state` does not need:
|
|
189
|
+
* `stale`.
|
|
190
|
+
*
|
|
191
|
+
* `stale` is the FEED PIPELINE's own freshness bleeding into a row, not an
|
|
192
|
+
* agent state. A directly-observed local session (no `mirroredAt`) is NEVER
|
|
193
|
+
* `stale` — the same-machine clock is trustworthy, so it goes straight to
|
|
194
|
+
* live/idle/closed. A replicated row is `stale` when the daemon that should
|
|
195
|
+
* keep refreshing it has gone quiet for more than 2x its push interval: at
|
|
196
|
+
* that point the numerically "fresh" `heartbeatAt`/`lastMcpActivityAt` carried
|
|
197
|
+
* in the record can no longer be trusted the way a live local read can, so the
|
|
198
|
+
* honest label is "we don't know", not "live".
|
|
199
|
+
*/
|
|
200
|
+
export function deriveLiveness(session, asOf, pushIntervalMs) {
|
|
201
|
+
if (session.state === "closed" || session.state === "expired")
|
|
202
|
+
return "closed";
|
|
203
|
+
if (isSessionExpired(session, { now: asOf, expiryMs: H2A_SESSION_DEFAULT_EXPIRY_MS })) {
|
|
204
|
+
return "closed";
|
|
205
|
+
}
|
|
206
|
+
// ORDERING IS LOAD-BEARING — do not move this gate below the confidence
|
|
207
|
+
// check. Because staleness is decided FIRST, any row that later returns
|
|
208
|
+
// 'idle' has already passed pipeline-freshness: an 'idle' is therefore
|
|
209
|
+
// genuine, fresh knowledge ("we looked, and it is quiet"), never absence of
|
|
210
|
+
// knowledge. That is the whole justification for ranking idle ABOVE stale in
|
|
211
|
+
// the instance roll-up (see LIVENESS_RANK). Reorder these two checks and a
|
|
212
|
+
// stale-pipeline row would surface as 'idle' — a fresh-looking claim built on
|
|
213
|
+
// timestamps nobody has refreshed — and the roll-up ordering would become
|
|
214
|
+
// wrong (stale would have to dominate instead). Pinned by the test named
|
|
215
|
+
// "the mirroredAt staleness gate strictly precedes the confidence check".
|
|
216
|
+
//
|
|
217
|
+
// Replicated/mirrored record (Part C's push-to-root path): `heartbeatAt` is
|
|
218
|
+
// re-stamped with the receiving clock on ingest, but the payload's own
|
|
219
|
+
// `lastMcpActivityAt` is a LOCAL clock value copied through verbatim — it is
|
|
220
|
+
// NOT proof of current liveness once the pipeline itself may have gone quiet.
|
|
221
|
+
if (session.mirroredAt && pushIntervalMs) {
|
|
222
|
+
const mirroredAt = parseIso(session.mirroredAt);
|
|
223
|
+
if (mirroredAt !== undefined && asOf - mirroredAt > 2 * pushIntervalMs) {
|
|
224
|
+
return "stale"; // pipeline lag, not agent state
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const confidence = deriveConnectionConfidence(session, { now: asOf });
|
|
228
|
+
return confidence === "active" ? "live" : "idle";
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Best-of ranking for the instance-level roll-up: live > idle > stale > closed.
|
|
232
|
+
*
|
|
233
|
+
* `idle` outranks `stale` ONLY because {@link deriveLiveness} decides staleness
|
|
234
|
+
* before it consults connection confidence, so an `idle` here is always fresh
|
|
235
|
+
* knowledge rather than absence of it. If that ordering is ever inverted, this
|
|
236
|
+
* ranking must be inverted with it — `stale` would then have to dominate.
|
|
237
|
+
*/
|
|
238
|
+
const LIVENESS_RANK = {
|
|
239
|
+
live: 3,
|
|
240
|
+
idle: 2,
|
|
241
|
+
// "we don't know" ranks below a KNOWN idle, and above a known-closed row.
|
|
242
|
+
stale: 1,
|
|
243
|
+
closed: 0
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Roll several sessions' liveness up to their instance: best-of, per Part A
|
|
247
|
+
* ("Best-of across the instance's sessions"). An instance with no session at
|
|
248
|
+
* all reads `closed` — absence is not liveness.
|
|
249
|
+
*/
|
|
250
|
+
export function rollUpLiveness(states) {
|
|
251
|
+
let best = "closed";
|
|
252
|
+
for (const state of states) {
|
|
253
|
+
if (LIVENESS_RANK[state] > LIVENESS_RANK[best])
|
|
254
|
+
best = state;
|
|
255
|
+
}
|
|
256
|
+
return best;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* One presence record → one `SessionDescriptor`.
|
|
260
|
+
*
|
|
261
|
+
* `lastActivityAt` prefers `lastMcpActivityAt` (WP-F: proof the MCP channel
|
|
262
|
+
* carried real traffic) and falls back to `heartbeatAt`. The fallback is
|
|
263
|
+
* advisory-only — a live process, not proven channel activity — which is why
|
|
264
|
+
* `activitySource` is baked into the descriptor rather than left to the
|
|
265
|
+
* consumer's inference (ratification condition #2).
|
|
266
|
+
*/
|
|
267
|
+
export function buildSessionDescriptor(session, options) {
|
|
268
|
+
const registration = options.registration;
|
|
269
|
+
const workspaceLabel = labelOf(session.workspace) ?? labelOf(registration?.workspace) ?? UNKNOWN;
|
|
270
|
+
// DEC-114 per-session mutable display name (host-native customTitle /
|
|
271
|
+
// thread_name, or `/rename`). May legitimately diverge from the owning
|
|
272
|
+
// instance's displayName — a session can be renamed independently. `nonEmpty`
|
|
273
|
+
// keeps `""` behaving as absence, so the chain cannot emit a blank title.
|
|
274
|
+
const topicOrTitle = nonEmpty(session.name) ?? nonEmpty(registration?.name) ?? workspaceLabel;
|
|
275
|
+
const mcpActivityAt = parseIso(session.lastMcpActivityAt);
|
|
276
|
+
const provenMcp = mcpActivityAt !== undefined;
|
|
277
|
+
return {
|
|
278
|
+
sessionId: session.sessionId,
|
|
279
|
+
instanceId: session.instance,
|
|
280
|
+
topicOrTitle,
|
|
281
|
+
state: deriveSessionState(session, options.asOf),
|
|
282
|
+
openedAt: isoOrUnknown(session.startedAt),
|
|
283
|
+
// When the MCP stamp is absent/unparseable we fall back to the heartbeat,
|
|
284
|
+
// which is itself validated: an unparseable heartbeat yields the sentinel
|
|
285
|
+
// rather than leaking arbitrary text into an ISO-typed field. The source is
|
|
286
|
+
// still reported as 'heartbeat' — that IS the source we consulted, and a
|
|
287
|
+
// consumer must keep treating it as advisory.
|
|
288
|
+
lastActivityAt: provenMcp
|
|
289
|
+
? session.lastMcpActivityAt
|
|
290
|
+
: isoOrUnknown(session.heartbeatAt),
|
|
291
|
+
activitySource: provenMcp ? "mcp" : "heartbeat",
|
|
292
|
+
// From an explicit branch, never a literal default: an empty list here is
|
|
293
|
+
// the CLAIM "there are no counterparts", so it must be established.
|
|
294
|
+
counterpartsOpaqueRefs: counterpartsOpaqueRefsFor()
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* One instance (+ its sessions) → one `InstanceDescriptor`.
|
|
299
|
+
*
|
|
300
|
+
* `displayName` order per Part A: the registration's DEC-114 mutable name,
|
|
301
|
+
* then the most recent LIVE session's host-native name (WP-6), then the
|
|
302
|
+
* workspace label. `lastSeen` is the max heartbeat across the instance's
|
|
303
|
+
* sessions. `host` comes from the most recent session's host hint.
|
|
304
|
+
*
|
|
305
|
+
* Every chain below matches the contract's declared mapping exactly and adds no
|
|
306
|
+
* undeclared step: earlier revisions scanned ALL sessions for a label/host and
|
|
307
|
+
* fell back to `workspace.host` and to `registration.createdAt`, none of which
|
|
308
|
+
* the spec declares. Code and contract must not disagree, so those were removed
|
|
309
|
+
* rather than quietly kept.
|
|
310
|
+
*/
|
|
311
|
+
export function buildInstanceDescriptor(instanceId, options) {
|
|
312
|
+
const registration = options.registration;
|
|
313
|
+
const ordered = [...options.sessions].sort((a, b) => heartbeatMs(b) - heartbeatMs(a));
|
|
314
|
+
const mostRecent = ordered[0];
|
|
315
|
+
// Declared mapping: the session's workspace label (per-session authoritative,
|
|
316
|
+
// taken from the most recent session), else the registration's, else nothing.
|
|
317
|
+
const workspaceLabel = labelOf(mostRecent?.workspace) ?? labelOf(registration?.workspace) ?? UNKNOWN;
|
|
318
|
+
const liveSessionName = ordered
|
|
319
|
+
.filter((session) => deriveSessionState(session, options.asOf) !== "closed")
|
|
320
|
+
.map((session) => nonEmpty(session.name))
|
|
321
|
+
.find((name) => name !== undefined);
|
|
322
|
+
const displayName = nonEmpty(registration?.name) ?? liveSessionName ?? workspaceLabel;
|
|
323
|
+
// Declared mapping: the most recent session's host hint, else nothing. A
|
|
324
|
+
// workspace ref is NOT consulted here — that would be a second reader of the
|
|
325
|
+
// ref and would break `labelOf`'s choke-point guarantee.
|
|
326
|
+
const host = nonEmpty(mostRecent?.host) ?? UNKNOWN;
|
|
327
|
+
// Strictly max(heartbeatAt). No mint-time fallback: `createdAt` is not a
|
|
328
|
+
// sighting, and presenting it as "last seen" would be an unearned freshness
|
|
329
|
+
// claim.
|
|
330
|
+
const lastSeenMs = ordered.reduce((max, session) => Math.max(max, heartbeatMs(session)), 0);
|
|
331
|
+
const lastSeen = lastSeenMs > 0 ? new Date(lastSeenMs).toISOString() : UNKNOWN;
|
|
332
|
+
const liveness = rollUpLiveness(ordered.map((session) => deriveLiveness(session, options.asOf, options.pushIntervalMs)));
|
|
333
|
+
return {
|
|
334
|
+
instanceId,
|
|
335
|
+
displayName,
|
|
336
|
+
host,
|
|
337
|
+
// Validated against H2A_ROLES on read, and never synthesized for a missing
|
|
338
|
+
// one (see the field's doc). Whoever wrote the registry, the wire union holds.
|
|
339
|
+
role: sanitizeRole(registration?.roles?.[0]),
|
|
340
|
+
workspaceLabel,
|
|
341
|
+
// Declared DISPLAY list, read from `declaredCapabilities` and ALLOWLISTED
|
|
342
|
+
// against the closed vocabulary — an intersection, never a denylist. The
|
|
343
|
+
// authority-bearing `capabilities` is deliberately NOT read here: it is the
|
|
344
|
+
// subagent ceiling and the attestation right, and it must never surface in a
|
|
345
|
+
// browser panel nor be conflated with a declaration.
|
|
346
|
+
declaredCapabilities: declaredCapabilitiesOf(registration),
|
|
347
|
+
lastSeen,
|
|
348
|
+
liveness
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/** Every instance id mentioned by a presence record or a registration. */
|
|
352
|
+
function instanceIds(input) {
|
|
353
|
+
const ids = [];
|
|
354
|
+
const seen = new Set();
|
|
355
|
+
const push = (id) => {
|
|
356
|
+
if (typeof id !== "string" || id.length === 0 || seen.has(id))
|
|
357
|
+
return;
|
|
358
|
+
seen.add(id);
|
|
359
|
+
ids.push(id);
|
|
360
|
+
};
|
|
361
|
+
for (const registration of requireRead(input.registrations, "registrations")) {
|
|
362
|
+
push(registration.instance);
|
|
363
|
+
}
|
|
364
|
+
for (const session of input.sessions)
|
|
365
|
+
push(session.instance);
|
|
366
|
+
return ids;
|
|
367
|
+
}
|
|
368
|
+
function registrationIndex(registrations) {
|
|
369
|
+
const index = new Map();
|
|
370
|
+
for (const registration of registrations) {
|
|
371
|
+
if (!index.has(registration.instance))
|
|
372
|
+
index.set(registration.instance, registration);
|
|
373
|
+
}
|
|
374
|
+
return index;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Presence + registry → `InstanceDescriptor[]`, **ordered by `lastSeen`
|
|
378
|
+
* descending** (most recently seen agent first). The order is part of the
|
|
379
|
+
* behaviour, not an accident of input order, and is pinned by a test — a
|
|
380
|
+
* documented behaviour that can be deleted with the suite still green is not a
|
|
381
|
+
* behaviour. Rows whose `lastSeen` is the sentinel sort last.
|
|
382
|
+
*/
|
|
383
|
+
export function buildInstanceDescriptors(input) {
|
|
384
|
+
// Both sources must have been READ. An empty result below is then a fact.
|
|
385
|
+
requireRead(input.sessions, "sessions");
|
|
386
|
+
const index = registrationIndex(requireRead(input.registrations, "registrations"));
|
|
387
|
+
return instanceIds(input)
|
|
388
|
+
.map((instanceId) => buildInstanceDescriptor(instanceId, {
|
|
389
|
+
asOf: input.asOf,
|
|
390
|
+
sessions: sessionsOfInstance(input.sessions, instanceId),
|
|
391
|
+
registration: index.get(instanceId),
|
|
392
|
+
pushIntervalMs: input.pushIntervalMs
|
|
393
|
+
}))
|
|
394
|
+
.sort((a, b) => (parseIso(b.lastSeen) ?? 0) - (parseIso(a.lastSeen) ?? 0));
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Presence + registry → `SessionDescriptor[]`, **ordered by `lastActivityAt`
|
|
398
|
+
* descending** (most recently active session first). Pinned by a test, for the
|
|
399
|
+
* same reason as {@link buildInstanceDescriptors}.
|
|
400
|
+
*/
|
|
401
|
+
export function buildSessionDescriptors(input) {
|
|
402
|
+
const sessions = requireRead(input.sessions, "sessions");
|
|
403
|
+
const index = registrationIndex(requireRead(input.registrations, "registrations"));
|
|
404
|
+
return sessions
|
|
405
|
+
.map((session) => buildSessionDescriptor(session, {
|
|
406
|
+
asOf: input.asOf,
|
|
407
|
+
registration: index.get(session.instance)
|
|
408
|
+
}))
|
|
409
|
+
.sort((a, b) => (parseIso(b.lastActivityAt) ?? 0) - (parseIso(a.lastActivityAt) ?? 0));
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Presence + registry → the whole `H2AFeedResponse`.
|
|
413
|
+
*
|
|
414
|
+
* The caller decides WHICH sessions and registrations to hand in — this
|
|
415
|
+
* function never widens that set, and (per P1) principal scoping happens
|
|
416
|
+
* server-side before the call, never here.
|
|
417
|
+
*/
|
|
418
|
+
export function buildFeedResponse(input) {
|
|
419
|
+
return {
|
|
420
|
+
asOf: new Date(input.asOf).toISOString(),
|
|
421
|
+
instances: buildInstanceDescriptors(input),
|
|
422
|
+
sessions: buildSessionDescriptors(input)
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
//# sourceMappingURL=descriptors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptors.js","sourceRoot":"","sources":["../../../src/runtime/feed/descriptors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* h2a → sentropic session-exposure feed (P1). Read-only, principal-scoped
|
|
3
|
+
* presence/session descriptors. Contract:
|
|
4
|
+
* `docs/superpowers/specs/2026-07-24-h2a-feed-contract-for-sentropic.md`
|
|
5
|
+
* (ratified 2026-07-24).
|
|
6
|
+
*
|
|
7
|
+
* Step 1 = these pure builders only. No HTTP route, no auth, no binding store,
|
|
8
|
+
* no push daemon, no gateway, no UI — each of those is a separate, separately
|
|
9
|
+
* gated step of the plan.
|
|
10
|
+
*/
|
|
11
|
+
export { buildFeedResponse, buildInstanceDescriptor, buildInstanceDescriptors, buildSessionDescriptor, buildSessionDescriptors, deriveLiveness, deriveSessionState, rollUpLiveness, type BuildFeedInput, type BuildInstanceDescriptorOptions, type BuildSessionDescriptorOptions, type H2AFeedResponse, type H2ALivenessState, type InstanceDescriptor, type SessionDescriptor } from "./descriptors.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/feed/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,8BAA8B,EACnC,KAAK,6BAA6B,EAClC,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* h2a → sentropic session-exposure feed (P1). Read-only, principal-scoped
|
|
3
|
+
* presence/session descriptors. Contract:
|
|
4
|
+
* `docs/superpowers/specs/2026-07-24-h2a-feed-contract-for-sentropic.md`
|
|
5
|
+
* (ratified 2026-07-24).
|
|
6
|
+
*
|
|
7
|
+
* Step 1 = these pure builders only. No HTTP route, no auth, no binding store,
|
|
8
|
+
* no push daemon, no gateway, no UI — each of those is a separate, separately
|
|
9
|
+
* gated step of the plan.
|
|
10
|
+
*/
|
|
11
|
+
export { buildFeedResponse, buildInstanceDescriptor, buildInstanceDescriptors, buildSessionDescriptor, buildSessionDescriptors, deriveLiveness, deriveSessionState, rollUpLiveness } from "./descriptors.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/feed/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAClB,cAAc,EAQf,MAAM,kBAAkB,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { resolveProviderSession } from "./resolver.js";
|
|
2
2
|
export type { ProviderSession, ProviderSessionReaders, ProviderSessionSource, ResolveProviderSessionInput } from "./resolver.js";
|
|
3
|
-
export { defaultProviderSessionReaders, readHostSessionName } from "./readers.js";
|
|
3
|
+
export { CLAUDE_TITLE_TAIL_BYTES, CODEX_INDEX_TAIL_BYTES, MAX_DISPLAY_NAME_CHARS, createHostSessionNameRefresher, defaultProviderSessionReaders, readHostSessionName } from "./readers.js";
|
|
4
4
|
export type { HostNameReaders } from "./readers.js";
|
|
5
5
|
export { listBindings, findBinding, verifyReclaimProof, reclaimOrMint } from "./bindings.js";
|
|
6
6
|
export type { H2AIdentityBinding, IdentityBindingKey, ReclaimOrMintDeps, ReclaimOrMintResult } from "./bindings.js";
|
|
7
7
|
export { mergeInboxDedup, decideLegacyAdoption, listIdentityAliases, legacyAliasAlreadyAdopted, recordIdentityAlias } from "./migration.js";
|
|
8
8
|
export type { H2AIdentityAlias, LegacyAdoptionInput, LegacyAdoptionDecision } from "./migration.js";
|
|
9
|
-
export { resolveLiveIdentity } from "./live.js";
|
|
10
|
-
export type { ResolveLiveIdentityInput, ResolvedLiveIdentity } from "./live.js";
|
|
9
|
+
export { resolveLiveIdentity, sanitizeDeclaredCapabilities, H2A_CLI_DECLARED_CAPABILITIES, H2A_DECLARED_CAPABILITIES } from "./live.js";
|
|
10
|
+
export type { H2ADeclaredCapability, ResolveLiveIdentityInput, ResolvedLiveIdentity } from "./live.js";
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,8BAA8B,EAC9B,6BAA6B,EAC7B,mBAAmB,EACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,6BAA6B,EAC7B,yBAAyB,EAC1B,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,WAAW,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { resolveProviderSession } from "./resolver.js";
|
|
2
|
-
export { defaultProviderSessionReaders, readHostSessionName } from "./readers.js";
|
|
2
|
+
export { CLAUDE_TITLE_TAIL_BYTES, CODEX_INDEX_TAIL_BYTES, MAX_DISPLAY_NAME_CHARS, createHostSessionNameRefresher, defaultProviderSessionReaders, readHostSessionName } from "./readers.js";
|
|
3
3
|
export { listBindings, findBinding, verifyReclaimProof, reclaimOrMint } from "./bindings.js";
|
|
4
4
|
export { mergeInboxDedup, decideLegacyAdoption, listIdentityAliases, legacyAliasAlreadyAdopted, recordIdentityAlias } from "./migration.js";
|
|
5
|
-
export { resolveLiveIdentity } from "./live.js";
|
|
5
|
+
export { resolveLiveIdentity, sanitizeDeclaredCapabilities, H2A_CLI_DECLARED_CAPABILITIES, H2A_DECLARED_CAPABILITIES } from "./live.js";
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/identity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAOvD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/identity/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAOvD,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,8BAA8B,EAC9B,6BAA6B,EAC7B,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AAOvB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,6BAA6B,EAC7B,yBAAyB,EAC1B,MAAM,WAAW,CAAC"}
|
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
import { type H2AWorkspaceRef } from "@sentropic/h2a";
|
|
2
2
|
import { type ProviderSessionReaders } from "./resolver.js";
|
|
3
|
+
/**
|
|
4
|
+
* The CLOSED vocabulary an agent may DECLARE at registration.
|
|
5
|
+
*
|
|
6
|
+
* DISPLAY ONLY, and NON-AUTHORITATIVE. Self-reported by the agent, and it MUST
|
|
7
|
+
* NEVER be an input to any authorization decision, anywhere — not in h2a, not in
|
|
8
|
+
* a gateway, not in a UI. Authorization is the principal binding plus
|
|
9
|
+
* server-side scoping; a capability string proves nothing. (Binding condition #3
|
|
10
|
+
* of the session-exposure feed contract ratified 2026-07-24,
|
|
11
|
+
* docs/superpowers/specs/2026-07-24-h2a-feed-contract-for-sentropic.md.)
|
|
12
|
+
*
|
|
13
|
+
* These values are written to `H2AActorRegistration.declaredCapabilities` and
|
|
14
|
+
* NEVER to `capabilities` — the latter is the authority-bearing rights list read
|
|
15
|
+
* by the subagent ceiling (`subagents.ts` `capabilities-exceed-parent`) and by
|
|
16
|
+
* `canAttestComprehension`. Writing display vocabulary there would widen a
|
|
17
|
+
* privilege ceiling as a side effect of a display feature, which is exactly the
|
|
18
|
+
* defect the architect's 2026-07-25 split ruling removes. The two fields must
|
|
19
|
+
* never be merged.
|
|
20
|
+
*
|
|
21
|
+
* Note why "no vocabulary member may ever equal a right string" is NOT a
|
|
22
|
+
* sufficient guard, and is not relied upon here: the subagent ceiling is a
|
|
23
|
+
* SUBSET check over the whole field, not a lookup of specific right strings — so
|
|
24
|
+
* that invariant holds for these three values and the ceiling still widens.
|
|
25
|
+
* Separation of fields is the mitigation; string choice is not.
|
|
26
|
+
*
|
|
27
|
+
* Closed on purpose: an unknown string is DROPPED rather than stored, so the
|
|
28
|
+
* set a consumer can ever render stays enumerable and reviewable.
|
|
29
|
+
*/
|
|
30
|
+
export declare const H2A_DECLARED_CAPABILITIES: readonly ["h2a.session", "h2a.mcp", "h2a.subagents"];
|
|
31
|
+
export type H2ADeclaredCapability = (typeof H2A_DECLARED_CAPABILITIES)[number];
|
|
32
|
+
/**
|
|
33
|
+
* What the CLI's own registration path declares. Narrower than the vocabulary
|
|
34
|
+
* on purpose: these two are true of every h2a CLI agent by construction, while
|
|
35
|
+
* `h2a.subagents` is host-specific and not knowable at this call site — an
|
|
36
|
+
* over-claim would be a lie in a browser panel, so it is left to a host plugin
|
|
37
|
+
* that actually knows.
|
|
38
|
+
*/
|
|
39
|
+
export declare const H2A_CLI_DECLARED_CAPABILITIES: readonly H2ADeclaredCapability[];
|
|
40
|
+
/**
|
|
41
|
+
* Keep only members of the closed vocabulary, de-duplicated and in vocabulary
|
|
42
|
+
* order, so what lands in the registry is never caller-shaped free text.
|
|
43
|
+
*/
|
|
44
|
+
export declare function sanitizeDeclaredCapabilities(capabilities: readonly string[] | undefined): H2ADeclaredCapability[];
|
|
3
45
|
export interface ResolveLiveIdentityInput {
|
|
4
46
|
readonly root: string;
|
|
5
47
|
readonly host: string;
|
|
@@ -7,6 +49,14 @@ export interface ResolveLiveIdentityInput {
|
|
|
7
49
|
readonly explicitInstance?: string;
|
|
8
50
|
readonly name?: string;
|
|
9
51
|
readonly scopes?: readonly string[];
|
|
52
|
+
/**
|
|
53
|
+
* Capabilities the agent DECLARES at mint (display-only, non-authoritative —
|
|
54
|
+
* see {@link H2A_DECLARED_CAPABILITIES}). Filtered against the closed
|
|
55
|
+
* vocabulary; anything else is dropped. Written to the registration's
|
|
56
|
+
* `declaredCapabilities`, never to the authority-bearing `capabilities`.
|
|
57
|
+
* Absent → the field is omitted.
|
|
58
|
+
*/
|
|
59
|
+
readonly declaredCapabilities?: readonly string[];
|
|
10
60
|
readonly readers?: ProviderSessionReaders;
|
|
11
61
|
readonly now?: () => number;
|
|
12
62
|
}
|
|
@@ -18,9 +68,27 @@ export interface ResolvedLiveIdentity {
|
|
|
18
68
|
readonly legacyInstance?: string;
|
|
19
69
|
readonly action: "override" | "reclaim" | "mint";
|
|
20
70
|
readonly providerSessionSource?: string;
|
|
71
|
+
/**
|
|
72
|
+
* The host-native provider session id actually read (Claude
|
|
73
|
+
* CLAUDE_CODE_SESSION_ID / Codex thread id), when one was readable. Exposed so
|
|
74
|
+
* the caller can build a heartbeat display-name refresher against the same
|
|
75
|
+
* conversation this identity resolved from (spec
|
|
76
|
+
* 2026-07-25-h2a-lane-addressing §D1b). Absent when no provider session was
|
|
77
|
+
* readable — do NOT substitute the synthetic `fallback:` id here, it names no
|
|
78
|
+
* transcript.
|
|
79
|
+
*/
|
|
80
|
+
readonly providerSessionId?: string;
|
|
21
81
|
readonly privateKeyPath?: string;
|
|
22
82
|
readonly publicKeyPath?: string;
|
|
23
83
|
readonly migrationNotice?: string;
|
|
24
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Short, stable, NON-SECRET fingerprint of a public key: the first 16 hex chars
|
|
87
|
+
* of its sha256. Used by the reclaim proof's nonce and by the enrollment
|
|
88
|
+
* ceremony's owner-facing summary, so the owner can eyeball WHICH key was
|
|
89
|
+
* proved without ever reading a PEM. It is a label, never an authority: nothing
|
|
90
|
+
* may accept a fingerprint where it should verify a signature.
|
|
91
|
+
*/
|
|
92
|
+
export declare function publicKeyFingerprint(publicKeyPem: string): string;
|
|
25
93
|
export declare function resolveLiveIdentity(input: ResolveLiveIdentityInput): ResolvedLiveIdentity;
|
|
26
94
|
//# sourceMappingURL=live.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/live.ts"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAGpF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACjD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/runtime/identity/live.ts"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAGpF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,yBAAyB,sDAO5B,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,EAAE,SAAS,qBAAqB,EAGzE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAC1C,qBAAqB,EAAE,CAGzB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACjD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAsCD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEjE;AAoHD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,oBAAoB,CAqHzF"}
|