Add activated workspace reflection and Studio definition watches
Expose bounded snapshot-bound definition reads and latest-only watches from the serving checked bundle. Add checked reflection dependency ports, generated SDK bindings and selector-scoped invocation authority. Move Studio factory, contract and query discovery to public reflection inventories. Share an active-definition watch across canvas and standalone routes and invalidate/reload on epoch changes instead of polling GetWorkspace. Document the API and deferred scope; cover compiler/codegen, SDK injection, transport authorization, activation publication, pagination and reconnect behavior. Keep all work local; no deployment or publication.
This commit is contained in:
@@ -12,6 +12,17 @@ const schemaFor = (body: string): BindingSchema => {
|
||||
if (!compiled.ok || compiled.resource.kind !== "package") throw new Error("expected package");
|
||||
return { format: "quixos-bindings", version: 1, interfaces: [], packages: [compiled.resource.revision] };
|
||||
};
|
||||
test("reflection ports generate explicit selector-restricted package bindings", () => {
|
||||
const schema = schemaFor(
|
||||
'function inspect id "inspect" : unit -> unit requires { reflection meta id "meta" [active, atoms, interfaces, conformances, queries, indexes]; };',
|
||||
);
|
||||
const generated = generateTypeScriptBindings(schema, "demo@1");
|
||||
assert.match(
|
||||
generated,
|
||||
/QxReflectionPort<"active" \| "atoms" \| "interfaces" \| "conformances" \| "queries" \| "indexes">/,
|
||||
);
|
||||
assert.match(generated, /"kind": "reflection"/);
|
||||
});
|
||||
test("generator uses exact IDs, restricted ports, nominal references, and lossless scalar types", () => {
|
||||
const schema = schemaFor(
|
||||
'operation run id "run-id" : list<int64> -> optional<atom-ref<Thing>> mode call receiver atom Thing requires { state payload id "payload-id" : bytes [read]; };',
|
||||
|
||||
@@ -43,6 +43,7 @@ test("runtime conformance descriptors preserve closed and universal collection i
|
||||
};
|
||||
operation inspect<object Item> id "inspect" : ref<Item> -> unit mode call receiver any requires {
|
||||
interface items id "items" : Collection<Item>;
|
||||
reflection metadata id "metadata" [atoms, interfaces];
|
||||
};
|
||||
}`,
|
||||
{ source, environment: { interfaces: new Map([["Collection", collection.resource.revision]]) } },
|
||||
@@ -77,6 +78,11 @@ test("runtime conformance descriptors preserve closed and universal collection i
|
||||
return null;
|
||||
},
|
||||
inspect: async (context) => {
|
||||
await context.ports.metadata.read({selector:{kind:"atoms",interfaceRevisionId:"named"}});
|
||||
// @ts-expect-error Queries are outside this port's declared authority.
|
||||
await context.ports.metadata.read({selector:{kind:"queries"}});
|
||||
// @ts-expect-error Interface inventory does not support atom filters.
|
||||
await context.ports.metadata.read({selector:{kind:"interfaces",atomId:"book"}});
|
||||
const view = await context.conform.tryConform(context.objectId, context.ports.items.contract);
|
||||
if (view) await view["items.connect"](context.input);
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { compileCapabilityResourceSource, compileCapabilitySource } from "../src/capability-language/parser.js";
|
||||
import { generateTypeScriptBindings } from "../src/bindings/index.js";
|
||||
const source = { repository: "https://example.test/meta.git", commit: "a".repeat(40) };
|
||||
|
||||
test("reflection authority is an explicit checked workspace binding, including generic exports", () => {
|
||||
const iface = compileCapabilityResourceSource(
|
||||
'interface Inspect id "inspect" revision "inspect@1" {operation run id "run" : unit -> unit {call id "call";}}',
|
||||
{ source },
|
||||
);
|
||||
assert.ok(iface.ok && iface.resource.kind === "interface");
|
||||
if (!iface.ok || iface.resource.kind !== "interface") throw Error("interface");
|
||||
const interfaceRevision = iface.resource.revision;
|
||||
for (const generic of [false, true]) {
|
||||
const pkg = compileCapabilityResourceSource(
|
||||
`package Inspector id "inspector" revision "inspector@1" {operation run${generic ? "<value T>" : ""} id "run" : unit -> unit mode call receiver any requires {reflection meta id "meta" [atoms, interfaces];};}`,
|
||||
{ source },
|
||||
);
|
||||
assert.ok(pkg.ok && pkg.resource.kind === "package", JSON.stringify(pkg.diagnostics));
|
||||
if (!pkg.ok || pkg.resource.kind !== "package") throw Error("package");
|
||||
const packageRevision = pkg.resource.revision;
|
||||
const compile = (selectors: string) =>
|
||||
compileCapabilitySource(
|
||||
`workspace W id "ws" revision "ws@1" commit "${source.commit}" {
|
||||
import interface Inspect;import package Inspector;atom Thing id "thing";
|
||||
conform Thing as Inspect id "inspection" {bind run.call to package Inspector.run${generic ? "<string>" : ""} with {meta to workspace reflection [${selectors}];};}
|
||||
}`,
|
||||
"workspace.qx",
|
||||
{ interfaces: new Map([["Inspect", interfaceRevision]]), packages: new Map([["Inspector", packageRevision]]) },
|
||||
);
|
||||
const result = compile("atoms, interfaces");
|
||||
assert.ok(result.ok, JSON.stringify(result.diagnostics));
|
||||
assert.equal(compile("atoms").ok, false, "binding cannot narrow or expand the declared contract silently");
|
||||
assert.equal(compile("atoms, interfaces, queries").ok, false);
|
||||
if (!result.ok) throw Error("workspace");
|
||||
const generated = generateTypeScriptBindings(
|
||||
{
|
||||
format: "quixos-bindings",
|
||||
version: 1,
|
||||
interfaces: result.workspace.interfaceImports,
|
||||
packages: result.workspace.packageImports,
|
||||
},
|
||||
"inspector@1",
|
||||
);
|
||||
assert.match(generated, /QxReflectionPort/);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user