@lambdacurry/arbor 0.12.8 → 0.13.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.
Files changed (2) hide show
  1. package/dist/arbor.js +295 -5
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -1613,7 +1613,7 @@ var computerSnapshots = sqliteTable("computer_snapshots", {
1613
1613
  contentDigest: text("content_digest"),
1614
1614
  createdAt: ts("created_at").notNull()
1615
1615
  }, (t) => ({
1616
- providerRefIdx: uniqueIndex("computer_snapshots_provider_ref_idx").on(t.provider, t.providerRef),
1616
+ providerRefIdx: index("computer_snapshots_provider_ref_idx").on(t.provider, t.providerRef),
1617
1617
  topicBaseIdx: uniqueIndex("computer_snapshots_topic_base_idx").on(t.topicId, t.configKey),
1618
1618
  lineageIdx: uniqueIndex("computer_snapshots_lineage_idx").on(t.lineageKey),
1619
1619
  computerIdx: index("computer_snapshots_computer_idx").on(t.computerId, t.createdAt),
@@ -1801,6 +1801,105 @@ var artifactVersions = sqliteTable("artifact_versions", {
1801
1801
  }, (t) => ({
1802
1802
  artifactVersionUq: uniqueIndex("artifact_versions_artifact_version_uq").on(t.artifactId, t.version)
1803
1803
  }));
1804
+ var appBundles = sqliteTable("app_bundles", {
1805
+ id: text("id").primaryKey(),
1806
+ artifactVersionId: text("artifact_version_id").notNull().references(() => artifactVersions.id),
1807
+ spaceId: text("space_id").notNull().references(() => spaces.id),
1808
+ compatibilityDate: text("compatibility_date").notNull(),
1809
+ mainModule: text("main_module").notNull(),
1810
+ modules: text("modules", { mode: "json" }).$type().notNull(),
1811
+ staticAssets: text("static_assets", { mode: "json" }).$type().notNull(),
1812
+ runtimeEntrypoint: text("runtime_entrypoint").$type().notNull(),
1813
+ capabilityRequirements: text("capability_requirements", { mode: "json" }).$type().notNull().default([]),
1814
+ stateSchemaVersion: integer("state_schema_version").notNull().default(0),
1815
+ stateCompatibleFrom: integer("state_compatible_from").notNull().default(0),
1816
+ stateCompatibleThrough: integer("state_compatible_through").notNull().default(0),
1817
+ contentDigest: text("content_digest").notNull(),
1818
+ computerSessionId: text("computer_session_id").references(() => computerSessions.id),
1819
+ snapshotId: text("snapshot_id").references(() => computerSnapshots.id),
1820
+ createdByProfileId: text("created_by_profile_id").notNull().references(() => profiles.id),
1821
+ createdExecutionContextId: text("created_execution_context_id").notNull().references(() => executionContexts.id),
1822
+ idempotencyKey: text("idempotency_key"),
1823
+ idempotencyFingerprint: text("idempotency_fingerprint"),
1824
+ createdAt: ts("created_at").notNull()
1825
+ }, (t) => ({
1826
+ sourceDigestIdx: index("app_bundles_source_digest_idx").on(t.artifactVersionId, t.contentDigest),
1827
+ unkeyedSourceDigestUq: uniqueIndex("app_bundles_unkeyed_source_digest_uq").on(t.artifactVersionId, t.contentDigest).where(sql`${t.idempotencyKey} IS NULL`),
1828
+ digestIdx: index("app_bundles_content_digest_idx").on(t.contentDigest),
1829
+ spaceIdx: index("app_bundles_space_idx").on(t.spaceId, t.createdAt),
1830
+ idempotencyUq: uniqueIndex("app_bundles_idempotency_uq").on(t.computerSessionId, t.createdByProfileId, t.idempotencyKey)
1831
+ }));
1832
+ var apps = sqliteTable("apps", {
1833
+ id: text("id").primaryKey(),
1834
+ orgId: text("org_id").notNull().references(() => orgs.id),
1835
+ spaceId: text("space_id").notNull().references(() => spaces.id),
1836
+ title: text("title").notNull(),
1837
+ slug: text("slug").notNull(),
1838
+ lifecycle: text("lifecycle").$type().notNull().default("active"),
1839
+ access: text("access").$type().notNull(),
1840
+ discovery: text("discovery").$type(),
1841
+ activeDeploymentId: text("active_deployment_id"),
1842
+ runtimeProvider: text("runtime_provider").$type().notNull(),
1843
+ runtimeHealth: text("runtime_health").$type().notNull().default("unknown"),
1844
+ runtimeHealthUpdatedAt: ts("runtime_health_updated_at"),
1845
+ stateMode: text("state_mode").$type().notNull(),
1846
+ stateIdentity: text("state_identity").notNull(),
1847
+ stateGeneration: integer("state_generation").notNull().default(0),
1848
+ currentStateSchemaVersion: integer("current_state_schema_version").notNull().default(0),
1849
+ deploymentRevision: integer("deployment_revision").notNull().default(0),
1850
+ createdByProfileId: text("created_by_profile_id").notNull().references(() => profiles.id),
1851
+ createdExecutionContextId: text("created_execution_context_id").notNull().references(() => executionContexts.id),
1852
+ createdAt: ts("created_at").notNull(),
1853
+ archivedAt: ts("archived_at")
1854
+ }, (t) => ({
1855
+ slugUq: uniqueIndex("apps_slug_uq").on(t.slug),
1856
+ spaceIdx: index("apps_space_idx").on(t.spaceId, t.lifecycle, t.createdAt),
1857
+ orgIdx: index("apps_org_idx").on(t.orgId, t.access, t.discovery)
1858
+ }));
1859
+ var appDeployments = sqliteTable("app_deployments", {
1860
+ id: text("id").primaryKey(),
1861
+ appId: text("app_id").notNull().references(() => apps.id),
1862
+ bundleId: text("bundle_id").notNull().references(() => appBundles.id),
1863
+ version: integer("version").notNull(),
1864
+ contentDigest: text("content_digest").notNull(),
1865
+ status: text("status").$type().notNull().default("candidate"),
1866
+ deployedByProfileId: text("deployed_by_profile_id").notNull().references(() => profiles.id),
1867
+ deployedExecutionContextId: text("deployed_execution_context_id").notNull().references(() => executionContexts.id),
1868
+ idempotencyKey: text("idempotency_key").notNull(),
1869
+ idempotencyFingerprint: text("idempotency_fingerprint").notNull(),
1870
+ providerReceipt: text("provider_receipt", { mode: "json" }).$type(),
1871
+ healthResult: text("health_result", { mode: "json" }).$type(),
1872
+ failureCode: text("failure_code"),
1873
+ createdAt: ts("created_at").notNull(),
1874
+ verifiedAt: ts("verified_at"),
1875
+ activatedAt: ts("activated_at"),
1876
+ supersededAt: ts("superseded_at")
1877
+ }, (t) => ({
1878
+ appVersionUq: uniqueIndex("app_deployments_app_version_uq").on(t.appId, t.version),
1879
+ idempotencyUq: uniqueIndex("app_deployments_idempotency_uq").on(t.appId, t.deployedByProfileId, t.idempotencyKey),
1880
+ appIdx: index("app_deployments_app_idx").on(t.appId, t.createdAt),
1881
+ bundleIdx: index("app_deployments_bundle_idx").on(t.bundleId)
1882
+ }));
1883
+ var appStateResets = sqliteTable("app_state_resets", {
1884
+ id: text("id").primaryKey(),
1885
+ appId: text("app_id").notNull().references(() => apps.id),
1886
+ fromGeneration: integer("from_generation").notNull(),
1887
+ toGeneration: integer("to_generation").notNull(),
1888
+ idempotencyKey: text("idempotency_key").notNull(),
1889
+ resetByProfileId: text("reset_by_profile_id").notNull().references(() => profiles.id),
1890
+ resetExecutionContextId: text("reset_execution_context_id").notNull().references(() => executionContexts.id),
1891
+ providerReceipt: text("provider_receipt", { mode: "json" }).$type().notNull(),
1892
+ createdAt: ts("created_at").notNull()
1893
+ }, (t) => ({
1894
+ idempotencyUq: uniqueIndex("app_state_resets_idempotency_uq").on(t.appId, t.resetByProfileId, t.idempotencyKey),
1895
+ appIdx: index("app_state_resets_app_idx").on(t.appId, t.createdAt)
1896
+ }));
1897
+ var appViewerGrantUses = sqliteTable("app_viewer_grant_uses", {
1898
+ jti: text("jti").primaryKey(),
1899
+ appId: text("app_id").notNull().references(() => apps.id),
1900
+ profileId: text("profile_id").notNull().references(() => profiles.id),
1901
+ consumedAt: ts("consumed_at").notNull()
1902
+ });
1804
1903
  var requests = sqliteTable("requests", {
1805
1904
  id: text("id").primaryKey(),
1806
1905
  threadId: text("thread_id").notNull().references(() => threads.id),
@@ -1920,6 +2019,9 @@ var PREVIEW_MIME_TYPES = new Set([
1920
2019
  "font/woff",
1921
2020
  "font/woff2"
1922
2021
  ]);
2022
+ // ../core/src/ops/app.ts
2023
+ var APP_MAX_MODULE_BYTES = 10 * 1024 * 1024;
2024
+ var APP_MAX_ASSET_BYTES = 25 * 1024 * 1024;
1923
2025
  // ../core/src/queries/lane-match.ts
1924
2026
  var STOP_WORDS = new Set("a an and are as at be by for from has have here how i in is it me of on or our the their they this to was what when where which who will with you your".split(" "));
1925
2027
  // ../core/src/queries/activity.ts
@@ -16573,7 +16675,7 @@ var ACTIONS = [
16573
16675
  description: "Replace your organization's sparse computer-default layer without allocating runtime state. Omitted/null values fall back to provider defaults; Space, Topic, and Thread layers may override individual fields.",
16574
16676
  inputSchema: {
16575
16677
  backend: exports_external.enum(["worker-shell", "container"]).nullable().optional().describe("default execution tier, or null to use worker-shell"),
16576
- containerProfile: exports_external.string().nullable().optional().describe("optional logical Currybox container profile, or null to clear"),
16678
+ containerProfile: exports_external.string().nullable().optional().describe("logical container profile; use bun-typescript-v1 for the pinned Bun monorepo toolchain, or null to clear"),
16577
16679
  setupScript: exports_external.string().nullable().optional().describe("optional setup run when materializing a reusable base, or null to clear"),
16578
16680
  repositories: exports_external.array(exports_external.string()).nullable().optional().describe("default repositories, repeated --repositories; [] clears and null inherits provider default")
16579
16681
  },
@@ -16588,7 +16690,7 @@ var ACTIONS = [
16588
16690
  inputSchema: {
16589
16691
  spaceId: exports_external.string().describe("the Space, spc_…"),
16590
16692
  backend: exports_external.enum(["worker-shell", "container"]).nullable().optional().describe("override execution tier, or null to inherit"),
16591
- containerProfile: exports_external.string().nullable().optional().describe("optional logical Currybox container profile, or null to clear inherited profile"),
16693
+ containerProfile: exports_external.string().nullable().optional().describe("logical container profile; use bun-typescript-v1 for the pinned Bun monorepo toolchain, or null to clear inherited profile"),
16592
16694
  setupScript: exports_external.string().nullable().optional().describe("optional setup run when materializing a reusable base, or null to clear"),
16593
16695
  repositories: exports_external.array(exports_external.string()).nullable().optional().describe("repository allowlist/default clones; [] clears and null inherits")
16594
16696
  },
@@ -16603,7 +16705,7 @@ var ACTIONS = [
16603
16705
  inputSchema: {
16604
16706
  topicId: exports_external.string().describe("the Topic, top_…"),
16605
16707
  backend: exports_external.enum(["worker-shell", "container"]).nullable().optional().describe("override execution tier, or null to inherit"),
16606
- containerProfile: exports_external.string().nullable().optional().describe("optional logical Currybox container profile, or null to clear inherited profile"),
16708
+ containerProfile: exports_external.string().nullable().optional().describe("logical container profile; use bun-typescript-v1 for the pinned Bun monorepo toolchain, or null to clear inherited profile"),
16607
16709
  setupScript: exports_external.string().nullable().optional().describe("optional setup run, or null to clear"),
16608
16710
  repositories: exports_external.array(exports_external.string()).nullable().optional().describe("repository allowlist/default clones; [] clears and null inherits")
16609
16711
  },
@@ -16618,7 +16720,7 @@ var ACTIONS = [
16618
16720
  inputSchema: {
16619
16721
  threadId: exports_external.string().describe("the Thread, thr_…"),
16620
16722
  backend: exports_external.enum(["worker-shell", "container"]).nullable().optional().describe("override execution tier, or null to inherit"),
16621
- containerProfile: exports_external.string().nullable().optional().describe("optional logical Currybox container profile, or null to clear inherited profile"),
16723
+ containerProfile: exports_external.string().nullable().optional().describe("logical container profile; use bun-typescript-v1 for the pinned Bun monorepo toolchain, or null to clear inherited profile"),
16622
16724
  setupScript: exports_external.string().nullable().optional().describe("optional setup run, or null to clear"),
16623
16725
  repositories: exports_external.array(exports_external.string()).nullable().optional().describe("repository allowlist/default clones; [] clears and null inherits")
16624
16726
  },
@@ -16782,6 +16884,26 @@ var ACTIONS = [
16782
16884
  toolset: "loop",
16783
16885
  run: forward("computer_runtime.publish_preview")
16784
16886
  },
16887
+ {
16888
+ name: "computer_publish_app_bundle",
16889
+ title: "Publish an immutable AppBundle",
16890
+ description: "After a Bun container build is green, freeze one Worker entry module plus optional static assets from this Thread computer into a content-addressed AppBundle sourced from an ArtifactVersion. Use the returned bundleId with apps verb=deploy (CLI: app_deploy); uploads complete and verify before Arbor publishes the bundle manifest, and retries require the same idempotencyKey.",
16891
+ inputSchema: {
16892
+ computerSessionId: exports_external.string().describe("the computerSessionId returned by computer_open, cms_…"),
16893
+ artifactVersionId: exports_external.string().describe("the source ArtifactVersion, artv_…"),
16894
+ entryPath: exports_external.string().describe("absolute TypeScript/JavaScript Worker entry under /workspace"),
16895
+ assetsPath: exports_external.string().optional().describe("optional absolute static-asset directory under /workspace"),
16896
+ runtimeEntrypoint: exports_external.enum(["fetch", "durable-object"]).describe("fetch for stateless Apps; durable-object must export class App"),
16897
+ compatibilityDate: exports_external.string().describe("Cloudflare compatibility date, YYYY-MM-DD"),
16898
+ stateSchemaVersion: exports_external.number().int().min(0).optional().describe("durable schema this release writes; default 0"),
16899
+ stateCompatibleFrom: exports_external.number().int().min(0).optional().describe("oldest durable schema this code can open"),
16900
+ stateCompatibleThrough: exports_external.number().int().min(0).optional().describe("newest durable schema this code can open"),
16901
+ idempotencyKey: exports_external.string().min(1).max(200).describe("stable key for this one logical bundle publication")
16902
+ },
16903
+ surfaces: ["computer-mcp", "computer-cli"],
16904
+ toolset: "apps",
16905
+ run: forward("computer_runtime.publish_app_bundle")
16906
+ },
16785
16907
  {
16786
16908
  name: "computer_stop",
16787
16909
  title: "Checkpoint and stop",
@@ -17698,6 +17820,174 @@ var ACTIONS = [
17698
17820
  promote_attachment: "attachment.promote"
17699
17821
  }, (verb, input) => verb === "edit" ? { ...input, verb: Array.isArray(input.patches) ? "patch" : "replace" } : input)
17700
17822
  },
17823
+ {
17824
+ name: "apps",
17825
+ title: "List visible Apps",
17826
+ description: "List Apps available to you: every App in your Spaces plus listed public Apps across the organization. Lifecycle and runtime health are separate fields; unlisted public Apps appear only to their owning Space.",
17827
+ inputSchema: {
17828
+ includeArchived: exports_external.boolean().optional().describe("include archived Apps you are authorized to inspect")
17829
+ },
17830
+ surfaces: ["cli"],
17831
+ toolset: "apps",
17832
+ run: forward("app.list")
17833
+ },
17834
+ {
17835
+ name: "apps",
17836
+ title: "Publish and manage Apps",
17837
+ description: "Manage stable Arbor Apps through one guarded lifecycle (AD-248). verb=list shows Apps visible across your Spaces; get reads the current active release, state generation, and history; create mints the Space-owned identity; deploy health-checks an immutable AppBundle without moving the URL; deployment inspects one candidate; activate and rollback health-check then compare-and-swap the active release; set_access changes Space/public and public discovery immediately; reset_state is the only durable SQLite deletion; archive stops serving but retains history. Read with get immediately before activate, rollback, access, or reset so expectedActiveDeploymentId/expectedGeneration are current; start public Apps as public+unlisted+none and private stateful Apps as space+durable.",
17838
+ inputSchema: {
17839
+ verb: exports_external.enum([
17840
+ "list",
17841
+ "get",
17842
+ "create",
17843
+ "deploy",
17844
+ "deployment",
17845
+ "activate",
17846
+ "rollback",
17847
+ "set_access",
17848
+ "reset_state",
17849
+ "archive"
17850
+ ]).describe("which App lifecycle operation to perform"),
17851
+ includeArchived: exports_external.boolean().optional().describe("list: include authorized archived Apps"),
17852
+ appId: exports_external.string().optional().describe("required for every verb except list and create: the App, app_…"),
17853
+ spaceId: exports_external.string().optional().describe("create: owning Space, spc_…"),
17854
+ title: exports_external.string().min(1).max(160).optional().describe("create: short factual title"),
17855
+ slug: exports_external.string().min(1).max(59).optional().describe("create: stable label in app-<slug>.arborthreads.dev"),
17856
+ access: exports_external.enum(["space", "public"]).optional().describe("create/set_access: gateway access"),
17857
+ discovery: exports_external.enum(["unlisted", "listed"]).nullable().optional().describe("create/set_access: public discovery; Space Apps use null"),
17858
+ stateMode: exports_external.enum(["none", "durable"]).optional().describe("create: none or isolated durable SQLite"),
17859
+ bundleId: exports_external.string().optional().describe("deploy: verified immutable AppBundle, bnd_…"),
17860
+ deploymentId: exports_external.string().optional().describe("deployment/activate/rollback: deployment, dep_…"),
17861
+ expectedActiveDeploymentId: exports_external.string().nullable().optional().describe("activate/rollback: active deployment just read; null only for first activation"),
17862
+ expectedGeneration: exports_external.number().int().min(0).optional().describe("reset_state: durable generation just read"),
17863
+ idempotencyKey: exports_external.string().min(1).max(200).optional().describe("deploy/reset_state: stable key for this one logical mutation")
17864
+ },
17865
+ surfaces: ["mcp"],
17866
+ toolset: "apps",
17867
+ run: dispatch({
17868
+ list: "app.list",
17869
+ get: "app.get",
17870
+ create: "app.create",
17871
+ deploy: "app.deploy",
17872
+ deployment: "app.deployment_get",
17873
+ activate: "app.activate",
17874
+ rollback: "app.rollback",
17875
+ set_access: "app.set_access",
17876
+ reset_state: "app.reset_state",
17877
+ archive: "app.archive"
17878
+ })
17879
+ },
17880
+ {
17881
+ name: "app_get",
17882
+ title: "Read an App",
17883
+ description: "Inspect one App's stable URL, active release, source AppBundle, deployment timeline, runtime health, state identity/generation, and reset history. Read this before deployment, rollback, access, or state changes so your compare-and-swap inputs are current.",
17884
+ inputSchema: { appId: exports_external.string().describe("the App, app_…") },
17885
+ surfaces: ["cli"],
17886
+ toolset: "apps",
17887
+ run: forward("app.get")
17888
+ },
17889
+ {
17890
+ name: "app_create",
17891
+ title: "Create an App",
17892
+ description: "Create a stable first-class App identity in a Space before deploying code. Start small public Apps as public+unlisted+none; use space+durable only when the App needs membership authorization and isolated SQLite state.",
17893
+ inputSchema: {
17894
+ spaceId: exports_external.string().describe("owning Space, spc_…"),
17895
+ title: exports_external.string().min(1).max(160).describe("short factual App title"),
17896
+ slug: exports_external.string().min(1).max(59).describe("stable DNS label used by app-<slug>.arborthreads.dev"),
17897
+ access: exports_external.enum(["space", "public"]).describe("space requires membership; public is anonymous at the gateway"),
17898
+ discovery: exports_external.enum(["unlisted", "listed"]).nullable().optional().describe("public Apps only; default unlisted"),
17899
+ stateMode: exports_external.enum(["none", "durable"]).describe("durable allocates isolated facet SQLite; deployment never resets it")
17900
+ },
17901
+ surfaces: ["cli"],
17902
+ toolset: "apps",
17903
+ run: forward("app.create")
17904
+ },
17905
+ {
17906
+ name: "app_deploy",
17907
+ title: "Prepare an App deployment",
17908
+ description: "Create an immutable candidate from an AppBundle and run the provider health check without changing the stable URL. A failed candidate is recorded with redacted diagnostics and leaves the active release live; call app_activate only after this returns a verified candidate.",
17909
+ inputSchema: {
17910
+ appId: exports_external.string().describe("target App, app_…"),
17911
+ bundleId: exports_external.string().describe("verified immutable AppBundle, bnd_…"),
17912
+ idempotencyKey: exports_external.string().min(1).max(200).describe("stable key for this one logical deployment attempt")
17913
+ },
17914
+ surfaces: ["cli"],
17915
+ toolset: "apps",
17916
+ run: forward("app.deploy")
17917
+ },
17918
+ {
17919
+ name: "app_deployment",
17920
+ title: "Inspect an App deployment",
17921
+ description: "Read one deployment's candidate/active/failed/superseded state, source bundle, provider receipt, and redacted health result. Use it when a deployment is pending or failed; provider output never includes credentials.",
17922
+ inputSchema: {
17923
+ appId: exports_external.string().describe("owning App, app_…"),
17924
+ deploymentId: exports_external.string().describe("deployment, dep_…")
17925
+ },
17926
+ surfaces: ["cli"],
17927
+ toolset: "apps",
17928
+ run: forward("app.deployment_get")
17929
+ },
17930
+ {
17931
+ name: "app_activate",
17932
+ title: "Activate a verified deployment",
17933
+ description: "Atomically advance an App's stable URL to a verified candidate after a fresh health check. Pass the active deployment id you just read (or null for the first release); a concurrent change is rejected instead of overwriting it.",
17934
+ inputSchema: {
17935
+ appId: exports_external.string().describe("target App, app_…"),
17936
+ deploymentId: exports_external.string().describe("verified candidate, dep_…"),
17937
+ expectedActiveDeploymentId: exports_external.string().nullable().describe("active deployment from app_get, or null before first activation")
17938
+ },
17939
+ surfaces: ["cli"],
17940
+ toolset: "apps",
17941
+ run: forward("app.activate")
17942
+ },
17943
+ {
17944
+ name: "app_rollback",
17945
+ title: "Roll back App code",
17946
+ description: "Re-activate a superseded deployment while preserving the App's state identity and SQLite data. Durable rollback is refused when the target bundle cannot read the current state schema; reset is a separate destructive operation.",
17947
+ inputSchema: {
17948
+ appId: exports_external.string().describe("target App, app_…"),
17949
+ deploymentId: exports_external.string().describe("superseded deployment to restore, dep_…"),
17950
+ expectedActiveDeploymentId: exports_external.string().describe("current active deployment from app_get")
17951
+ },
17952
+ surfaces: ["cli"],
17953
+ toolset: "apps",
17954
+ run: forward("app.rollback")
17955
+ },
17956
+ {
17957
+ name: "app_set_access",
17958
+ title: "Change App access",
17959
+ description: "Change the gateway policy immediately and record who changed it: space requires a current Space member, while public permits anonymous requests and may be unlisted or listed. This does not redeploy code or pass an Arbor identity into App code.",
17960
+ inputSchema: {
17961
+ appId: exports_external.string().describe("target App, app_…"),
17962
+ access: exports_external.enum(["space", "public"]).describe("new gateway access"),
17963
+ discovery: exports_external.enum(["unlisted", "listed"]).nullable().optional().describe("required concept only for public Apps")
17964
+ },
17965
+ surfaces: ["cli"],
17966
+ toolset: "apps",
17967
+ run: forward("app.set_access")
17968
+ },
17969
+ {
17970
+ name: "app_reset_state",
17971
+ title: "Reset durable App state",
17972
+ description: "Permanently delete one durable App facet's isolated SQLite database as an explicit operation; deploying or rolling back never does this. Read app_get first, pass its expectedGeneration, and use a stable idempotencyKey so retries do not delete a later generation.",
17973
+ inputSchema: {
17974
+ appId: exports_external.string().describe("durable App, app_…"),
17975
+ expectedGeneration: exports_external.number().int().min(0).describe("state generation from app_get"),
17976
+ idempotencyKey: exports_external.string().min(1).max(200).describe("stable key for this one deliberate reset")
17977
+ },
17978
+ surfaces: ["cli"],
17979
+ toolset: "apps",
17980
+ run: forward("app.reset_state")
17981
+ },
17982
+ {
17983
+ name: "app_archive",
17984
+ title: "Archive an App",
17985
+ description: "Remove an App from active serving while retaining its stable identity, deployment timeline, receipts, and durable state for audit/recovery. Archive is lifecycle-only: it neither resets state nor deletes release history.",
17986
+ inputSchema: { appId: exports_external.string().describe("target App, app_…") },
17987
+ surfaces: ["cli"],
17988
+ toolset: "apps",
17989
+ run: forward("app.archive")
17990
+ },
17701
17991
  {
17702
17992
  name: "charter",
17703
17993
  title: "Set the guidance surfaces",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.12.8",
3
+ "version": "0.13.0",
4
4
  "description": "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
5
5
  "keywords": [
6
6
  "agents",