@almadar/std 17.0.3 → 17.1.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/behaviors/lolo/auth/atoms/std-dev-personas.lolo +27 -2
- package/behaviors/lolo/cli/atoms/std-orb-goldens.lolo +6 -3
- package/behaviors/lolo/cli/atoms/std-orb-lint-mem-handles.lolo +54 -34
- package/behaviors/lolo/cli/atoms/std-orb-lint-os-grants.lolo +4 -4
- package/behaviors/lolo/cli/atoms/std-orb-mcp.lolo +16 -21
- package/behaviors/lolo/cli/atoms/std-orb-serve.lolo +24 -4
- package/behaviors/lolo/codec/atoms/std-lolo-kotlin.lolo +26 -3
- package/behaviors/lolo/codec/atoms/std-lolo-python.lolo +15 -2
- package/behaviors/lolo/codec/atoms/std-lolo-rust.lolo +27 -2
- package/behaviors/lolo/codec/atoms/std-lolo-source.lolo +251 -60
- package/behaviors/lolo/codec/atoms/std-lolo-swift.lolo +24 -1
- package/behaviors/lolo/codec/atoms/std-lolo-typescript.lolo +24 -3
- package/behaviors/lolo/connect/atoms/std-meta-ads.lolo +4 -4
- package/behaviors/lolo/connect/atoms/std-stdio-lines.lolo +7 -4
- package/behaviors/lolo/connect/atoms/std-youtube.lolo +9 -9
- package/behaviors/lolo/dev/atoms/std-guest-session.lolo +122 -10
- package/behaviors/lolo/dev/atoms/std-mock-seed-marks.lolo +66 -0
- package/behaviors/lolo/dev/organisms/std-behavior-playground.lolo +5 -2
- package/behaviors/lolo/dev/organisms/std-launchpad.lolo +4 -3
- package/behaviors/lolo/gpu/atoms/std-gpu-compute.lolo +329 -0
- package/behaviors/lolo/net/atoms/std-http-client.lolo +4 -4
- package/behaviors/lolo/net/atoms/std-http-fetch.lolo +6 -6
- package/behaviors/lolo/net/atoms/std-npm-lookup.lolo +1 -1
- package/behaviors/lolo/net/atoms/std-npm-registry.lolo +2 -2
- package/behaviors/lolo/spec/auth/dev-personas.replay.goldens.json +263 -2
- package/behaviors/lolo/spec/cli/lint-all.lolo +1 -0
- package/behaviors/lolo/spec/cli/lint-item-action-event.replay.goldens.json +9 -9
- package/behaviors/lolo/spec/cli/lint-mem-handles.replay.goldens.json +3021 -1
- package/behaviors/lolo/spec/cli/lint-os-grants.replay.goldens.json +284 -12
- package/behaviors/lolo/spec/cli/mcp-server.replay.goldens.json +51 -55
- package/behaviors/lolo/spec/cli/orb-compile.replay.goldens.json +10 -4
- package/behaviors/lolo/spec/codec/lolo-kotlin.replay.goldens.json +7496 -7497
- package/behaviors/lolo/spec/codec/lolo-python.replay.goldens.json +341 -3
- package/behaviors/lolo/spec/codec/lolo-rust.replay.goldens.json +18931 -6142
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/compose-pair.lolo +44 -0
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/config-read.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/divide-default.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/divide-plain.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/get-past-end.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/list-call.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/list-plain.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/minus-binary.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/minus-unary.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/nested-let.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/no-machine.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/no-template.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/nth-past-end.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/nth-raw.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/ports-call.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/range-one.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/range-two.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/router-trio.lolo +88 -0
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/store-pair.lolo +62 -0
- package/behaviors/lolo/spec/codec/lolo-source.fixtures/string-literal.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.gen/knobs.py +27 -1
- package/behaviors/lolo/spec/codec/lolo-source.gen/src_assemble.in +54 -2
- package/behaviors/lolo/spec/codec/lolo-source.gen/src_finish.in +1 -1
- package/behaviors/lolo/spec/codec/lolo-source.gen/src_fold.in +24 -4
- package/behaviors/lolo/spec/codec/lolo-source.gen/src_head.in +8 -3
- package/behaviors/lolo/spec/codec/lolo-source.gen/src_prepare.in +6 -2
- package/behaviors/lolo/spec/codec/lolo-source.gen/src_trait.in +12 -2
- package/behaviors/lolo/spec/codec/lolo-source.parity/agent-step.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.parity/agent-step.server.lolo +1 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/chunk.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.parity/chunk.server.lolo +1 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/compose-pair.events.json +36 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/compose-pair.replay.goldens.json +91 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/cosine.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.parity/cosine.server.lolo +1 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/kotlin/compose-pair.kt +31 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/kotlin/router-trio.kt +31 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/kotlin/store-pair.kt +31 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/python/compose-pair.py +18 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/python/router-trio.py +18 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/python/store-pair.py +17 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/rust/compose-pair.rs +37 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/rust/router-trio.rs +37 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/rust/store-pair.rs +36 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/swift/compose-pair.swift +24 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/swift/router-trio.swift +24 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/swift/store-pair.swift +23 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/typescript/compose-pair.mts +24 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/typescript/router-trio.mts +24 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/typescript/store-pair.mts +22 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/recall-at-k.lolo +2 -1
- package/behaviors/lolo/spec/codec/lolo-source.parity/recall-at-k.server.lolo +1 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/router-trio.events.json +18 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/router-trio.replay.goldens.json +87 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/store-pair.events.json +58 -0
- package/behaviors/lolo/spec/codec/lolo-source.parity/store-pair.replay.goldens.json +238 -0
- package/behaviors/lolo/spec/codec/lolo-swift.replay.goldens.json +15599 -2204
- package/behaviors/lolo/spec/codec/lolo-typescript.replay.goldens.json +28930 -28929
- package/behaviors/lolo/spec/connect/bearer-api.replay.goldens.json +1 -1
- package/behaviors/lolo/spec/connect/esign.replay.goldens.json +3 -3
- package/behaviors/lolo/spec/connect/github.replay.goldens.json +13 -13
- package/behaviors/lolo/spec/connect/google-calendar.replay.goldens.json +2 -2
- package/behaviors/lolo/spec/connect/image.replay.goldens.json +1 -1
- package/behaviors/lolo/spec/connect/meta-ads.replay.goldens.json +2 -2
- package/behaviors/lolo/spec/connect/stdio-lines.replay.goldens.json +90 -0
- package/behaviors/lolo/spec/connect/twilio.replay.goldens.json +2 -2
- package/behaviors/lolo/spec/connect/youtube.replay.goldens.json +1 -1
- package/behaviors/lolo/spec/dev/guest-session.replay.goldens.json +824 -0
- package/behaviors/lolo/spec/dev/mock-seed-marks.replay.goldens.json +365 -0
- package/behaviors/lolo/spec/dev/verify-walk.replay.goldens.json +2 -1
- package/behaviors/lolo/spec/gpu/gpu-compute.replay.goldens.json +784 -0
- package/behaviors/lolo/spec/mem/mem-buffer.replay.goldens.json +97 -1
- package/behaviors/lolo/spec/ml/vector-write.goldens.json +1 -1
- package/behaviors/lolo/spec/ml/vector-write.replay.goldens.json +2 -2
- package/behaviors/lolo/spec/net/http-client-call-host.replay.goldens.json +3 -3
- package/behaviors/lolo/spec/net/http-client-env-host.replay.goldens.json +3 -3
- package/behaviors/lolo/spec/net/http-client.replay.goldens.json +56 -56
- package/behaviors/lolo/spec/net/http-fetch.replay.goldens.json +2 -2
- package/behaviors/lolo/spec/net/npm-lookup.replay.goldens.json +1 -1
- package/behaviors/lolo/spec/net/npm-registry.replay.goldens.json +2 -2
- package/behaviors/lolo/spec/net/server-declared-traits.replay.goldens.json +6 -3
- package/behaviors/lolo/spec/net/server-external-inputs.replay.goldens.json +16 -8
- package/behaviors/lolo/spec/net/server-retargeted-leg.replay.goldens.json +4 -2
- package/behaviors/lolo/spec/net/server-untargeted-discovery.replay.goldens.json +50 -45
- package/behaviors/lolo/spec/ops/llm-spend-board.replay.goldens.json +112 -16
- package/behaviors/lolo/spec/store/firestore-twin.replay.goldens.json +1 -1
- package/behaviors/lolo/spec/store/row-store-postgres.gen/record_real_sql.py +1 -1
- package/behaviors/lolo/spec/ui/game/fx-particles.replay.goldens.json +37 -0
- package/behaviors/lolo/ui/avl/atoms/std-avl-cosmic-zoom.lolo +2 -2
- package/behaviors/lolo/ui/game/atoms/std-fx-particles.lolo +10 -1
- package/behaviors/lolo/ui/game/atoms/ui-draw-fx-layer.lolo +4 -4
- package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +9 -9
- package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +4 -4
- package/behaviors/lolo/ui/game/organisms/std-dungeon-board-2d.lolo +5 -5
- package/behaviors/lolo/ui/game/organisms/std-market-board-3d.lolo +9 -9
- package/behaviors/lolo/ui/game/organisms/std-objective-board-3d.lolo +9 -9
- package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +5 -5
- package/behaviors/lolo/ui/game/organisms/std-platformer-puzzle.lolo +4 -4
- package/behaviors/lolo/ui/game/organisms/std-survival-board-3d.lolo +9 -9
- package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +5 -5
- package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +9 -9
- package/behaviors/registry/auth/atoms/std-dev-personas.orb +1 -1
- package/behaviors/registry/cli/atoms/std-orb-goldens.orb +1 -1
- package/behaviors/registry/cli/atoms/std-orb-lint-mem-handles.orb +1 -1
- package/behaviors/registry/cli/atoms/std-orb-lint-os-grants.orb +1 -1
- package/behaviors/registry/cli/atoms/std-orb-mcp.orb +1 -1
- package/behaviors/registry/cli/atoms/std-orb-serve.orb +1 -1
- package/behaviors/registry/codec/atoms/std-lolo-kotlin.orb +1 -1
- package/behaviors/registry/codec/atoms/std-lolo-python.orb +1 -1
- package/behaviors/registry/codec/atoms/std-lolo-rust.orb +1 -1
- package/behaviors/registry/codec/atoms/std-lolo-source.orb +1 -1
- package/behaviors/registry/codec/atoms/std-lolo-swift.orb +1 -1
- package/behaviors/registry/codec/atoms/std-lolo-typescript.orb +1 -1
- package/behaviors/registry/connect/atoms/std-meta-ads.orb +1 -1
- package/behaviors/registry/connect/atoms/std-stdio-lines.orb +1 -1
- package/behaviors/registry/connect/atoms/std-youtube.orb +1 -1
- package/behaviors/registry/dev/atoms/std-guest-session.orb +1 -1
- package/behaviors/registry/dev/atoms/std-mock-seed-marks.orb +1 -0
- package/behaviors/registry/dev/organisms/std-behavior-playground.orb +37 -0
- package/behaviors/registry/dev/organisms/std-launchpad.orb +25 -0
- package/behaviors/registry/gpu/atoms/std-gpu-compute.orb +1 -0
- package/behaviors/registry/net/atoms/std-http-client.orb +1 -1
- package/behaviors/registry/net/atoms/std-http-fetch.orb +1 -1
- package/behaviors/registry/net/atoms/std-npm-lookup.orb +1 -1
- package/behaviors/registry/net/atoms/std-npm-registry.orb +1 -1
- package/behaviors/registry/spec/cli/lint-all.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/compose-pair.orb +1 -0
- package/behaviors/registry/spec/codec/lolo-source.fixtures/config-read.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/divide-default.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/divide-plain.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/get-past-end.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/list-call.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/list-plain.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/minus-binary.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/minus-unary.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/nested-let.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/no-machine.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/no-template.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/nth-past-end.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/nth-raw.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/ports-call.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/range-one.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/range-two.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.fixtures/router-trio.orb +1 -0
- package/behaviors/registry/spec/codec/lolo-source.fixtures/store-pair.orb +1 -0
- package/behaviors/registry/spec/codec/lolo-source.fixtures/string-literal.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/agent-step.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/agent-step.server.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/chunk.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/chunk.server.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/cosine.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/cosine.server.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/recall-at-k.orb +1 -1
- package/behaviors/registry/spec/codec/lolo-source.parity/recall-at-k.server.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/std-avl-cosmic-zoom.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-fx-layer.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +20 -13
- package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +9 -5
- package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +17 -7
- package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +19 -15
- package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +15 -12
- package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +17 -7
- package/behaviors/registry/ui/game/organisms/std-platformer-puzzle.orb +4 -0
- package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +15 -12
- package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +13 -6
- package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +14 -12
- package/canonical-operators.json +1426 -103
- package/dist/{chunk-EK22WRB6.js → chunk-2UGHBVU2.js} +2 -2
- package/dist/{chunk-GDMH5T4J.js → chunk-3DK7GI2C.js} +2 -2
- package/dist/chunk-3MDASC5C.js +26 -0
- package/dist/{chunk-K5ZI27PB.js → chunk-3PHO4RRF.js} +1 -1
- package/dist/{chunk-7IEMMYM6.js → chunk-4MJCLAZW.js} +1 -1
- package/dist/{chunk-W4IEV4BY.js → chunk-55JPIL7A.js} +2 -2
- package/dist/{chunk-RUGBZTV3.js → chunk-66BLZLFI.js} +1 -1
- package/dist/{chunk-YWFISV7L.js → chunk-66RAJFOD.js} +1 -1
- package/dist/{chunk-JWOWWGNZ.js → chunk-6ED4SUC6.js} +1 -1
- package/dist/{chunk-LL7P6EII.js → chunk-6KFCHNE2.js} +2 -2
- package/dist/{chunk-GFBL2TW6.js → chunk-A4QB3Y6L.js} +1 -1
- package/dist/chunk-BVWMLS32.js +123 -0
- package/dist/{chunk-5KQCGSNC.js → chunk-CRKVDCY7.js} +1 -1
- package/dist/{chunk-WHQDLLC3.js → chunk-EKWEY4OJ.js} +1 -1
- package/dist/{chunk-Y3BRVNYK.js → chunk-EU22GCGV.js} +2 -2
- package/dist/{chunk-XQPYTDZ4.js → chunk-FB6PKNRS.js} +1 -1
- package/dist/{chunk-UX3MDFX6.js → chunk-FSVOJQLP.js} +1 -1
- package/dist/{chunk-LDBD2FBQ.js → chunk-GAKLBWBR.js} +1 -1
- package/dist/{chunk-C3IEMPRZ.js → chunk-GO3FKBV2.js} +2 -2
- package/dist/{chunk-LZSPEHSM.js → chunk-GPDTJHYY.js} +1 -1
- package/dist/{chunk-W5ABMOXU.js → chunk-JQBWLH5V.js} +1 -1
- package/dist/{chunk-63X6RNY6.js → chunk-KKW3JHTC.js} +1 -1
- package/dist/{chunk-5PLJE42Q.js → chunk-LF2EZVAM.js} +1 -1
- package/dist/{chunk-RXWBYWQB.js → chunk-LGCKOZP3.js} +2 -2
- package/dist/{chunk-JJEADYP7.js → chunk-LMZ6XJFB.js} +2 -2
- package/dist/{chunk-CWYSQZJU.js → chunk-M2YQNSAZ.js} +2 -2
- package/dist/{chunk-GNCKJV3P.js → chunk-MKWHYBIS.js} +1 -1
- package/dist/{chunk-ZB2CLGEG.js → chunk-MXBGYTYF.js} +1 -1
- package/dist/{chunk-UN76TRSK.js → chunk-NH6MXHZR.js} +41 -41
- package/dist/{chunk-II2VW7T6.js → chunk-ODBIX4DB.js} +1 -1
- package/dist/{chunk-3F3CNWOG.js → chunk-OYDQR6DT.js} +2 -2
- package/dist/{chunk-FVL6BT6L.js → chunk-PD6POR44.js} +1 -1
- package/dist/{chunk-U6USXZ5M.js → chunk-PHFT3QNS.js} +2 -2
- package/dist/{chunk-RJYKIZMS.js → chunk-PQZ6PVKG.js} +2 -2
- package/dist/{chunk-TQPQXCSZ.js → chunk-Q6NHXIOZ.js} +2 -2
- package/dist/{chunk-KYGWVCTM.js → chunk-QMDVYTB7.js} +1 -1
- package/dist/{chunk-XKTATY45.js → chunk-RW2KMSG5.js} +4 -4
- package/dist/{chunk-UHNSPTFT.js → chunk-SA2ZS24W.js} +1 -1
- package/dist/{chunk-6YPUQK36.js → chunk-SFWP4UMK.js} +2 -2
- package/dist/{chunk-ZZYLFHBU.js → chunk-TLNEQA4D.js} +1 -1
- package/dist/{chunk-RGTBRWWA.js → chunk-TOODE5AD.js} +2 -2
- package/dist/{chunk-QGWAHOFR.js → chunk-U57GY7SM.js} +2 -2
- package/dist/{chunk-FDJZKB7J.js → chunk-UIDQQJSX.js} +1 -1
- package/dist/{chunk-LLH3WXM3.js → chunk-UVFP2B7I.js} +1 -1
- package/dist/{chunk-4OF7727E.js → chunk-VEGZPCTZ.js} +2 -2
- package/dist/{chunk-73YUPNIT.js → chunk-VXN4V7LC.js} +1 -1
- package/dist/{chunk-4D3W6AAE.js → chunk-YHQVZWPG.js} +1 -1
- package/dist/{chunk-XXYBHYLM.js → chunk-YQO3TO66.js} +2 -2
- package/dist/{chunk-YZAYFR5A.js → chunk-ZSJ3GEOJ.js} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +50 -50
- package/dist/modules/anim.js +2 -2
- package/dist/modules/array.js +2 -2
- package/dist/modules/auth.js +3 -3
- package/dist/modules/behavior.js +2 -2
- package/dist/modules/bit.js +2 -2
- package/dist/modules/browser.js +2 -2
- package/dist/modules/bytes.js +2 -2
- package/dist/modules/codec.js +3 -3
- package/dist/modules/composition.js +2 -2
- package/dist/modules/core.js +2 -2
- package/dist/modules/csv.js +2 -2
- package/dist/modules/ffi.js +3 -3
- package/dist/modules/format.js +2 -2
- package/dist/modules/geo.js +2 -2
- package/dist/modules/gpu.d.ts +12 -0
- package/dist/modules/gpu.js +3 -0
- package/dist/modules/grid.js +2 -2
- package/dist/modules/i18n.js +2 -2
- package/dist/modules/index.d.ts +1 -2
- package/dist/modules/index.js +45 -46
- package/dist/modules/json.js +2 -2
- package/dist/modules/kernel.js +3 -3
- package/dist/modules/kv.js +3 -3
- package/dist/modules/llm.js +2 -2
- package/dist/modules/math.js +2 -2
- package/dist/modules/mem.js +3 -3
- package/dist/modules/object.js +2 -2
- package/dist/modules/os-common.d.ts +1 -1
- package/dist/modules/os-common.js +2 -2
- package/dist/modules/os-desktop.js +3 -3
- package/dist/modules/os-dev.js +3 -3
- package/dist/modules/os-dir.js +3 -3
- package/dist/modules/os-env-stdio.js +3 -3
- package/dist/modules/os-fs.js +3 -3
- package/dist/modules/os-net.js +3 -3
- package/dist/modules/os-path.js +3 -3
- package/dist/modules/os-process.js +3 -3
- package/dist/modules/os-sys.js +3 -3
- package/dist/modules/os-time-users.js +3 -3
- package/dist/modules/os.js +13 -13
- package/dist/modules/path.js +2 -2
- package/dist/modules/prob.js +2 -2
- package/dist/modules/program.js +2 -2
- package/dist/modules/session.js +2 -2
- package/dist/modules/str.js +2 -2
- package/dist/modules/time.js +2 -2
- package/dist/modules/validate.js +2 -2
- package/dist/modules/vector.js +2 -2
- package/dist/modules/workspace.js +2 -2
- package/dist/modules/xml.js +2 -2
- package/dist/modules/yaml.js +2 -2
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +49 -49
- package/dist/{types-BA4LkhNJ.d.ts → types-CgiGhK6t.d.ts} +17 -3
- package/package.json +5 -5
- package/dist/chunk-F5TP25JA.js +0 -26
- package/dist/chunk-NE4WSTN7.js +0 -26
- package/dist/modules/trace.d.ts +0 -15
- package/dist/modules/trace.js +0 -2
- /package/dist/{chunk-SHSBTDDX.js → chunk-QUQ33UXH.js} +0 -0
|
@@ -42,9 +42,17 @@ orbital DevPersonasOrbital {
|
|
|
42
42
|
INIT -> ready when (!= @config.autoSignIn "")
|
|
43
43
|
(os/getenv "FIREBASE_AUTH_EMULATOR_HOST" { key: "auto" emit: { success: AUTO_HOST failure: AUTO_FAILED } })
|
|
44
44
|
AUTO_HOST -> ready when (= (default @payload.value "") @config.authEmulatorHost)
|
|
45
|
-
(
|
|
45
|
+
(fetch DevPersona { limit: @config.maxRows emit: { success: AUTO_ROWS failure: AUTO_ROWS_FAILED } })
|
|
46
46
|
AUTO_HOST -> ready when (!= (default @payload.value "") @config.authEmulatorHost)
|
|
47
47
|
AUTO_FAILED -> ready
|
|
48
|
+
AUTO_ROWS -> ready
|
|
49
|
+
(emit AUTO_RESOLVED { id: (let ((byId (array/find @payload.data (fn r (= (default @r.id "") @config.autoSignIn)))) (byRole (array/find @payload.data (fn r (= (default @r.role "") @config.autoSignIn))))) (default (object/get (default @byId (default @byRole {})) "id") "")) })
|
|
50
|
+
AUTO_RESOLVED -> ready when (!= @payload.id "")
|
|
51
|
+
(emit TOKEN_MINT { key: @payload.id, purpose: "sign-in" })
|
|
52
|
+
AUTO_RESOLVED -> ready when (= @payload.id "")
|
|
53
|
+
(emit PERSONA_SIGN_IN_REFUSED { error: (str/concat "persona sign-in refused: no identity row has the id or the role " @config.autoSignIn), kind: "no-persona" })
|
|
54
|
+
AUTO_ROWS_FAILED -> ready
|
|
55
|
+
(emit PERSONA_SIGN_IN_REFUSED { error: (str/concat "persona sign-in refused: the identity rows could not be read to resolve " @config.autoSignIn ": " (default @payload.error "")), kind: "no-persona" })
|
|
48
56
|
TOKEN_MINT -> ready
|
|
49
57
|
(emit TOKEN_MINTED { key: @payload.key, purpose: @payload.purpose, token: (str/concat (str/replace-pattern (str/replace-pattern (str/replace-pattern (base64/encode (json/stringify { alg: "none", typ: "JWT" })) "\\+" "-") "/" "_") "=+$" "") "." (str/replace-pattern (str/replace-pattern (str/replace-pattern (base64/encode (json/stringify { aud: (if (!= @config.emulatorAudience "") @config.emulatorAudience @config.projectId), iat: (time/diff @now @config.epoch "s"), exp: (+ (time/diff @now @config.epoch "s") 3600), iss: (if (!= @config.emulatorIssuer "") @config.emulatorIssuer (str/concat "https://securetoken.google.com/" @config.projectId)), sub: @payload.key, uid: @payload.key })) "\\+" "-") "/" "_") "=+$" "") ".") })
|
|
50
58
|
ANSWER_TOKEN_MINT -> ready
|
|
@@ -221,6 +229,23 @@ orbital DevPersonasOrbital {
|
|
|
221
229
|
}
|
|
222
230
|
@description "Internal: the environment could not be read at a session's start; the session stays as it is."
|
|
223
231
|
@tier "internal"
|
|
232
|
+
AUTO_ROWS -> internal {
|
|
233
|
+
data : [DevPersona]!
|
|
234
|
+
totalCount : number!
|
|
235
|
+
}
|
|
236
|
+
@description "Internal: the identity rows read to resolve autoSignIn at a session's start."
|
|
237
|
+
@tier "internal"
|
|
238
|
+
AUTO_ROWS_FAILED -> internal {
|
|
239
|
+
error : string
|
|
240
|
+
code : string
|
|
241
|
+
}
|
|
242
|
+
@description "Internal: the identity rows could not be read to resolve autoSignIn."
|
|
243
|
+
@tier "internal"
|
|
244
|
+
AUTO_RESOLVED -> internal {
|
|
245
|
+
id : string!
|
|
246
|
+
}
|
|
247
|
+
@description "Internal: the id of the identity row autoSignIn resolved to (an id match, else the first row of that role), or empty when none matched."
|
|
248
|
+
@tier "internal"
|
|
224
249
|
ACT_AS_HOST -> internal {
|
|
225
250
|
value : string
|
|
226
251
|
key : string
|
|
@@ -311,7 +336,7 @@ orbital DevPersonasOrbital {
|
|
|
311
336
|
@tier "infra"
|
|
312
337
|
autoSignIn : string = ""
|
|
313
338
|
@label "Auto sign-in persona"
|
|
314
|
-
@description "
|
|
339
|
+
@description "The ALMADAR_PERSONA spec of the persona to sign in as: an identity row id, else the first row whose role is this value; empty signs nobody in. A new session of an app running against the Auth emulator (FIREBASE_AUTH_EMULATOR_HOST equal to authEmulatorHost) reads the identity rows at its start, resolves the spec and signs in as that row: its unsigned emulator token goes through jws/verify (allowUnsigned, the emulator issuer knob) and identity/sign-in, the same path as the persona picker. A spec no row matches answers PERSONA_SIGN_IN_REFUSED naming it and leaves the session signed out. Never signs in anywhere else."
|
|
315
340
|
@synonyms "default persona, dev user, emulator user"
|
|
316
341
|
@tier "policy"
|
|
317
342
|
emulatorIssuer : string = ""
|
|
@@ -2,7 +2,7 @@ app std-orb-goldens [
|
|
|
2
2
|
version: "1.0.0",
|
|
3
3
|
inbound: ["cli-goldens"],
|
|
4
4
|
fs: { cwd: "**": [read], "/**": [read] },
|
|
5
|
-
description: "std-orb-goldens — the `orb goldens <file.goldens.json>` command, the parity-golden replay as a std program. The file names an atom (a path under the std lolo root, resolved three levels above the file: spec/<topic>/<file>), a default trait and cases; each case is a list of steps { trait, from, event, payload, expect { fired, state, emits [{ event, payload }], neverEmits [event] } }. It reads the file and the atom (os/read-file, program/read) and plays each case's steps in ONE program/step call, a fresh kernel per case. An expected emit matches the emit at the same position by event name and by every payload key it names (a nested value compares whole). One line per case, `pass` or `fail`, the unmet expectations indented under a fail, then `N passed, M failed`; status 200 (exit 0) when none failed, else 500 (exit 1); usage status 400 (exit 2); a failed read, parse or step answers 500 with its error. An expect may carry emitCounts ({ EVENT: n }, the event is emitted exactly n times in the step; 0 means never) and exactEmits, the step's complete ordered emit list: it must have as many emits as the step produced and each, in position, must match by event name and the payload keys it names, so an early incomplete emit is not masked by a later full one. A case is checked against the schema before it is played: an unknown case, step or expect key (note and golden are doc-only case strings, never asserted) each fail the case with a message. An expect.entity names fields of the step's row after its effects (program/step's result.entityAfter); each named key must be present and equal whole (a nested value compares whole), and a step answer with no row fails each named key. A case entity seeds the first step and a step entity seeds that step, through program/step's per-request entity; now is forwarded likewise, and a case config sets the knobs of the default trait on each of its steps. When a case fails, the failure also names each trait that fired in a step's cascade (other than the step's own trait) which no earlier step of the case plays and the case's `defaults` (a list of trait names that run on their entity defaults on purpose) does not list; a passing case is never annotated. A case credentials map (credential name to value) is test-only: the replay holds those credentials for each step of the case, answering the kernel's credential asks, and they are never journaled or printed; a name the map does not give is not held."
|
|
5
|
+
description: "std-orb-goldens — the `orb goldens <file.goldens.json>` command, the parity-golden replay as a std program. The file names an atom (a path under the std lolo root, resolved three levels above the file: spec/<topic>/<file>), a default trait and cases; each case is a list of steps { trait, from, event, payload, expect { fired, state, emits [{ event, payload }], neverEmits [event] } }. It reads the file and the atom (os/read-file, program/read) and plays each case's steps in ONE program/step call, a fresh kernel per case. An expected emit matches the emit at the same position by event name and by every payload key it names (a nested value compares whole). One line per case, `pass` or `fail`, the unmet expectations indented under a fail, then `N passed, M failed`; status 200 (exit 0) when none failed, else 500 (exit 1); usage status 400 (exit 2); a failed read, parse or step answers 500 with its error. An expect may carry emitCounts ({ EVENT: n }, the event is emitted exactly n times in the step; 0 means never) and exactEmits, the step's complete ordered emit list: it must have as many emits as the step produced and each, in position, must match by event name and the payload keys it names, so an early incomplete emit is not masked by a later full one. A case is checked against the schema before it is played: an unknown case, step or expect key (note and golden are doc-only case strings, never asserted) each fail the case with a message. An expect.entity names fields of the step's row after its effects (program/step's result.entityAfter); each named key must be present and equal whole (a nested value compares whole), and a step answer with no row fails each named key. A case entity seeds the first step and a step entity seeds that step, through program/step's per-request entity; now is forwarded likewise, and a case config sets the knobs of the default trait on each of its steps. When a case fails, the failure also names each trait that fired in a step's cascade (other than the step's own trait) which no earlier step of the case plays and the case's `defaults` (a list of trait names that run on their entity defaults on purpose) does not list; a passing case is never annotated. A step answers list ({ operator, ok } or { operator, error: { kind, message } }) is the host's plain answers to that step's os asks, forwarded to program/step, so the kernel unwraps, mints and routes them as it does live: a sealed handle is minted, never fed. A case credentials map (credential name to value) is test-only: the replay holds those credentials for each step of the case, answering the kernel's credential asks, and they are never journaled or printed; a name the map does not give is not held."
|
|
6
6
|
]
|
|
7
7
|
uses Spec from "almadar-std/orb-goldens"
|
|
8
8
|
type OrbCommandArgs = { argv : [string]!, cwd : string! }
|
|
@@ -12,7 +12,9 @@ type GoldenEmit = { event : string!, payload : GoldenPayload, optionsAt : number
|
|
|
12
12
|
type GoldenEmitted = { type : string!, payload : GoldenPayload }
|
|
13
13
|
type GoldenExpect = { fired : boolean, state : string, emits : [GoldenEmit], neverEmits : [string], exactEmits : [GoldenEmit], emitCounts : Map string number, effects : [GoldenPayload], rendered : [GoldenPayload], entity : GoldenPayload }
|
|
14
14
|
type GoldenIdentity = Map string GoldenValue?
|
|
15
|
-
type
|
|
15
|
+
type GoldenAnswerError = { kind : string!, message : string! }
|
|
16
|
+
type GoldenAnswer = { operator : string!, ok : GoldenValue?, error : GoldenAnswerError }
|
|
17
|
+
type GoldenStep = { answers : [GoldenAnswer], keep : string, keepField : string, now : number | string, identity : GoldenPayload?, entity : GoldenPayload, trait : string, orbital : string, from : string, event : string!, payload : GoldenPayload, options : GoldenPayload, expect : GoldenExpect }
|
|
16
18
|
type GoldenCase = { note : string, golden : string, skip : string, entity : GoldenPayload, config : GoldenPayload, credentials : Map string string, defaults : [string], now : number | string, id : string!, steps : [GoldenStep]! }
|
|
17
19
|
type GoldenFile = { atom : string!, trait : string!, orbital : string, cases : [GoldenCase]! }
|
|
18
20
|
type GoldenFull = { orbitals : [orbital] }
|
|
@@ -131,7 +133,7 @@ orbital GoldensOrbital {
|
|
|
131
133
|
(array/map (array/filter (object/keys @cc) (fn k (not (array/includes ["skip", "entity", "config", "credentials", "defaults", "now", "id", "steps", "note", "golden"] @k)))) (fn k (str/concat "unknown case key: " @k)))
|
|
132
134
|
(array/flatten (array/reduce (object/get @cc "steps") [] (fn acc s
|
|
133
135
|
(array/append @acc (array/concat
|
|
134
|
-
(array/map (array/filter (object/keys @s) (fn k (not (array/includes ["keep", "keepField", "now", "identity", "entity", "trait", "orbital", "from", "event", "payload", "options", "expect"] @k)))) (fn k (str/concat "step " (array/len @acc) ": unknown step key: " @k)))
|
|
136
|
+
(array/map (array/filter (object/keys @s) (fn k (not (array/includes ["answers", "keep", "keepField", "now", "identity", "entity", "trait", "orbital", "from", "event", "payload", "options", "expect"] @k)))) (fn k (str/concat "step " (array/len @acc) ": unknown step key: " @k)))
|
|
135
137
|
(array/map (array/filter (object/keys (object/get @s "expect" {})) (fn k (not (array/includes ["fired", "state", "emits", "neverEmits", "exactEmits", "emitCounts", "effects", "rendered", "entity"] @k)))) (fn k (str/concat "step " (array/len @acc) ": unknown expect key: " @k)))
|
|
136
138
|
(if (object/has @s "options")
|
|
137
139
|
(let ((op (as (object/get @s "options") GoldenPayload)))
|
|
@@ -168,6 +170,7 @@ orbital GoldensOrbital {
|
|
|
168
170
|
(if (or (= @seed null) (= (array/len (object/keys @seed)) 0)) {} { entity: @seed }))
|
|
169
171
|
(if (object/has @s "now") { now: (object/get @s "now") } (if (object/has @cc "now") { now: (object/get @cc "now") } {}))
|
|
170
172
|
(if (object/has @s "identity") { identity: (object/get @s "identity") } {})
|
|
173
|
+
(if (object/has @s "answers") { answers: (object/get @s "answers") } {})
|
|
171
174
|
(if (and (object/has @cc "config") (= (object/get @s "trait" (object/get @gf "trait")) (object/get @gf "trait"))) { config: (object/get @cc "config") } {})
|
|
172
175
|
(if (object/has @cc "credentials") { credentials: (object/get @cc "credentials") } {}))))))
|
|
173
176
|
{ key: "steps" emit: { success: GOLDENS_STEPPED, failure: GOLDENS_CASE_FAILED } render: (array/some (object/get @entity.curCase "steps") (fn s (= (object/get (default (as (object/get @s "options" {}) GoldenPayload) {}) "render") true))) renderProps: (array/some (object/get @entity.curCase "steps") (fn s (= (object/get (default (as (object/get @s "options" {}) GoldenPayload) {}) "renderProps") true))) live: (array/some (object/get @entity.curCase "steps") (fn s (= (object/get (default (as (object/get @s "options" {}) GoldenPayload) {}) "live") true))) })
|
|
@@ -4,7 +4,7 @@ app std-orb-lint-mem-handles [
|
|
|
4
4
|
env: ["PATH"],
|
|
5
5
|
exec: [exe],
|
|
6
6
|
fs: { cwd: "**": [read], "/**": [read], "~/.orb/node_modules/**": [read] },
|
|
7
|
-
description: "std-orb-lint-mem-handles — the `orb lint mem-handles <file>` command, the typestate check of EXEC-METAL-3
|
|
7
|
+
description: "std-orb-lint-mem-handles — the `orb lint mem-handles <file>` command, the typestate check of EXEC-METAL-3 and EXEC-GPU-5. The vocabulary is the `families` config (mem/ and gpu/ by default); the prose below describes the mem family, and the gpu family reuses the use-after-end, double-end and resting-state leak rules with its own ops (ORB_GPU_USE_AFTER_RELEASE, ORB_GPU_LEAK). The alias rule is mem-only. Over a trait's transition graph. It lowers the file with program/read and, for every inline trait that calls a mem/ operator, walks the graph (transition = edge from each `from` state to its `to` state, guards ignored, so every written path counts) carrying the set of handle facts true on some path into each state until nothing changes. HANDLE SOURCE: a handle is named only by the exact argument `@entity.<field>` (or, inside one transition, `@payload.<field>`); an argument that is anything else (a let binding, a computed value, an array element) is skipped, no finding. A handle enters a field only where a transition sets `@entity.<f>` from `@payload.arena`, `@payload.block` or `@payload.borrow` (the documented success payloads of mem/arena-new, mem/alloc and mem/borrow); any other `set @entity.<f>` rebinds f and forgets what was known of it. Order inside one effect or guard is its pre-order, mem calls before the sets nested in the same top-level effect. ORB_MEM_USE_AFTER_FREE: a mem/ call taking the handle (alloc, borrow, write, read, read-uint, length) on a path after mem/free, mem/arena-drop or mem/release of the same source. ORB_MEM_DOUBLE_FREE: a second mem/free, mem/arena-drop or mem/release of the same source on a path; dropping an arena also kills every block field the trait allocated from that arena field (the link is a mem/alloc whose success route sets that field from `@payload.block`), so a later free of such a block is a double free. ORB_MEM_ALIAS: a mem/borrow with the literal mode \"exclusive\" of a block source while a borrow of that source is live, or any borrow while an exclusive one is live; a borrow is live from the transition that sets its field from `@payload.borrow` (the borrow effect's success route; the field must be set by exactly one borrow call's route, else it is untracked) until mem/release of that field, and two borrow calls of one source inside one transition conflict at once. ORB_MEM_LEAK: a mem/arena-new whose arena is stored in an entity field (success route sets it from `@payload.arena`) and reaches a RESTING state of the trait without mem/arena-drop of that field on some path; RESTING means the trait's initial state or a state with no transition to a different state. A `stack` arena (literal kind) dies with its dispatch and is never a leak. Not tracked: handles outside the file's inline traits (composed `uses` traits are their own file's), handles passed through a payload, a let or an emit, and arenas overwritten without a drop. Clean answers `lint mem-handles: clean` (status 200, exit 0); findings are status 500, exit 1. Anything but one file argument is the usage (status 400, exit 2); an unreadable or unlowerable file is status 500."
|
|
8
8
|
]
|
|
9
9
|
uses Spec from "almadar-std/lint-mem-handles"
|
|
10
10
|
type OrbCommandArgs = { argv : [string]!, cwd : string! }
|
|
@@ -12,7 +12,8 @@ type MhValue = string | number | boolean | [MhValue?] | Map string MhValue?
|
|
|
12
12
|
type MhCall = [MhValue?]
|
|
13
13
|
type MhEmit = { success : string! }
|
|
14
14
|
type MhOpts = { emit : MhEmit! }
|
|
15
|
-
type MhOp = { k : string!, j : number!, at : string!, h : string!, src : string!, key : string!, lit : string!, ev : string!, f : string!, v : string! }
|
|
15
|
+
type MhOp = { k : string!, j : number!, at : string!, h : string!, src : string!, key : string!, lit : string!, ev : string!, f : string!, v : string!, cmd : string! }
|
|
16
|
+
type MhBody = Map string MhValue?
|
|
16
17
|
type MhT = { j : number!, ev : string!, to : string!, from : [string]!, ops : [MhOp]! }
|
|
17
18
|
type MhLink = { f : string!, h : string!, tgt : string! }
|
|
18
19
|
type MhAcc = { s : [string]!, f : [OrbFinding]! }
|
|
@@ -29,7 +30,8 @@ type OrbFinding = { code : string!, path : string!, message : string!, suggestio
|
|
|
29
30
|
type GtCallHit = { path : string, node : GtVal?, at : number }
|
|
30
31
|
type GtVal = string | number | boolean | [GtVal?] | Map string GtVal?
|
|
31
32
|
type LintCodeDecl = { code : string!, category : string!, description : string! }
|
|
32
|
-
type LintMemHandlesCodes = { useAfterFree : LintCodeDecl, doubleFree : LintCodeDecl, alias : LintCodeDecl, leak : LintCodeDecl , lintIndexMissing : LintCodeDecl }
|
|
33
|
+
type LintMemHandlesCodes = { useAfterFree : LintCodeDecl, doubleFree : LintCodeDecl, alias : LintCodeDecl, leak : LintCodeDecl, gpuUseAfterRelease : LintCodeDecl, gpuLeak : LintCodeDecl, lintIndexMissing : LintCodeDecl }
|
|
34
|
+
type LintHandleFamily = { name : string!, prefix : string!, handleFields : [string]!, ends : [string]!, endedText : string!, mintText : string!, useAfterKey : string!, doubleKey : string!, leakOp : string!, leakField : string!, leakEnd : string!, leakExempt : [string]!, leakNoun : string!, leakVerb : string!, leakKey : string!, allocOp : string!, allocField : string!, borrowOp : string!, borrowField : string!, releaseOp : string!, cmdOp : string!, cmdPos : number!, cmdKeys : [string]!, cmdListKeys : [string]! }
|
|
33
35
|
|
|
34
36
|
orbital OrbLintMemHandlesOrbital {
|
|
35
37
|
uses Input from "std/behaviors/std-orb-lint-input"
|
|
@@ -55,7 +57,9 @@ orbital OrbLintMemHandlesOrbital {
|
|
|
55
57
|
LINT_INPUT -> ready
|
|
56
58
|
(set @entity.scope @payload.scope)
|
|
57
59
|
(set @entity.findings (if (and @entity.sitesCallsHeard (= @entity.sitesCallsScope @payload.scope))
|
|
58
|
-
(let ((orbitals (object/get @payload.program "orbitals" []))
|
|
60
|
+
(let ((orbitals (object/get @payload.program "orbitals" [])))
|
|
61
|
+
(array/flatten (array/map @config.families (fn fam (let ((pfx : string (object/get @fam "prefix")) (handleFields : [string] (object/get @fam "handleFields")) (ends : [string] (object/get @fam "ends")) (leakOp : string (object/get @fam "leakOp")) (leakField : string (object/get @fam "leakField")) (leakEnd : string (object/get @fam "leakEnd")) (leakExempt : [string] (object/get @fam "leakExempt")) (allocOp : string (object/get @fam "allocOp")) (allocField : string (object/get @fam "allocField")) (borrowOp : string (object/get @fam "borrowOp")) (borrowField : string (object/get @fam "borrowField")) (releaseOp : string (object/get @fam "releaseOp")) (cmdOp : string (object/get @fam "cmdOp")) (cmdPos : number (object/get @fam "cmdPos")) (cmdKeys : [string] (object/get @fam "cmdKeys")) (cmdListKeys : [string] (object/get @fam "cmdListKeys")))
|
|
62
|
+
(let ((endsText : string (str/concat (str/join (array/map (array/filter @ends (fn e (!= @e (default (array/last @ends) "")))) (fn e (str/concat "`" @e "`"))) ", ") " or `" (default (array/last @ends) "") "`")) (memHits : [GtCallHit] (array/flatten (array/map (array/filter (object/keys @entity.sCalls) (fn h (str/startsWith @h @pfx))) (fn h (object/get @entity.sCalls @h []))))))
|
|
59
63
|
(array/flatten (array/map (array/range 0 (array/len @orbitals)) (fn oi
|
|
60
64
|
(let ((orb (default (array/nth @orbitals @oi) {})))
|
|
61
65
|
(array/flatten (array/map (array/range 0 (array/len (object/get @orb "traits" []))) (fn ti
|
|
@@ -78,27 +82,40 @@ orbital OrbLintMemHandlesOrbital {
|
|
|
78
82
|
ops: (array/flatten (array/map @items (fn e
|
|
79
83
|
(let ((nd (array/filter (array/map (json/nodes [@e]) (fn n (default (as @n MhCall) []))) (fn c (and (> (array/len @c) 0) (!= (as (array/first @c) string) null))))))
|
|
80
84
|
(array/concat
|
|
81
|
-
(array/map (array/filter @nd (fn c (str/startsWith (default (as (array/first @c) string) "")
|
|
85
|
+
(array/flatten (array/map (array/filter @nd (fn c (str/startsWith (default (as (array/first @c) string) "") @pfx))) (fn c
|
|
82
86
|
(let ((hd : string (default (as (array/first @c) string) "")) (a0 : string (default (as (array/nth @c 1) string) "")) (a1 : string (default (as (array/nth @c 2) string) "")) (opt (as (array/last @c) MhOpts)))
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
(array/concat
|
|
88
|
+
[{ k: "call", j: @j, at: @at, h: @hd, src: @a0, f: "", v: "", cmd: "",
|
|
89
|
+
key: (if (str/startsWith @a0 (str/concat @sig "entity.")) (str/slice @a0 8) (if (str/startsWith @a0 (str/concat @sig "payload.")) (str/concat "payload." (str/slice @a0 9)) "")),
|
|
90
|
+
lit: (if (= @hd @leakOp) @a0 @a1),
|
|
91
|
+
ev: (if (= @opt null) "" (object/get (object/get @opt "emit") "success" "")) }]
|
|
92
|
+
(if (or (= @cmdOp "") (!= @hd @cmdOp))
|
|
93
|
+
[]
|
|
94
|
+
(array/flatten (array/map (default (as (array/nth @c (+ @cmdPos 1)) MhCall) []) (fn ent
|
|
95
|
+
(let ((entm : MhBody (default (as @ent MhBody) {})))
|
|
96
|
+
(array/flatten (array/map (object/keys @entm) (fn cn
|
|
97
|
+
(let ((body : MhBody (default (as (object/get @entm @cn null) MhBody) {})))
|
|
98
|
+
(array/flatten (array/map (array/concat @cmdKeys @cmdListKeys) (fn kk
|
|
99
|
+
(let ((raw (object/get @body @kk null)))
|
|
100
|
+
(array/map (array/filter (if (array/includes @cmdListKeys @kk) (default (as @raw MhCall) []) [@raw]) (fn r (str/startsWith (default (as @r string) "") (str/concat @sig "entity.")))) (fn r
|
|
101
|
+
{ k: "call", j: @j, at: @at, h: @hd, src: (default (as @r string) ""), f: "", v: "", lit: "", ev: "",
|
|
102
|
+
cmd: (str/concat @cn "." @kk),
|
|
103
|
+
key: (str/slice (default (as @r string) "") 8) }))))))))))))))))))))
|
|
87
104
|
(array/map (array/filter @nd (fn c (and (= (default (as (array/first @c) string) "") "set") (> (array/len @c) 2) (str/startsWith (default (as (array/nth @c 1) string) "") (str/concat @sig "entity."))))) (fn c
|
|
88
|
-
{ k: "set", j: @j, at: @at, h: "", src: "", key: "", lit: "", ev: "",
|
|
105
|
+
{ k: "set", j: @j, at: @at, h: "", src: "", key: "", lit: "", ev: "", cmd: "",
|
|
89
106
|
f: (str/slice (default (as (array/nth @c 1) string) "") 8),
|
|
90
107
|
v: (default (as (array/nth @c 2) string) "") }))))))) }))))))
|
|
91
108
|
(if (not (array/some @perT (fn p (> (array/len (object/get @p "ops")) 0))))
|
|
92
109
|
[]
|
|
93
|
-
(let ((rows : [MhLink] (array/flatten (array/map (array/flatten (array/map @perT (fn p (array/filter (object/get @p "ops") (fn o (and (= (object/get @o "k") "
|
|
94
|
-
(let ((want : string (if (= (object/get @o "h")
|
|
95
|
-
(tgt : string (if (= (object/get @o "h")
|
|
110
|
+
(let ((rows : [MhLink] (array/flatten (array/map (array/flatten (array/map @perT (fn p (array/filter (object/get @p "ops") (fn o (and (= (object/get @o "k") "call") (!= (object/get @o "ev") "") (array/includes [@allocOp @borrowOp @leakOp] (object/get @o "h")) (array/includes @handleFields (if (= (object/get @o "h") @allocOp) @allocField (if (= (object/get @o "h") @borrowOp) @borrowField @leakField))))))))) (fn o
|
|
111
|
+
(let ((want : string (str/concat @sig "payload." (if (= (object/get @o "h") @allocOp) @allocField (if (= (object/get @o "h") @borrowOp) @borrowField @leakField))))
|
|
112
|
+
(tgt : string (if (= (object/get @o "h") @borrowOp) (str/concat (object/get @o "key") "|" (object/get @o "lit")) (if (= (object/get @o "h") @allocOp) (object/get @o "key") (object/get @o "lit")))))
|
|
96
113
|
(array/flatten (array/map @perT (fn p
|
|
97
114
|
(if (!= (object/get @p "ev") (object/get @o "ev"))
|
|
98
115
|
[]
|
|
99
116
|
(array/map (array/filter (object/get @p "ops") (fn s (and (= (object/get @s "k") "set") (= (object/get @s "v") @want)))) (fn s
|
|
100
117
|
{ f: (object/get @s "f"), h: (object/get @o "h"), tgt: @tgt }))))))))))))
|
|
101
|
-
(let ((links : [MhLink] (array/filter @rows (fn r (and (not (array/some @rows (fn r2 (and (= (object/get @r2 "f") (object/get @r "f")) (= (object/get @r2 "h") (object/get @r "h")) (!= (object/get @r2 "tgt") (object/get @r "tgt")))))) (or (= (object/get @r "h")
|
|
118
|
+
(let ((links : [MhLink] (array/filter @rows (fn r (and (not (array/some @rows (fn r2 (and (= (object/get @r2 "f") (object/get @r "f")) (= (object/get @r2 "h") (object/get @r "h")) (!= (object/get @r2 "tgt") (object/get @r "tgt")))))) (or (= (object/get @r "h") @leakOp) (and (!= (object/get @r "tgt") "") (not (str/startsWith (object/get @r "tgt") "|")))))))))
|
|
102
119
|
(let ((rinit : MhRound { facts: {}, fnd: [] }))
|
|
103
120
|
(let ((done : MhRound (array/reduce (array/range 0 (+ (array/len @stNames) 1)) @rinit (fn racc r
|
|
104
121
|
(let ((tinit : MhRound { facts: (object/get @racc "facts"), fnd: [] }))
|
|
@@ -108,43 +125,43 @@ orbital OrbLintMemHandlesOrbital {
|
|
|
108
125
|
(to : string (object/get @p "to"))
|
|
109
126
|
(ainit : MhAcc { s: [], f: [] }))
|
|
110
127
|
(let ((res : MhAcc (array/reduce (object/get @p "ops") (let ((a0 : MhAcc { s: @inF, f: [] })) @a0) (fn acc o
|
|
111
|
-
(let ((S : [string] (object/get @acc "s")) (F : [OrbFinding] (object/get @acc "f")) (k : string (object/get @o "key")) (h : string (object/get @o "h")) (lit : string (object/get @o "lit")))
|
|
128
|
+
(let ((S : [string] (object/get @acc "s")) (F : [OrbFinding] (object/get @acc "f")) (k : string (object/get @o "key")) (h : string (object/get @o "h")) (lit : string (object/get @o "lit")) (cmd : string (object/get @o "cmd")))
|
|
112
129
|
(if (= (object/get @o "k") "set")
|
|
113
130
|
(let ((f : string (object/get @o "f")) (v : string (object/get @o "v")))
|
|
114
|
-
(let ((bl (array/find @links (fn l (and (= (object/get @l "f") @f) (= (object/get @l "h")
|
|
115
|
-
(made (array/find @links (fn l (and (= (object/get @l "f") @f) (= (object/get @l "h")
|
|
131
|
+
(let ((bl (array/find @links (fn l (and (= (object/get @l "f") @f) (= (object/get @l "h") @borrowOp)))))
|
|
132
|
+
(made (array/find @links (fn l (and (= (object/get @l "f") @f) (= (object/get @l "h") @leakOp) (not (array/includes @leakExempt (object/get @l "tgt"))))))))
|
|
116
133
|
{ s: (array/concat
|
|
117
|
-
(array/filter @S (fn x (not (or (= @x (str/concat "F:" @f)) (and (or (str/startsWith @x "BX:") (str/startsWith @x "BS:")) (str/endsWith @x (str/concat ":" @f))) (and (= @v (str/concat @sig "payload.
|
|
118
|
-
(if (and (= @v (str/concat @sig "payload.
|
|
119
|
-
(if (and (= @v (str/concat @sig "payload.
|
|
134
|
+
(array/filter @S (fn x (not (or (= @x (str/concat "F:" @f)) (and (or (str/startsWith @x "BX:") (str/startsWith @x "BS:")) (str/endsWith @x (str/concat ":" @f))) (and (= @v (str/concat @sig "payload." @leakField)) (str/startsWith @x (str/concat "A:" @f ":"))) (and (= @v (str/concat @sig "payload." @allocField)) (or (str/startsWith @x (str/concat "BX:" @f ":")) (str/startsWith @x (str/concat "BS:" @f ":"))))))))
|
|
135
|
+
(if (and (= @v (str/concat @sig "payload." @leakField)) (!= @made null)) [(str/concat "A:" @f ":" (object/get @o "j"))] [])
|
|
136
|
+
(if (and (= @v (str/concat @sig "payload." @borrowField)) (!= @bl null) (array/includes ["exclusive" "shared"] (default (array/nth (str/split (object/get @bl "tgt") "|") 1) "")))
|
|
120
137
|
[(str/concat (if (= (array/nth (str/split (object/get @bl "tgt") "|") 1) "exclusive") "BX" "BS") ":" (default (array/first (str/split (object/get @bl "tgt") "|")) "") ":" @f)]
|
|
121
138
|
[])),
|
|
122
139
|
f: @F }))
|
|
123
140
|
(if (= @k "")
|
|
124
141
|
@acc
|
|
125
142
|
(let ((src : string (object/get @o "src")) (at : string (object/get @o "at"))
|
|
126
|
-
(isEnd : boolean (array/includes
|
|
143
|
+
(isEnd : boolean (array/includes @ends @h))
|
|
127
144
|
(freed : boolean (array/includes @S (str/concat "F:" @k)))
|
|
128
|
-
(modeOk : boolean (and (
|
|
145
|
+
(modeOk : boolean (and (!= @borrowOp "") (= @h @borrowOp) (array/includes ["exclusive" "shared"] @lit))))
|
|
129
146
|
(let ((conflict : boolean (and @modeOk (array/some @S (fn x (or (str/startsWith @x (str/concat "BX:" @k ":")) (str/startsWith @x (str/concat "pBX:" @k ":")) (and (= @lit "exclusive") (or (str/startsWith @x (str/concat "BS:" @k ":")) (str/startsWith @x (str/concat "pBS:" @k ":"))))))))))
|
|
130
|
-
{ s: (if (
|
|
147
|
+
{ s: (if (and @isEnd (!= @h @leakEnd) (!= @h @releaseOp))
|
|
131
148
|
(array/concat @S [(str/concat "F:" @k)])
|
|
132
|
-
(if (= @h
|
|
133
|
-
(let ((blocks : [string] (array/map (array/filter @links (fn l (and (= (object/get @l "h")
|
|
134
|
-
(if (= @h
|
|
149
|
+
(if (= @h @leakEnd)
|
|
150
|
+
(let ((blocks : [string] (array/map (array/filter @links (fn l (and (= (object/get @l "h") @allocOp) (= (object/get @l "tgt") @k)))) (fn l (object/get @l "f"))))) (array/concat (array/filter @S (fn x (not (or (str/startsWith @x (str/concat "A:" @k ":")) (array/some @blocks (fn b (or (str/startsWith @x (str/concat "BX:" @b ":")) (str/startsWith @x (str/concat "BS:" @b ":"))))))))) [(str/concat "F:" @k)] (array/map @blocks (fn b (str/concat "F:" @b)))))
|
|
151
|
+
(if (= @h @releaseOp)
|
|
135
152
|
(array/concat (array/filter @S (fn x (not (and (or (str/startsWith @x "BX:") (str/startsWith @x "BS:")) (str/endsWith @x (str/concat ":" @k)))))) [(str/concat "F:" @k)])
|
|
136
153
|
(if @modeOk
|
|
137
154
|
(array/concat @S [(str/concat (if (= @lit "exclusive") "pBX:" "pBS:") @k ":")])
|
|
138
155
|
@S)))),
|
|
139
156
|
f: (array/concat @F
|
|
140
157
|
(if (and @freed (not @isEnd))
|
|
141
|
-
[{ code: @config.codes
|
|
158
|
+
[{ code: (default (object/get (default (object/get @config.codes (object/get @fam "useAfterKey")) {}) "code") ""), path: @at, message: (if (= @cmd "") (str/concat "`(" @h " " @src " ...)` uses a handle that " @endsText " already ended on some path to this transition") (str/concat "`(" @h " ...)` command `" @cmd "` names `" @src "`, a handle that " @endsText " already ended on some path to this transition")), suggestion: (str/concat "Stop using the handle after it is " (object/get @fam "endedText") ", or rebind the field from a fresh " (object/get @fam "mintText") " first"), severity: "error" }]
|
|
142
159
|
[])
|
|
143
160
|
(if (and @freed @isEnd)
|
|
144
|
-
[{ code: @config.codes
|
|
161
|
+
[{ code: (default (object/get (default (object/get @config.codes (object/get @fam "doubleKey")) {}) "code") ""), path: @at, message: (str/concat "`(" @h " " @src ")` ends a handle that " @endsText " already ended on some path to this transition"), suggestion: "End each handle once on every path, or set the field to a new handle between the two", severity: "error" }]
|
|
145
162
|
[])
|
|
146
163
|
(if @conflict
|
|
147
|
-
[{ code: @config.codes.alias.code, path: @at, message: (str/concat "`(
|
|
164
|
+
[{ code: @config.codes.alias.code, path: @at, message: (str/concat "`(" @h " " @src " \"" @lit "\")` borrows a block that another borrow of it (an exclusive one, or any when this one is exclusive) still holds on some path to this transition"), suggestion: (str/concat "`" @releaseOp "` the earlier borrow before borrowing again"), severity: "error" }]
|
|
148
165
|
[])) })))))))))
|
|
149
166
|
{ facts: (object/set @inM @to (array/unique (array/concat (object/get @inM @to []) (array/filter (object/get @res "s") (fn x (not (or (str/startsWith @x "pB") (str/startsWith @x (str/concat "F:payload."))))))))),
|
|
150
167
|
fnd: (array/concat (object/get @acc2 "fnd") (object/get @res "f")) }))))))))))
|
|
@@ -153,11 +170,11 @@ orbital OrbLintMemHandlesOrbital {
|
|
|
153
170
|
(array/concat (object/get @done "fnd")
|
|
154
171
|
(array/map (array/unique (array/flatten (array/map @resting (fn r (array/filter (object/get @inFinal @r []) (fn x (str/startsWith @x "A:"))))))) (fn fact
|
|
155
172
|
(let ((parts : [string] (str/split @fact ":")))
|
|
156
|
-
{ code: @config.codes
|
|
173
|
+
{ code: (default (object/get (default (object/get @config.codes (object/get @fam "leakKey")) {}) "code") ""),
|
|
157
174
|
path: (str/concat @prefix ".transitions[" (default (array/nth @parts 2) "") "]"),
|
|
158
|
-
message: (str/concat "The
|
|
159
|
-
suggestion: "
|
|
160
|
-
severity: "error" }))))))))))))))))))))))
|
|
175
|
+
message: (str/concat "The " (object/get @fam "leakNoun") " stored in '" @sig "entity." (default (array/nth @parts 1) "") "' can reach the resting state(s) '" (str/join (array/filter @resting (fn r (array/includes (object/get @inFinal @r []) @fact))) "', '") "' without `" @leakEnd "`"),
|
|
176
|
+
suggestion: (str/concat (object/get @fam "leakVerb") " the " (object/get @fam "leakNoun") " on every path to a resting state, including the failure routes"),
|
|
177
|
+
severity: "error" })))))))))))))))))))))))))))
|
|
161
178
|
[{ code: @config.codes.lintIndexMissing.code, path: "", message: "the lint input arrived without LINT_SITES, so this rule cannot check the program", suggestion: "std-orb-lint-input sends LINT_SITES before LINT_INPUT; this rule did not hear it", severity: "error" }]))
|
|
162
179
|
(set @entity.sitesCallsHeard false)
|
|
163
180
|
(emit LINT_FINISH { })
|
|
@@ -183,9 +200,12 @@ orbital OrbLintMemHandlesOrbital {
|
|
|
183
200
|
OrbLintInput.LINT_SITES -> SITES_HEARD
|
|
184
201
|
}
|
|
185
202
|
config {
|
|
186
|
-
codes : LintMemHandlesCodes = { lintIndexMissing: { code: "ORB_LINT_INDEX_MISSING", category: "lint", description: "The lint input arrived without a shared program fact the rule reads (the structural index, sites, units, embeds or entities), so the rule cannot check the program" }, useAfterFree: { code: "ORB_MEM_USE_AFTER_FREE", category: "mem", description: "A mem/ call takes a handle after it was freed, dropped or released on some path" }, doubleFree: { code: "ORB_MEM_DOUBLE_FREE", category: "mem", description: "A handle is freed, dropped or released a second time on some path" }, alias: { code: "ORB_MEM_ALIAS", category: "mem", description: "An exclusive borrow of a block while another borrow of it is live, or a borrow while an exclusive one is live" }, leak: { code: "ORB_MEM_LEAK", category: "mem", description: "An arena reaches a resting state on some path without being dropped" } }
|
|
203
|
+
codes : LintMemHandlesCodes = { lintIndexMissing: { code: "ORB_LINT_INDEX_MISSING", category: "lint", description: "The lint input arrived without a shared program fact the rule reads (the structural index, sites, units, embeds or entities), so the rule cannot check the program" }, useAfterFree: { code: "ORB_MEM_USE_AFTER_FREE", category: "mem", description: "A mem/ call takes a handle after it was freed, dropped or released on some path" }, doubleFree: { code: "ORB_MEM_DOUBLE_FREE", category: "mem", description: "A handle is freed, dropped or released a second time on some path" }, alias: { code: "ORB_MEM_ALIAS", category: "mem", description: "An exclusive borrow of a block while another borrow of it is live, or a borrow while an exclusive one is live" }, leak: { code: "ORB_MEM_LEAK", category: "mem", description: "An arena reaches a resting state on some path without being dropped" }, gpuUseAfterRelease: { code: "ORB_GPU_USE_AFTER_RELEASE", category: "gpu", description: "A gpu/ call takes a handle after it was released or its device closed on some path, or a handle is released a second time" }, gpuLeak: { code: "ORB_GPU_LEAK", category: "gpu", description: "A device reaches a resting state on some path without being closed" } }
|
|
187
204
|
@label "Emitted codes"
|
|
188
205
|
@description "The finding codes this rule emits, with their category and meaning; the registry is generated from this declaration."
|
|
206
|
+
families : [LintHandleFamily] = [{ name: "mem", prefix: "mem/", handleFields: ["arena", "block", "borrow"], ends: ["mem/free", "mem/arena-drop", "mem/release"], endedText: "freed, dropped or released", mintText: "allocation", useAfterKey: "useAfterFree", doubleKey: "doubleFree", leakOp: "mem/arena-new", leakField: "arena", leakEnd: "mem/arena-drop", leakExempt: ["stack"], leakNoun: "arena", leakVerb: "Drop", leakKey: "leak", allocOp: "mem/alloc", allocField: "block", borrowOp: "mem/borrow", borrowField: "borrow", releaseOp: "mem/release", cmdOp: "", cmdPos: 0, cmdKeys: [], cmdListKeys: [] }, { name: "gpu", prefix: "gpu/", handleFields: ["device", "buffer", "texture", "sampler", "querySet", "shader", "pipeline", "bindGroup"], ends: ["gpu/release", "gpu/device-close"], endedText: "released or closed", mintText: "creation", useAfterKey: "gpuUseAfterRelease", doubleKey: "gpuUseAfterRelease", leakOp: "gpu/device-open", leakField: "device", leakEnd: "gpu/device-close", leakExempt: [], leakNoun: "device", leakVerb: "Close", leakKey: "gpuLeak", allocOp: "", allocField: "", borrowOp: "", borrowField: "", releaseOp: "", cmdOp: "gpu/submit", cmdPos: 1, cmdKeys: ["buffer", "texture", "from", "to", "pipeline", "target", "querySet"], cmdListKeys: ["bindGroups"] }]
|
|
207
|
+
@label "Handle families"
|
|
208
|
+
@description "The handle vocabulary the rule walks, one record per family: the op prefix; the payload fields whose success route mints a handle (handleFields); the ends (an end ends a handle, a later use is a finding, a second end is the double-end finding named by doubleKey); the resting-state leak rule (leakOp mints a handle into payload leakField, leakEnd ends it, leakExempt lists the literal first arguments of leakOp that never leak, a minted handle that reaches a resting state of the trait without leakEnd is the leakKey finding). allocOp, borrowOp and releaseOp are the mem alias machinery (a block allocated from the leak handle, exclusive or shared borrows of it, the release that ends a borrow): the alias rule exists only for a family that declares borrowOp, so gpu leaves them empty. An empty op or field turns that rule off for the family. cmdOp names the op whose argument at position cmdPos (0 is the first) is a list of command records (gpu/submit, position 1; empty for none): each literal `@entity.<f>` under a cmdKeys key of a record's body, or in the list under a cmdListKeys key, counts as a use of that handle, like a first argument."
|
|
189
209
|
}
|
|
190
210
|
|
|
191
211
|
}
|
|
@@ -2,7 +2,7 @@ app std-orb-lint-os-grants [
|
|
|
2
2
|
version: "1.0.0",
|
|
3
3
|
inbound: ["cli-lint-os-grants"],
|
|
4
4
|
fs: { cwd: "**": [read], "/**": [read] },
|
|
5
|
-
description: "std-orb-lint-os-grants — the `orb lint os-grants <file>` command, the static os-grant check. It asks the kernel (`program/os-grants`, twice: the program as written, then the finished program) for the typed findings of the file's resolved program and words them: ORB_OS_GRANT_MISSING (an `os/` call the grants of its orbital do not cover), ORB_OS_GRANT_UNUSED (a warning: a granted entry no call uses), ORB_OS_GRANT_ENTRY_INVALID (an entry that can match nothing)
|
|
5
|
+
description: "std-orb-lint-os-grants — the `orb lint os-grants <file>` command, the static os-grant check. It asks the kernel (`program/os-grants`, twice: the program as written, then the finished program) for the typed findings of the file's resolved program and words them: ORB_OS_GRANT_MISSING (an `os/` call the grants of its orbital do not cover), ORB_OS_GRANT_UNUSED (a warning: a granted entry no call uses), ORB_OS_GRANT_ENTRY_INVALID (an entry that can match nothing) ORB_OS_TARGET_NOT_STATIC (a computed target, so its grant cannot be checked) ORB_GPU_SHADER_INVALID (a literal gpu/shader-create WGSL source naga refuses) and ORB_GPU_BINDING_MISMATCH (a gpu/bind-group-create whose literal entries do not fit the bindings its pipeline uses, the pipeline traced through the trait to its WGSL; the finished-program pass only), at the site the kernel names. The finished-program pass answers as the rule os-grants-final, which belongs to `orb validate --final` only. Clean answers `lint os-grants: clean` (status 200, exit 0); findings are status 500, exit 1. Anything but one file argument is the usage (status 400, exit 2); a file the compiler cannot resolve is skipped here: validate reports that failure itself."
|
|
6
6
|
]
|
|
7
7
|
uses Spec from "almadar-std/lint-os-grants"
|
|
8
8
|
type OrbCommandArgs = { argv : [string]!, cwd : string! }
|
|
@@ -16,7 +16,7 @@ type RcRefRow = { kind : string!, path : string!, callSite : GrNode!, declaratio
|
|
|
16
16
|
type RcKept = { orbital : number!, traits : [string]! }
|
|
17
17
|
|
|
18
18
|
type LintCodeDecl = { code : string!, category : string!, description : string! }
|
|
19
|
-
type LintOsGrantsCodes = { missing : LintCodeDecl, unused : LintCodeDecl, entryInvalid : LintCodeDecl, targetNotStatic : LintCodeDecl }
|
|
19
|
+
type LintOsGrantsCodes = { missing : LintCodeDecl, unused : LintCodeDecl, entryInvalid : LintCodeDecl, targetNotStatic : LintCodeDecl, shaderInvalid : LintCodeDecl, bindingMismatch : LintCodeDecl }
|
|
20
20
|
|
|
21
21
|
orbital OrbLintOsGrantsOrbital {
|
|
22
22
|
uses CsInput from "std/behaviors/std-orb-lint-call-site-input"
|
|
@@ -76,7 +76,7 @@ orbital OrbLintOsGrantsOrbital {
|
|
|
76
76
|
state mapping {
|
|
77
77
|
INIT -> mapping
|
|
78
78
|
LINT_MAP -> mapping
|
|
79
|
-
(set @entity.mapped (array/map @entity.tagged (fn x (let ((f (object/get @x "f")) (via (object/get (object/get @x "f") "via" "")) (code (object/get (object/get @x "f") "code")) (orbital (object/get (object/get @x "f") "orbital" "")) (call (object/get (object/get @x "f") "call" "")) (entry (object/get (object/get @x "f") "entry" "")) (arg (object/get (object/get @x "f") "argument" 0))) { final: (object/get @x "final"), finding: { code: (if (= @code "missing") @config.codes.missing.code (if (= @code "unused") @config.codes.unused.code (if (= @code "entry-invalid") @config.codes.entryInvalid.code @config.codes.targetNotStatic.code))), path: (object/get @f "site"), severity: (if (= @code "unused") "warning" "error"), message: (if (= @code "missing") (str/concat "`" @call "` " (if (= @via "config") "can be given " "needs ") @entry (if (= @via "config") " by its config, but orbital " " but orbital ") @orbital " does not grant it") (if (= @code "unused") (str/concat "`" @entry "` is granted to " (if (= @orbital "") "the program" (str/concat "orbital " @orbital)) " but no `os/` call there uses it") (if (= @code "entry-invalid") @entry (if (= @via "config-unresolvable") (str/concat "`" @call "` argument " @arg " is read from config in a way the finished program cannot resolve, so its grant cannot be checked") (if (= @via "computed-path") (str/concat "`" @call "` argument " @arg " is a computed path the grant cannot cover: only a file path may be a `str/concat`") (str/concat "`" @call "` argument " @arg " is computed — an `os/` target must be a literal so the grant can be checked at build time")))))), suggestion: (if (= @code "missing") (str/concat "Add `" (object/get @f "grant" "") (if (object/get @f "app" false) "` to the orbital's bracket (`orbital Name [ … ]`) or the app's" "` to the orbital's bracket")) (if (= @code "unused") "Remove the entry: an unused grant is authority the program does not need" (if (= @code "entry-invalid") "" (if (= @via "config-unresolvable") "Read the target with `@config.<knob>`, `array/nth` and `object/get`, or write it as a literal; a `str/concat` directory prefix must be string knobs and literals ending in `/`" (if (= @via "computed-path") "Write the target as a literal" "Write the path, command, host, port or name as a literal; a file path may instead be a `str/concat` that starts with a literal or `@config.<knob>` directory ending in `/`, covered by an fs grant ending in `/**`, or an anchored path `{ anchor: \"cwd\" path: … }` (anchors `exe-dir`, `cwd`, `{ env: \"NAME\" }`) covered by an anchored grant such as `fs: { cwd: \"docs/**\": [read] }`; a host or port may be `{ anchor: { env: \"PORT\" } }` covered by `net: { env HOST, env PORT: [listen] }`"))))) } }))))
|
|
79
|
+
(set @entity.mapped (array/map @entity.tagged (fn x (let ((f (object/get @x "f")) (via (object/get (object/get @x "f") "via" "")) (code (object/get (object/get @x "f") "code")) (orbital (object/get (object/get @x "f") "orbital" "")) (call (object/get (object/get @x "f") "call" "")) (entry (object/get (object/get @x "f") "entry" "")) (arg (object/get (object/get @x "f") "argument" 0))) { final: (object/get @x "final"), finding: { code: (if (= @code "missing") @config.codes.missing.code (if (= @code "unused") @config.codes.unused.code (if (= @code "entry-invalid") @config.codes.entryInvalid.code (if (= @code "shader-invalid") @config.codes.shaderInvalid.code (if (= @code "binding-mismatch") @config.codes.bindingMismatch.code @config.codes.targetNotStatic.code))))), path: (object/get @f "site"), severity: (if (= @code "unused") "warning" "error"), message: (if (= @code "missing") (str/concat "`" @call "` " (if (= @via "config") "can be given " "needs ") @entry (if (= @via "config") " by its config, but orbital " " but orbital ") @orbital " does not grant it") (if (= @code "unused") (str/concat "`" @entry "` is granted to " (if (= @orbital "") "the program" (str/concat "orbital " @orbital)) " but no `os/` call there uses it") (if (or (= @code "entry-invalid") (= @code "shader-invalid")) @entry (if (= @code "binding-mismatch") (str/concat "`gpu/bind-group-create` entries do not fit the pipeline they are made for: " @entry) (if (= @via "config-unresolvable") (str/concat "`" @call "` argument " @arg " is read from config in a way the finished program cannot resolve, so its grant cannot be checked") (if (= @via "computed-path") (str/concat "`" @call "` argument " @arg " is a computed path the grant cannot cover: only a file path may be a `str/concat`") (str/concat "`" @call "` argument " @arg " is computed — an `os/` target must be a literal so the grant can be checked at build time"))))))), suggestion: (if (= @code "missing") (str/concat "Add `" (object/get @f "grant" "") (if (object/get @f "app" false) "` to the orbital's bracket (`orbital Name [ … ]`) or the app's" "` to the orbital's bracket")) (if (= @code "unused") "Remove the entry: an unused grant is authority the program does not need" (if (or (= @code "entry-invalid") (= @code "shader-invalid")) "" (if (= @code "binding-mismatch") "Give one entry per binding the pipeline's entry points use in that group, each the resource the WGSL declares (buffer, texture or sampler)" (if (= @via "config-unresolvable") "Read the target with `@config.<knob>`, `array/nth` and `object/get`, or write it as a literal; a `str/concat` directory prefix must be string knobs and literals ending in `/`" (if (= @via "computed-path") "Write the target as a literal" "Write the path, command, host, port or name as a literal; a file path may instead be a `str/concat` that starts with a literal or `@config.<knob>` directory ending in `/`, covered by an fs grant ending in `/**`, or an anchored path `{ anchor: \"cwd\" path: … }` (anchors `exe-dir`, `cwd`, `{ env: \"NAME\" }`) covered by an anchored grant such as `fs: { cwd: \"docs/**\": [read] }`; a host or port may be `{ anchor: { env: \"PORT\" } }` covered by `net: { env HOST, env PORT: [listen] }`")))))) } }))))
|
|
80
80
|
(emit LINT_SPLIT { })
|
|
81
81
|
LINT_SPLIT -> ready
|
|
82
82
|
(set @entity.findings (array/map (array/filter @entity.mapped (fn m (not (object/get @m "final")))) (fn m (object/get @m "finding"))))
|
|
@@ -117,7 +117,7 @@ orbital OrbLintOsGrantsOrbital {
|
|
|
117
117
|
@description "Internal: answer with the verdicts."
|
|
118
118
|
}
|
|
119
119
|
config {
|
|
120
|
-
codes : LintOsGrantsCodes = { missing: { code: "ORB_OS_GRANT_MISSING", category: "os", description: "An os/ call that the grants of its orbital (app level plus its own) do not cover" }, unused: { code: "ORB_OS_GRANT_UNUSED", category: "os", description: "A granted entry that no os/ call of the orbital (or of the program, at app level) uses; a warning" }, entryInvalid: { code: "ORB_OS_GRANT_ENTRY_INVALID", category: "os", description: "A declared grant entry that can match nothing" }, targetNotStatic: { code: "ORB_OS_TARGET_NOT_STATIC", category: "os", description: "An os/ call target that is computed, so its grant cannot be checked at build time" } }
|
|
120
|
+
codes : LintOsGrantsCodes = { missing: { code: "ORB_OS_GRANT_MISSING", category: "os", description: "An os/ call that the grants of its orbital (app level plus its own) do not cover" }, unused: { code: "ORB_OS_GRANT_UNUSED", category: "os", description: "A granted entry that no os/ call of the orbital (or of the program, at app level) uses; a warning" }, entryInvalid: { code: "ORB_OS_GRANT_ENTRY_INVALID", category: "os", description: "A declared grant entry that can match nothing" }, targetNotStatic: { code: "ORB_OS_TARGET_NOT_STATIC", category: "os", description: "An os/ call target that is computed, so its grant cannot be checked at build time" }, shaderInvalid: { code: "ORB_GPU_SHADER_INVALID", category: "os", description: "A literal gpu/shader-create WGSL source that naga refuses to parse or validate" }, bindingMismatch: { code: "ORB_GPU_BINDING_MISMATCH", category: "os", description: "A gpu/bind-group-create whose literal entries do not fit the bindings its traced pipeline's entry points use in its WGSL" } }
|
|
121
121
|
@label "Emitted codes"
|
|
122
122
|
@description "The finding codes this rule emits, with their category and meaning; the registry is generated from this declaration."
|
|
123
123
|
}
|
|
@@ -243,56 +243,54 @@ orbital OrbMcpOrbital {
|
|
|
243
243
|
(emit MCP_ANSWERED { status: 500, body: (str/concat "orb mcp: " (default @payload.error "")) })
|
|
244
244
|
MCP_EOF -> starting
|
|
245
245
|
(emit MCP_ANSWERED { status: 200, body: "" })
|
|
246
|
-
MCP_PUMP -> serving
|
|
247
|
-
(emit MCP_INPUT_NEXT {})
|
|
248
246
|
MCP_LINE_IN -> serving when (= (str/trim @payload.line) "")
|
|
249
|
-
(emit
|
|
247
|
+
(emit MCP_INPUT_NEXT {})
|
|
250
248
|
MCP_LINE_IN -> serving when (and (!= (str/trim @payload.line) "") (not (json/valid @payload.line)))
|
|
251
249
|
(set @entity.reply (json/stringify (let ((reply : McpParseError { jsonrpc: "2.0" id: null error: { code: -32700 message: "parse error: invalid JSON" } })) @reply)))
|
|
252
250
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
253
|
-
(emit
|
|
251
|
+
(emit MCP_INPUT_NEXT {})
|
|
254
252
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (= (json/parse @payload.line McpMessage) null))
|
|
255
253
|
(set @entity.reply (json/stringify (let ((reply : McpParseError { jsonrpc: "2.0" id: null error: { code: -32600 message: "Invalid Request" } })) @reply)))
|
|
256
254
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
257
|
-
(emit
|
|
255
|
+
(emit MCP_INPUT_NEXT {})
|
|
258
256
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (not (object/has (json/parse @payload.line McpMessage) "id")) (= (object/get (json/parse @payload.line McpMessage) "method") null))
|
|
259
257
|
(set @entity.reply (json/stringify (let ((reply : McpParseError { jsonrpc: "2.0" id: null error: { code: -32600 message: "Invalid Request" } })) @reply)))
|
|
260
258
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
261
|
-
(emit
|
|
259
|
+
(emit MCP_INPUT_NEXT {})
|
|
262
260
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (not (object/has (json/parse @payload.line McpMessage) "id")) (!= (object/get (json/parse @payload.line McpMessage) "method") null))
|
|
263
|
-
(emit
|
|
261
|
+
(emit MCP_INPUT_NEXT {})
|
|
264
262
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "initialize"))
|
|
265
263
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") result: { protocolVersion: (if (array/includes ["2025-06-18", "2025-03-26", "2024-11-05"] (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "protocolVersion")) (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "protocolVersion") "2025-06-18") capabilities: { tools: (json/parse "{}" McpJson) prompts: (json/parse "{}" McpJson) } serverInfo: { name: "orb" version: @entity.version } instructions: @entity.instructions } }))
|
|
266
264
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
267
|
-
(emit
|
|
265
|
+
(emit MCP_INPUT_NEXT {})
|
|
268
266
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "ping"))
|
|
269
267
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") result: (json/parse "{}" McpJson) }))
|
|
270
268
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
271
|
-
(emit
|
|
269
|
+
(emit MCP_INPUT_NEXT {})
|
|
272
270
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "tools/list"))
|
|
273
271
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") result: { tools: @entity.tools } }))
|
|
274
272
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
275
|
-
(emit
|
|
273
|
+
(emit MCP_INPUT_NEXT {})
|
|
276
274
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "prompts/list"))
|
|
277
275
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") result: { prompts: [{ name: "build" description: "Build an app in Orb, from finding behaviors to a program that validates 0/0" arguments: [{ name: "app" description: "What to build" required: false }] }] } }))
|
|
278
276
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
279
|
-
(emit
|
|
277
|
+
(emit MCP_INPUT_NEXT {})
|
|
280
278
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "prompts/get") (!= (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name") "build"))
|
|
281
279
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") error: { code: -32602 message: (str/concat "unknown prompt " (json/stringify (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name"))) } }))
|
|
282
280
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
283
|
-
(emit
|
|
281
|
+
(emit MCP_INPUT_NEXT {})
|
|
284
282
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "prompts/get") (= (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name") "build"))
|
|
285
283
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") result: { description: "Build an app in Orb" messages: [{ role: "user" content: { type: "text" text: (str/concat "Build " (default (object/get (default (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "arguments") {}) "app") "the app the user asked for") " in Orb.\n\n" @entity.instructions) } }] } }))
|
|
286
284
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
287
|
-
(emit
|
|
285
|
+
(emit MCP_INPUT_NEXT {})
|
|
288
286
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (not (array/includes ["initialize", "ping", "tools/list", "tools/call", "prompts/list", "prompts/get"] (object/get (json/parse @payload.line McpMessage) "method"))))
|
|
289
287
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") error: { code: -32601 message: (str/concat "method not found: " (default (object/get (json/parse @payload.line McpMessage) "method") "")) } }))
|
|
290
288
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
291
|
-
(emit
|
|
289
|
+
(emit MCP_INPUT_NEXT {})
|
|
292
290
|
MCP_LINE_IN -> serving when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "tools/call") (not (array/includes ["validate", "complete", "format", "operators", "patterns", "behaviors", "describe_behavior", "read_behavior", "play", "test", "reference", "evaluate"] (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name"))) (not (array/includes @entity.hookNames (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name"))))
|
|
293
291
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: (object/get (json/parse @payload.line McpMessage) "id") result: { content: [{ type: "text" text: (str/concat "orb has no tool `" (default (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name") "") "`") }] isError: true } }))
|
|
294
292
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
295
|
-
(emit
|
|
293
|
+
(emit MCP_INPUT_NEXT {})
|
|
296
294
|
MCP_LINE_IN -> working when (and (json/valid @payload.line) (!= (json/parse @payload.line McpMessage) null) (object/has (json/parse @payload.line McpMessage) "id") (= (object/get (json/parse @payload.line McpMessage) "method") "tools/call") (or (array/includes ["validate", "format", "behaviors", "describe_behavior", "read_behavior", "play", "operators", "patterns", "evaluate", "complete", "reference", "test"] (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name")) (array/includes @entity.hookNames (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name"))))
|
|
297
295
|
(set @entity.rid (object/get (json/parse @payload.line McpMessage) "id"))
|
|
298
296
|
(set @entity.tool (default (object/get (default (object/get (json/parse @payload.line McpMessage) "params") {}) "name") ""))
|
|
@@ -419,11 +417,11 @@ orbital OrbMcpOrbital {
|
|
|
419
417
|
MCP_TOOL_DONE -> serving
|
|
420
418
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: @entity.rid result: { content: [{ type: "text" text: (json/stringify @payload.result) }] structuredContent: @payload.result isError: false } }))
|
|
421
419
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
422
|
-
(emit
|
|
420
|
+
(emit MCP_INPUT_NEXT {})
|
|
423
421
|
MCP_TOOL_FAILED -> serving
|
|
424
422
|
(set @entity.reply (json/stringify { jsonrpc: "2.0" id: @entity.rid result: { content: [{ type: "text" text: @payload.error }] isError: true } }))
|
|
425
423
|
(emit MCP_LINE_OUT { line: @entity.reply })
|
|
426
|
-
(emit
|
|
424
|
+
(emit MCP_INPUT_NEXT {})
|
|
427
425
|
}
|
|
428
426
|
|
|
429
427
|
emits {
|
|
@@ -442,9 +440,6 @@ orbital OrbMcpOrbital {
|
|
|
442
440
|
@description "Start the composed standard input line transport."
|
|
443
441
|
MCP_INPUT_NEXT {}
|
|
444
442
|
@description "Acknowledge the processed request and permit the next line."
|
|
445
|
-
MCP_PUMP { }
|
|
446
|
-
@description "Internal: acknowledge the processed request."
|
|
447
|
-
@tier "internal"
|
|
448
443
|
MCP_LISTEN { }
|
|
449
444
|
@description "Internal: start reading stdin."
|
|
450
445
|
@tier "internal"
|
|
@@ -639,7 +634,7 @@ orbital OrbMcpOrbital {
|
|
|
639
634
|
words : [string]!
|
|
640
635
|
}
|
|
641
636
|
@description "std-args's ARGS_PARSED."
|
|
642
|
-
MCP_LINE_IN { line : string! }
|
|
637
|
+
MCP_LINE_IN { line : string! seq : number! }
|
|
643
638
|
@description "One framed input line from the transport."
|
|
644
639
|
MCP_EOF {}
|
|
645
640
|
@description "The transport reached EOF after all requests were acknowledged."
|