@geminixiang/mikan 1.0.0-beta.62 → 1.0.0-beta.64

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 (56) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +13 -13
  3. package/dist/adapters/commands/sandbox.d.ts.map +1 -1
  4. package/dist/adapters/commands/sandbox.js +30 -53
  5. package/dist/adapters/commands/sandbox.js.map +1 -1
  6. package/dist/adapters/commands/types.d.ts +3 -3
  7. package/dist/adapters/commands/types.d.ts.map +1 -1
  8. package/dist/adapters/commands/types.js.map +1 -1
  9. package/dist/adapters/slack/bot.d.ts +8 -0
  10. package/dist/adapters/slack/bot.d.ts.map +1 -1
  11. package/dist/adapters/slack/bot.js +32 -2
  12. package/dist/adapters/slack/bot.js.map +1 -1
  13. package/dist/adapters/web/admin/portal.d.ts.map +1 -1
  14. package/dist/adapters/web/admin/portal.js +26 -121
  15. package/dist/adapters/web/admin/portal.js.map +1 -1
  16. package/dist/cli/boot.js +1 -1
  17. package/dist/cli/boot.js.map +1 -1
  18. package/dist/cli/office.d.ts.map +1 -1
  19. package/dist/cli/office.js +33 -1
  20. package/dist/cli/office.js.map +1 -1
  21. package/dist/config.d.ts +26 -11
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +103 -61
  24. package/dist/config.js.map +1 -1
  25. package/dist/harness/execution-resolver.d.ts.map +1 -1
  26. package/dist/harness/execution-resolver.js +1 -1
  27. package/dist/harness/execution-resolver.js.map +1 -1
  28. package/dist/harness/prompt.d.ts.map +1 -1
  29. package/dist/harness/prompt.js +17 -21
  30. package/dist/harness/prompt.js.map +1 -1
  31. package/dist/harness/runner.d.ts.map +1 -1
  32. package/dist/harness/runner.js +2 -2
  33. package/dist/harness/runner.js.map +1 -1
  34. package/dist/office/projection.d.ts +19 -2
  35. package/dist/office/projection.d.ts.map +1 -1
  36. package/dist/office/projection.js +67 -99
  37. package/dist/office/projection.js.map +1 -1
  38. package/dist/office/types.d.ts +7 -8
  39. package/dist/office/types.d.ts.map +1 -1
  40. package/dist/office/types.js.map +1 -1
  41. package/dist/sandbox/index.d.ts +9 -1
  42. package/dist/sandbox/index.d.ts.map +1 -1
  43. package/dist/sandbox/index.js +16 -12
  44. package/dist/sandbox/index.js.map +1 -1
  45. package/dist/sandbox/provisioner.d.ts +8 -0
  46. package/dist/sandbox/provisioner.d.ts.map +1 -1
  47. package/dist/sandbox/provisioner.js +36 -0
  48. package/dist/sandbox/provisioner.js.map +1 -1
  49. package/dist/settings-mutation.d.ts +5 -29
  50. package/dist/settings-mutation.d.ts.map +1 -1
  51. package/dist/settings-mutation.js +7 -13
  52. package/dist/settings-mutation.js.map +1 -1
  53. package/dist/types.d.ts +2 -32
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js.map +1 -1
  56. package/package.json +1 -1
package/dist/cli/boot.js CHANGED
@@ -78,7 +78,7 @@ export function helpText() {
78
78
  return (bootCommand().helpInformation() +
79
79
  `
80
80
  Commands:
81
- mikan office <list|claim|migrate-openconnector|migrate-events> Inspect offices, claim legacy directories, migrate legacy state.
81
+ mikan office <list|claim|migrate-openconnector|migrate-events|migrate-door-policy> Inspect offices, claim legacy directories, migrate legacy state.
82
82
  mikan sessions migrate Migrate legacy sessions (stop the daemon first).
83
83
  mikan env Show environment-variable inventory.
84
84
  mikan onboard Interactive first-run setup.
@@ -1 +1 @@
1
- {"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Boot resolution for the `mikan` binary: argv → a BootPlan saying which mode\n * to run and with what configuration. Pure — no side effects, no exits — so\n * the grammar that actually drives the daemon is testable without spawning a\n * process; main.ts just executes the plan.\n *\n * Modes, highest priority first: `office`, `sessions`, `env` (own grammars, never\n * flag-parsed here), `help`, `version`, `onboard`, `download`, `run`.\n */\nimport { join, resolve } from \"node:path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg } from \"../sandbox/index.js\";\nimport type { BootPlan } from \"./types.js\";\nimport { cliCommand, defaultStateDir, nonEmptyValue, resolveStateDir } from \"./arg-grammar.js\";\n\nexport type { BootPlan } from \"./types.js\";\n\nconst SUBCOMMANDS = [\"office\", \"sessions\", \"env\"] as const;\n\ninterface BootOptions {\n stateDir?: string;\n sandbox?: string;\n download?: string;\n help?: boolean;\n version?: boolean;\n onboard?: boolean;\n}\n\nfunction bootCommand() {\n return cliCommand(\"mikan\")\n .description(\"Multi-platform chat agent daemon\")\n .helpOption(false)\n .argument(\"[working-directory...]\", \"Workspace directory (default: <state-dir>/workspace)\")\n .option(\"--state-dir <dir>\", \"State directory (default: ~/.mikan)\", nonEmptyValue)\n .option(\n \"--sandbox <spec>\",\n \"host | container:<name> | image:<image[:tag]> | cloudflare:<id>\",\n nonEmptyValue,\n )\n .option(\"--download <channel>\", \"Dump a Slack channel's history, then exit\", nonEmptyValue)\n .option(\"--onboard\", \"Interactive first-run setup (also: mikan onboard)\")\n .option(\"-v, --version\", \"Print version\")\n .option(\"-V\", \"Print version\")\n .option(\"-h, --help\", \"Show help\");\n}\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n const routed = subcommandPlan(args);\n if (routed) return routed;\n\n const command = bootCommand();\n command.parse(args, { from: \"user\" });\n const options = command.opts<BootOptions & { V?: boolean }>();\n // `onboard` counts as a subcommand only in first position; anywhere else it\n // is an ordinary working-directory positional.\n const onboardFirst = args[0] === \"onboard\";\n const workingDirArg = (onboardFirst ? command.args.slice(1) : command.args).at(-1);\n const downloadChannel = options.download;\n const sandboxArg = options.sandbox;\n const stateDir = resolveStateDir(args);\n return {\n mode: bootMode({ ...options, version: options.version || options.V }, onboardFirst),\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox: sandboxArg === undefined ? { type: \"host\" } : parseSandboxArg(sandboxArg),\n downloadChannel,\n };\n}\n\nfunction subcommandPlan(args: string[]): BootPlan | undefined {\n const mode = SUBCOMMANDS.find((name) => name === args[0]);\n if (!mode) return undefined;\n const stateDir = defaultStateDir();\n return {\n mode,\n ...(mode === \"office\" ? { officeArgs: args.slice(1) } : {}),\n ...(mode === \"sessions\" ? { sessionsArgs: args.slice(1) } : {}),\n stateDir,\n workingDir: join(stateDir, \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n}\n\nfunction bootMode(options: BootOptions, onboardFirst: boolean): BootPlan[\"mode\"] {\n if (options.help) return \"help\";\n if (options.version) return \"version\";\n if (onboardFirst || options.onboard) return \"onboard\";\n if (options.download) return \"download\";\n return \"run\";\n}\n\nexport function helpText(): string {\n return (\n bootCommand().helpInformation() +\n `\nCommands:\n mikan office <list|claim|migrate-openconnector|migrate-events> Inspect offices, claim legacy directories, migrate legacy state.\n mikan sessions migrate Migrate legacy sessions (stop the daemon first).\n mikan env Show environment-variable inventory.\n mikan onboard Interactive first-run setup.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun mikan env for the full inventory.`\n );\n}\n"]}
1
+ {"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Boot resolution for the `mikan` binary: argv → a BootPlan saying which mode\n * to run and with what configuration. Pure — no side effects, no exits — so\n * the grammar that actually drives the daemon is testable without spawning a\n * process; main.ts just executes the plan.\n *\n * Modes, highest priority first: `office`, `sessions`, `env` (own grammars, never\n * flag-parsed here), `help`, `version`, `onboard`, `download`, `run`.\n */\nimport { join, resolve } from \"node:path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg } from \"../sandbox/index.js\";\nimport type { BootPlan } from \"./types.js\";\nimport { cliCommand, defaultStateDir, nonEmptyValue, resolveStateDir } from \"./arg-grammar.js\";\n\nexport type { BootPlan } from \"./types.js\";\n\nconst SUBCOMMANDS = [\"office\", \"sessions\", \"env\"] as const;\n\ninterface BootOptions {\n stateDir?: string;\n sandbox?: string;\n download?: string;\n help?: boolean;\n version?: boolean;\n onboard?: boolean;\n}\n\nfunction bootCommand() {\n return cliCommand(\"mikan\")\n .description(\"Multi-platform chat agent daemon\")\n .helpOption(false)\n .argument(\"[working-directory...]\", \"Workspace directory (default: <state-dir>/workspace)\")\n .option(\"--state-dir <dir>\", \"State directory (default: ~/.mikan)\", nonEmptyValue)\n .option(\n \"--sandbox <spec>\",\n \"host | container:<name> | image:<image[:tag]> | cloudflare:<id>\",\n nonEmptyValue,\n )\n .option(\"--download <channel>\", \"Dump a Slack channel's history, then exit\", nonEmptyValue)\n .option(\"--onboard\", \"Interactive first-run setup (also: mikan onboard)\")\n .option(\"-v, --version\", \"Print version\")\n .option(\"-V\", \"Print version\")\n .option(\"-h, --help\", \"Show help\");\n}\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n const routed = subcommandPlan(args);\n if (routed) return routed;\n\n const command = bootCommand();\n command.parse(args, { from: \"user\" });\n const options = command.opts<BootOptions & { V?: boolean }>();\n // `onboard` counts as a subcommand only in first position; anywhere else it\n // is an ordinary working-directory positional.\n const onboardFirst = args[0] === \"onboard\";\n const workingDirArg = (onboardFirst ? command.args.slice(1) : command.args).at(-1);\n const downloadChannel = options.download;\n const sandboxArg = options.sandbox;\n const stateDir = resolveStateDir(args);\n return {\n mode: bootMode({ ...options, version: options.version || options.V }, onboardFirst),\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox: sandboxArg === undefined ? { type: \"host\" } : parseSandboxArg(sandboxArg),\n downloadChannel,\n };\n}\n\nfunction subcommandPlan(args: string[]): BootPlan | undefined {\n const mode = SUBCOMMANDS.find((name) => name === args[0]);\n if (!mode) return undefined;\n const stateDir = defaultStateDir();\n return {\n mode,\n ...(mode === \"office\" ? { officeArgs: args.slice(1) } : {}),\n ...(mode === \"sessions\" ? { sessionsArgs: args.slice(1) } : {}),\n stateDir,\n workingDir: join(stateDir, \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n}\n\nfunction bootMode(options: BootOptions, onboardFirst: boolean): BootPlan[\"mode\"] {\n if (options.help) return \"help\";\n if (options.version) return \"version\";\n if (onboardFirst || options.onboard) return \"onboard\";\n if (options.download) return \"download\";\n return \"run\";\n}\n\nexport function helpText(): string {\n return (\n bootCommand().helpInformation() +\n `\nCommands:\n mikan office <list|claim|migrate-openconnector|migrate-events|migrate-door-policy> Inspect offices, claim legacy directories, migrate legacy state.\n mikan sessions migrate Migrate legacy sessions (stop the daemon first).\n mikan env Show environment-variable inventory.\n mikan onboard Interactive first-run setup.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun mikan env for the full inventory.`\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"AA+BA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAqDvD"}
1
+ {"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"AAuCA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAgEvD"}
@@ -5,6 +5,13 @@
5
5
  * mikan office claim <conversationId> <platform> [--state-dir <dir>] [--workspace <dir>]
6
6
  * mikan office migrate-openconnector [--state-dir <dir>] [--workspace <dir>]
7
7
  * mikan office migrate-events [--state-dir <dir>] [--workspace <dir>]
8
+ * mikan office migrate-door-policy [--state-dir <dir>] [--workspace <dir>]
9
+ *
10
+ * `migrate-door-policy` removes the retired `sandbox.image.workspaceMount` and
11
+ * `sandbox.workspace` keys from the global and every office settings file
12
+ * (ADR 0008). Only an explicit shared-support `private` visibility is carried
13
+ * into `office.visibility`; nothing else is derived. Run it with the daemon
14
+ * stopped.
8
15
  *
9
16
  * `migrate-events` moves legacy `<workspace>/events/*.json` records into the
10
17
  * owning office's host-only state (`conversations/<key>/events/`). Records
@@ -24,9 +31,10 @@
24
31
  import { join, resolve } from "node:path";
25
32
  import { assertPlatformName, OfficeRegistry } from "../office/index.js";
26
33
  import { cliCommand, commandExitCode, nonEmptyValue, resolveStateDir } from "./arg-grammar.js";
27
- import { readEnv } from "../env-manifest.js";
34
+ import { readEnv, setEnvAliases } from "../env-manifest.js";
28
35
  import { migrateLegacyOpenConnectorTokens } from "../harness/open-connector.js";
29
36
  import { migrateLegacyWorkspaceEvents } from "../events/index.js";
37
+ import { migrateLegacyDoorPolicy } from "../config.js";
30
38
  import { createWorkspace } from "../office/index.js";
31
39
  export function runOfficeCommand(argv) {
32
40
  const command = cliCommand("mikan office")
@@ -67,6 +75,14 @@ export function runOfficeCommand(argv) {
67
75
  const { workspace } = command.opts();
68
76
  result = migrateEvents(stateDir, workspace ? resolve(workspace) : join(stateDir, "workspace"));
69
77
  });
78
+ command
79
+ .command("migrate-door-policy")
80
+ .description("Remove retired door-policy settings (stop the daemon first)")
81
+ .action(() => {
82
+ const stateDir = resolveStateDir(argv);
83
+ const { workspace } = command.opts();
84
+ result = migrateDoorPolicy(stateDir, workspace ? resolve(workspace) : join(stateDir, "workspace"));
85
+ });
70
86
  try {
71
87
  command.parse(argv, { from: "user" });
72
88
  return result;
@@ -92,6 +108,22 @@ function listOffices(stateDir) {
92
108
  }
93
109
  return 0;
94
110
  }
111
+ function migrateDoorPolicy(stateDir, workspaceRoot) {
112
+ // Settings readers resolve the global file from the process state dir.
113
+ setEnvAliases("STATE_DIR", stateDir);
114
+ const report = migrateLegacyDoorPolicy(createWorkspace({ root: workspaceRoot, stateDir }));
115
+ console.log(report.global.length > 0
116
+ ? `Global settings: removed ${report.global.join(", ")}`
117
+ : "Global settings: nothing to remove");
118
+ console.log(`Offices changed: ${report.conversations.length}`);
119
+ for (const entry of report.conversations) {
120
+ const carried = entry.visibility ? ` (kept as office.visibility=${entry.visibility})` : "";
121
+ console.log(` ${entry.key}: removed ${entry.removed.join(", ")}${carried}`);
122
+ }
123
+ for (const entry of report.skipped)
124
+ console.log(` skipped ${entry.key}: ${entry.reason}`);
125
+ return report.skipped.length > 0 ? 1 : 0;
126
+ }
95
127
  function migrateEvents(stateDir, workspaceRoot) {
96
128
  try {
97
129
  const report = migrateLegacyWorkspaceEvents(createWorkspace({ root: workspaceRoot, stateDir }));
@@ -1 +1 @@
1
- {"version":3,"file":"office.js","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `mikan office` — inspect and claim conversation offices from the CLI.\n *\n * mikan office list [--state-dir <dir>] [--workspace <dir>]\n * mikan office claim <conversationId> <platform> [--state-dir <dir>] [--workspace <dir>]\n * mikan office migrate-openconnector [--state-dir <dir>] [--workspace <dir>]\n * mikan office migrate-events [--state-dir <dir>] [--workspace <dir>]\n *\n * `migrate-events` moves legacy `<workspace>/events/*.json` records into the\n * owning office's host-only state (`conversations/<key>/events/`). Records\n * without an attributable, registered owner stay put and are reported. Run it\n * with the daemon stopped.\n *\n * `migrate-openconnector` converts legacy per-office\n * `open-connector-runtime-token.json` files into ordinary conversation\n * `mcpServers` entries for the current `OPENCONNECTOR_ENDPOINT`. Run it with\n * the daemon stopped.\n *\n * `claim` records which platform owns a legacy raw-id conversation directory\n * when several platforms are enabled and boot cannot infer ownership. The\n * daemon performs the actual move on its next start. Run it with the daemon\n * stopped so the directory is not moving under a live runtime.\n */\nimport { join, resolve } from \"node:path\";\nimport { assertPlatformName, OfficeRegistry } from \"../office/index.js\";\nimport { cliCommand, commandExitCode, nonEmptyValue, resolveStateDir } from \"./arg-grammar.js\";\nimport { readEnv } from \"../env-manifest.js\";\nimport { migrateLegacyOpenConnectorTokens } from \"../harness/open-connector.js\";\nimport { migrateLegacyWorkspaceEvents } from \"../events/index.js\";\nimport { createWorkspace } from \"../office/index.js\";\n\nexport function runOfficeCommand(argv: string[]): number {\n const command = cliCommand(\"mikan office\")\n .description(\"Inspect conversation offices and claim legacy directories\")\n .option(\"--state-dir <dir>\", \"State directory\", nonEmptyValue)\n .option(\"--workspace <dir>\", \"Workspace directory\", nonEmptyValue);\n let result = 1;\n command\n .command(\"list\")\n .description(\"List registered offices\")\n .action(() => {\n result = listOffices(resolveStateDir(argv));\n });\n command\n .command(\"claim <conversationId> <platform>\")\n .description(\"Claim a legacy directory (stop the daemon first)\")\n .action((conversationId: string, platform: string) => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = claimOffice(stateDir, workspace ? resolve(workspace) : join(stateDir, \"workspace\"), [\n conversationId,\n platform,\n ]);\n });\n command\n .command(\"migrate-openconnector\")\n .description(\n \"Convert legacy OpenConnector token files into MCP settings (stop the daemon first)\",\n )\n .action(() => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = migrateOpenConnector(\n stateDir,\n workspace ? resolve(workspace) : join(stateDir, \"workspace\"),\n );\n });\n command\n .command(\"migrate-events\")\n .description(\"Move legacy workspace event files into office state (stop the daemon first)\")\n .action(() => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = migrateEvents(\n stateDir,\n workspace ? resolve(workspace) : join(stateDir, \"workspace\"),\n );\n });\n try {\n command.parse(argv, { from: \"user\" });\n return result;\n } catch (error) {\n return commandExitCode(error, command);\n }\n}\n\nfunction listOffices(stateDir: string): number {\n const state = new OfficeRegistry(stateDir).getState();\n console.log(`Enabled platforms: ${state.enabledPlatforms.join(\", \") || \"(none)\"}`);\n console.log(`Offices (${state.offices.length}):`);\n for (const office of state.offices) {\n console.log(` ${office.platform} ${office.conversationId}`);\n }\n const pending = state.migrations.filter((record) => record.status !== \"committed\");\n if (pending.length > 0) {\n console.log(`Pending migrations (${pending.length}):`);\n for (const record of pending) {\n const error = record.error ? ` (${record.error})` : \"\";\n console.log(` ${record.status} ${record.rawConversationId}${error}`);\n }\n }\n return 0;\n}\n\nfunction migrateEvents(stateDir: string, workspaceRoot: string): number {\n try {\n const report = migrateLegacyWorkspaceEvents(createWorkspace({ root: workspaceRoot, stateDir }));\n console.log(`Migrated ${report.migrated.length} event file(s) into office state.`);\n for (const entry of report.migrated) console.log(` ${entry.filename} -> ${entry.key}`);\n for (const entry of report.skipped) console.log(` skipped ${entry.filename}: ${entry.reason}`);\n return 0;\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\nfunction migrateOpenConnector(stateDir: string, workspaceRoot: string): number {\n const endpoint = readEnv(\"OPENCONNECTOR_ENDPOINT\");\n if (!endpoint) {\n console.error(\"OPENCONNECTOR_ENDPOINT is not set; nothing to migrate to.\");\n return 1;\n }\n try {\n const report = migrateLegacyOpenConnectorTokens(stateDir, endpoint, workspaceRoot);\n console.log(`Migrated ${report.migrated.length} office token file(s) into settings.json.`);\n for (const entry of report.skipped) {\n console.log(` skipped ${entry.key}: ${entry.reason}`);\n }\n return 0;\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\nfunction claimOffice(stateDir: string, workspaceRoot: string, rest: string[]): number {\n const [rawConversationId, platform] = rest;\n if (!rawConversationId || !platform) return 1;\n try {\n const record = new OfficeRegistry(stateDir).prepareLegacyMigration({\n rawConversationId,\n sourceDir: join(workspaceRoot, rawConversationId),\n workspaceRoot,\n ownerPlatform: assertPlatformName(platform),\n });\n console.log(\n `Claimed ${record.rawConversationId} for ${record.ownerPlatform}; ` +\n \"the daemon migrates the directory on its next start.\",\n );\n return 0;\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n"]}
1
+ {"version":3,"file":"office.js","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `mikan office` — inspect and claim conversation offices from the CLI.\n *\n * mikan office list [--state-dir <dir>] [--workspace <dir>]\n * mikan office claim <conversationId> <platform> [--state-dir <dir>] [--workspace <dir>]\n * mikan office migrate-openconnector [--state-dir <dir>] [--workspace <dir>]\n * mikan office migrate-events [--state-dir <dir>] [--workspace <dir>]\n * mikan office migrate-door-policy [--state-dir <dir>] [--workspace <dir>]\n *\n * `migrate-door-policy` removes the retired `sandbox.image.workspaceMount` and\n * `sandbox.workspace` keys from the global and every office settings file\n * (ADR 0008). Only an explicit shared-support `private` visibility is carried\n * into `office.visibility`; nothing else is derived. Run it with the daemon\n * stopped.\n *\n * `migrate-events` moves legacy `<workspace>/events/*.json` records into the\n * owning office's host-only state (`conversations/<key>/events/`). Records\n * without an attributable, registered owner stay put and are reported. Run it\n * with the daemon stopped.\n *\n * `migrate-openconnector` converts legacy per-office\n * `open-connector-runtime-token.json` files into ordinary conversation\n * `mcpServers` entries for the current `OPENCONNECTOR_ENDPOINT`. Run it with\n * the daemon stopped.\n *\n * `claim` records which platform owns a legacy raw-id conversation directory\n * when several platforms are enabled and boot cannot infer ownership. The\n * daemon performs the actual move on its next start. Run it with the daemon\n * stopped so the directory is not moving under a live runtime.\n */\nimport { join, resolve } from \"node:path\";\nimport { assertPlatformName, OfficeRegistry } from \"../office/index.js\";\nimport { cliCommand, commandExitCode, nonEmptyValue, resolveStateDir } from \"./arg-grammar.js\";\nimport { readEnv, setEnvAliases } from \"../env-manifest.js\";\nimport { migrateLegacyOpenConnectorTokens } from \"../harness/open-connector.js\";\nimport { migrateLegacyWorkspaceEvents } from \"../events/index.js\";\nimport { migrateLegacyDoorPolicy } from \"../config.js\";\nimport { createWorkspace } from \"../office/index.js\";\n\nexport function runOfficeCommand(argv: string[]): number {\n const command = cliCommand(\"mikan office\")\n .description(\"Inspect conversation offices and claim legacy directories\")\n .option(\"--state-dir <dir>\", \"State directory\", nonEmptyValue)\n .option(\"--workspace <dir>\", \"Workspace directory\", nonEmptyValue);\n let result = 1;\n command\n .command(\"list\")\n .description(\"List registered offices\")\n .action(() => {\n result = listOffices(resolveStateDir(argv));\n });\n command\n .command(\"claim <conversationId> <platform>\")\n .description(\"Claim a legacy directory (stop the daemon first)\")\n .action((conversationId: string, platform: string) => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = claimOffice(stateDir, workspace ? resolve(workspace) : join(stateDir, \"workspace\"), [\n conversationId,\n platform,\n ]);\n });\n command\n .command(\"migrate-openconnector\")\n .description(\n \"Convert legacy OpenConnector token files into MCP settings (stop the daemon first)\",\n )\n .action(() => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = migrateOpenConnector(\n stateDir,\n workspace ? resolve(workspace) : join(stateDir, \"workspace\"),\n );\n });\n command\n .command(\"migrate-events\")\n .description(\"Move legacy workspace event files into office state (stop the daemon first)\")\n .action(() => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = migrateEvents(\n stateDir,\n workspace ? resolve(workspace) : join(stateDir, \"workspace\"),\n );\n });\n command\n .command(\"migrate-door-policy\")\n .description(\"Remove retired door-policy settings (stop the daemon first)\")\n .action(() => {\n const stateDir = resolveStateDir(argv);\n const { workspace } = command.opts<{ workspace?: string }>();\n result = migrateDoorPolicy(\n stateDir,\n workspace ? resolve(workspace) : join(stateDir, \"workspace\"),\n );\n });\n try {\n command.parse(argv, { from: \"user\" });\n return result;\n } catch (error) {\n return commandExitCode(error, command);\n }\n}\n\nfunction listOffices(stateDir: string): number {\n const state = new OfficeRegistry(stateDir).getState();\n console.log(`Enabled platforms: ${state.enabledPlatforms.join(\", \") || \"(none)\"}`);\n console.log(`Offices (${state.offices.length}):`);\n for (const office of state.offices) {\n console.log(` ${office.platform} ${office.conversationId}`);\n }\n const pending = state.migrations.filter((record) => record.status !== \"committed\");\n if (pending.length > 0) {\n console.log(`Pending migrations (${pending.length}):`);\n for (const record of pending) {\n const error = record.error ? ` (${record.error})` : \"\";\n console.log(` ${record.status} ${record.rawConversationId}${error}`);\n }\n }\n return 0;\n}\n\nfunction migrateDoorPolicy(stateDir: string, workspaceRoot: string): number {\n // Settings readers resolve the global file from the process state dir.\n setEnvAliases(\"STATE_DIR\", stateDir);\n const report = migrateLegacyDoorPolicy(createWorkspace({ root: workspaceRoot, stateDir }));\n console.log(\n report.global.length > 0\n ? `Global settings: removed ${report.global.join(\", \")}`\n : \"Global settings: nothing to remove\",\n );\n console.log(`Offices changed: ${report.conversations.length}`);\n for (const entry of report.conversations) {\n const carried = entry.visibility ? ` (kept as office.visibility=${entry.visibility})` : \"\";\n console.log(` ${entry.key}: removed ${entry.removed.join(\", \")}${carried}`);\n }\n for (const entry of report.skipped) console.log(` skipped ${entry.key}: ${entry.reason}`);\n return report.skipped.length > 0 ? 1 : 0;\n}\n\nfunction migrateEvents(stateDir: string, workspaceRoot: string): number {\n try {\n const report = migrateLegacyWorkspaceEvents(createWorkspace({ root: workspaceRoot, stateDir }));\n console.log(`Migrated ${report.migrated.length} event file(s) into office state.`);\n for (const entry of report.migrated) console.log(` ${entry.filename} -> ${entry.key}`);\n for (const entry of report.skipped) console.log(` skipped ${entry.filename}: ${entry.reason}`);\n return 0;\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\nfunction migrateOpenConnector(stateDir: string, workspaceRoot: string): number {\n const endpoint = readEnv(\"OPENCONNECTOR_ENDPOINT\");\n if (!endpoint) {\n console.error(\"OPENCONNECTOR_ENDPOINT is not set; nothing to migrate to.\");\n return 1;\n }\n try {\n const report = migrateLegacyOpenConnectorTokens(stateDir, endpoint, workspaceRoot);\n console.log(`Migrated ${report.migrated.length} office token file(s) into settings.json.`);\n for (const entry of report.skipped) {\n console.log(` skipped ${entry.key}: ${entry.reason}`);\n }\n return 0;\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\nfunction claimOffice(stateDir: string, workspaceRoot: string, rest: string[]): number {\n const [rawConversationId, platform] = rest;\n if (!rawConversationId || !platform) return 1;\n try {\n const record = new OfficeRegistry(stateDir).prepareLegacyMigration({\n rawConversationId,\n sourceDir: join(workspaceRoot, rawConversationId),\n workspaceRoot,\n ownerPlatform: assertPlatformName(platform),\n });\n console.log(\n `Claimed ${record.rawConversationId} for ${record.ownerPlatform}; ` +\n \"the daemon migrates the directory on its next start.\",\n );\n return 0;\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n"]}
package/dist/config.d.ts CHANGED
@@ -2,11 +2,11 @@ export declare class MissingGlobalSettingsError extends Error {
2
2
  readonly settingsPath: string;
3
3
  constructor(settingsPath: string);
4
4
  }
5
- export type { AgentConfig, SandboxSettings, WorkspacePolicyChoice } from "./types.js";
6
- import type { AgentConfig, WorkspacePolicyChoice } from "./types.js";
5
+ export type { AgentConfig, SandboxSettings } from "./types.js";
6
+ import type { AgentConfig, OfficeKey } from "./types.js";
7
7
  import type { McpServerConfig } from "./harness/types.js";
8
8
  import type { OnboardLlmChoice } from "./types.js";
9
- import type { Office } from "./office/index.js";
9
+ import { type Office, type Workspace } from "./office/index.js";
10
10
  export declare function loadGlobalSettings(): AgentConfig;
11
11
  /**
12
12
  * Host-authoritative location of a conversation's settings file:
@@ -65,13 +65,28 @@ export declare function loadScopeMcpServers(office: Office): {
65
65
  conversation: Record<string, McpServerConfig>;
66
66
  };
67
67
  /**
68
- * The conversation's own door-policy override (legacy `image.workspaceMount`
69
- * included), or null when the office follows the global default. Missing
70
- * `visibility` on a shared-support choice defaults to "public" downstream
71
- * (see resolveEffectiveWorkspace), preserving today's read-write behavior for
72
- * every office that predates this setting.
68
+ * The conversation's own visibility override, or null when it follows the
69
+ * platform. Only "private" can be stored: an operator may narrow a public
70
+ * channel, never widen a private one (see ADR 0008).
73
71
  */
74
- export declare function loadConversationWorkspaceOverride(office: Office): WorkspacePolicyChoice | null;
75
- export declare function setConversationWorkspacePolicy(office: Office, choice: WorkspacePolicyChoice | null): void;
76
- export declare function setGlobalWorkspacePolicy(choice: WorkspacePolicyChoice | null): void;
72
+ export declare function loadOfficeVisibilityOverride(office: Office): "private" | null;
73
+ export declare function setOfficeVisibilityOverride(office: Office, visibility: "private" | null): void;
74
+ export interface DoorPolicyMigrationReport {
75
+ /** Retired keys removed from the global settings file. */
76
+ global: string[];
77
+ conversations: {
78
+ key: OfficeKey;
79
+ removed: string[];
80
+ visibility?: "private";
81
+ }[];
82
+ skipped: {
83
+ key: OfficeKey | "global";
84
+ reason: string;
85
+ }[];
86
+ }
87
+ /**
88
+ * One-time removal of the retired door-policy settings from the global file
89
+ * and every registered office (ADR 0008). Run with the daemon stopped.
90
+ */
91
+ export declare function migrateLegacyDoorPolicy(workspace: Workspace): DoorPolicyMigrationReport;
77
92
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,qBAAa,0BAA2B,SAAQ,KAAK;aACvB,YAAY,EAAE,MAAM;IAAhD,YAA4B,YAAY,EAAE,MAAM,EAG/C;CACF;AAED,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,WAAW,EAAmB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAsOhD,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA6B/D;AAiBD,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAcpF;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAiBvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAInE;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,IAAI,CAWN;AAOD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAkBzF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AA6ED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAEtE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAE5F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IACnD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC/C,CAKA;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAiB9F;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC,IAAI,CAEN;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAEnF"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,qBAAa,0BAA2B,SAAQ,KAAK;aACvB,YAAY,EAAE,MAAM;IAAhD,YAA4B,YAAY,EAAE,MAAM,EAG/C;CACF;AAED,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAmB,MAAM,YAAY,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAyB,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAsOvF,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA6B/D;AAiBD,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAcpF;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAiBvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAInE;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,IAAI,CAWN;AAOD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAkBzF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AAiFD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAEtE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAE5F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IACnD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC/C,CAKA;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE7E;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAa9F;AAED,MAAM,WAAW,yBAAyB;IACxC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE;QAAE,GAAG,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;IAC/E,OAAO,EAAE;QAAE,GAAG,EAAE,SAAS,GAAG,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1D;AA8CD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,GAAG,yBAAyB,CA4BvF"}
package/dist/config.js CHANGED
@@ -13,6 +13,7 @@ export class MissingGlobalSettingsError extends Error {
13
13
  this.name = "MissingGlobalSettingsError";
14
14
  }
15
15
  }
16
+ import { listRegisteredOffices } from "./office/index.js";
16
17
  const ONBOARD_SETTINGS = {
17
18
  llm: {
18
19
  provider: "anthropic",
@@ -29,11 +30,8 @@ const ONBOARD_SETTINGS = {
29
30
  cpus: "2",
30
31
  memory: "4g",
31
32
  },
32
- // No pinned workspace door policy: with nothing set, the projection
33
- // follows the platform's own channel vocabulary (public channels share
34
- // workspace memory, private channels read it without writing, DMs stay
35
- // isolated — see workspace-projection platformDerivedWorkspace).
36
- // Deployments that predate this keep their explicit isolated setting.
33
+ // Office visibility is not a setting here: it follows the platform
34
+ // conversation type (see office/projection resolveOfficeVisibility).
37
35
  defaultSharedVault: "",
38
36
  },
39
37
  };
@@ -57,6 +55,14 @@ const SettingsFileSchema = Type.Object({
57
55
  slack: Type.Optional(Type.Object({
58
56
  replyMode: Type.Optional(Type.Union([Type.Literal("top-level"), Type.Literal("thread")])),
59
57
  })),
58
+ /**
59
+ * Conversation-only office policy. `visibility: "private"` marks a
60
+ * platform-public conversation as private; nothing can widen visibility
61
+ * beyond what the platform grants, so "public" is never stored here.
62
+ */
63
+ office: Type.Optional(Type.Object({
64
+ visibility: Type.Optional(Type.Literal("private")),
65
+ })),
60
66
  sandbox: Type.Optional(Type.Object({
61
67
  cpus: Type.Optional(Type.String()),
62
68
  memory: Type.Optional(Type.String()),
@@ -64,6 +70,11 @@ const SettingsFileSchema = Type.Object({
64
70
  cpus: Type.Optional(Type.String()),
65
71
  memory: Type.Optional(Type.String()),
66
72
  })),
73
+ /**
74
+ * Retired door-policy keys (ADR 0008). Still accepted so existing files
75
+ * load, never copied into AgentConfig, and removed by
76
+ * `mikan office migrate-door-policy`.
77
+ */
67
78
  image: Type.Optional(Type.Object({
68
79
  workspaceMount: Type.Optional(Type.Union([Type.Literal("private"), Type.Literal("full")])),
69
80
  })),
@@ -117,20 +128,12 @@ function normalizeSettingsConfig(config) {
117
128
  */
118
129
  function normalizeSandboxSettings(sandbox) {
119
130
  const defaultSharedVault = sandbox.defaultSharedVault?.trim();
120
- const legacyWorkspace = sandbox.image?.workspaceMount === "private"
121
- ? { doorPolicy: "trusted", layout: "shared-support" }
122
- : sandbox.image?.workspaceMount === "full"
123
- ? { doorPolicy: "trusted", layout: "full" }
124
- : undefined;
125
- const workspace = legacyWorkspace
126
- ? { ...legacyWorkspace, ...sandbox.workspace }
127
- : sandbox.workspace;
131
+ // Retired `image.workspaceMount` and `workspace` are dropped here: office
132
+ // visibility comes from the platform (ADR 0008), never from these keys.
128
133
  return {
129
134
  ...(sandbox.cpus !== undefined ? { cpus: sandbox.cpus } : {}),
130
135
  ...(sandbox.memory !== undefined ? { memory: sandbox.memory } : {}),
131
136
  ...(sandbox.boost !== undefined ? { boost: sandbox.boost } : {}),
132
- ...(sandbox.image !== undefined ? { image: sandbox.image } : {}),
133
- ...(workspace !== undefined ? { workspace } : {}),
134
137
  ...(defaultSharedVault ? { defaultSharedVault } : {}),
135
138
  };
136
139
  }
@@ -150,10 +153,6 @@ function mergeSandboxSettings(base, override) {
150
153
  ...base,
151
154
  ...override,
152
155
  ...(base.boost || override.boost ? { boost: { ...base.boost, ...override.boost } } : {}),
153
- ...(base.image || override.image ? { image: { ...base.image, ...override.image } } : {}),
154
- ...(base.workspace || override.workspace
155
- ? { workspace: { ...base.workspace, ...override.workspace } }
156
- : {}),
157
156
  };
158
157
  }
159
158
  function getSettingsPath() {
@@ -369,6 +368,7 @@ function compactSettingsConfig(config) {
369
368
  ...(hasDefinedValue(config.sentry) ? { sentry: config.sentry } : {}),
370
369
  ...(hasDefinedValue(config.sandbox) ? { sandbox: config.sandbox } : {}),
371
370
  ...(hasDefinedValue(config.slack) ? { slack: config.slack } : {}),
371
+ ...(hasDefinedValue(config.office) ? { office: config.office } : {}),
372
372
  // An empty map means "all servers removed".
373
373
  ...(config.mcpServers !== undefined ? { mcpServers: config.mcpServers } : {}),
374
374
  };
@@ -394,6 +394,9 @@ function patchSettingsConfig(existing, config) {
394
394
  ...existing.slack,
395
395
  ...config.slack,
396
396
  },
397
+ // Office visibility has its own writer (setOfficeVisibilityOverride); the
398
+ // generic patch must not drop it.
399
+ ...(existing.office !== undefined ? { office: existing.office } : {}),
397
400
  // The portal edits the full MCP map, and
398
401
  // a merge would make removing a server impossible.
399
402
  ...(config.mcpServers !== undefined ? { mcpServers: config.mcpServers } : {}),
@@ -437,55 +440,94 @@ export function loadScopeMcpServers(office) {
437
440
  };
438
441
  }
439
442
  /**
440
- * The conversation's own door-policy override (legacy `image.workspaceMount`
441
- * included), or null when the office follows the global default. Missing
442
- * `visibility` on a shared-support choice defaults to "public" downstream
443
- * (see resolveEffectiveWorkspace), preserving today's read-write behavior for
444
- * every office that predates this setting.
443
+ * The conversation's own visibility override, or null when it follows the
444
+ * platform. Only "private" can be stored: an operator may narrow a public
445
+ * channel, never widen a private one (see ADR 0008).
445
446
  */
446
- export function loadConversationWorkspaceOverride(office) {
447
- const file = loadSettingsFile(conversationSettingsPath(office));
448
- const sandbox = file?.sandbox;
449
- if (sandbox?.workspace?.doorPolicy === "isolated")
450
- return { doorPolicy: "isolated" };
451
- if (sandbox?.workspace?.doorPolicy === "trusted") {
452
- if (sandbox.workspace.layout === "full")
453
- return { doorPolicy: "trusted", layout: "full" };
454
- return {
455
- doorPolicy: "trusted",
456
- layout: "shared-support",
457
- ...(sandbox.workspace.visibility ? { visibility: sandbox.workspace.visibility } : {}),
458
- };
459
- }
460
- if (sandbox?.image?.workspaceMount === "full")
461
- return { doorPolicy: "trusted", layout: "full" };
462
- if (sandbox?.image?.workspaceMount === "private") {
463
- return { doorPolicy: "trusted", layout: "shared-support" };
464
- }
465
- return null;
466
- }
467
- export function setConversationWorkspacePolicy(office, choice) {
468
- writeWorkspacePolicy(conversationSettingsPath(office), choice, {});
447
+ export function loadOfficeVisibilityOverride(office) {
448
+ return loadSettingsFile(conversationSettingsPath(office))?.office?.visibility ?? null;
469
449
  }
470
- export function setGlobalWorkspacePolicy(choice) {
471
- writeWorkspacePolicy(getSettingsPath(), choice, ONBOARD_SETTINGS);
450
+ export function setOfficeVisibilityOverride(office, visibility) {
451
+ const settingsPath = conversationSettingsPath(office);
452
+ const existing = loadSettingsFileForUpdate(settingsPath, {});
453
+ const { office: _previous, ...rest } = existing;
454
+ ensureDirExists(dirname(settingsPath));
455
+ atomicWritePrivateFile(settingsPath, JSON.stringify(compactSettingsConfig({ ...rest, ...(visibility ? { office: { visibility } } : {}) }), null, 2));
472
456
  }
457
+ const RETIRED_KEYS = {
458
+ image: "sandbox.image.workspaceMount",
459
+ workspace: "sandbox.workspace",
460
+ };
473
461
  /**
474
- * The generic settings patch merges leaves and cannot remove keys, so the
475
- * door-policy writer edits the file shape directly: it always drops the
476
- * legacy `image.workspaceMount` (the explicit choice replaces it) and either
477
- * sets or removes the `workspace` group.
462
+ * Strip the retired door-policy keys from one settings file. Returns the
463
+ * removed key paths, or an empty list when nothing had to change (the file is
464
+ * then left byte-for-byte alone, which also preserves `{}` migration markers).
465
+ * The only value carried forward is an explicit shared-support `private`
466
+ * visibility, which maps onto `office.visibility` (ADR 0008). Every other
467
+ * retired combination — `full`, `isolated`, legacy `private` — is dropped
468
+ * without deriving a grant.
478
469
  */
479
- function writeWorkspacePolicy(settingsPath, choice, defaultSettings) {
480
- const existing = loadSettingsFileForUpdate(settingsPath, defaultSettings);
481
- const { workspaceMount: _legacy, ...image } = existing.sandbox?.image ?? {};
482
- const { workspace: _previous, image: _image, ...sandboxRest } = existing.sandbox ?? {};
470
+ function stripRetiredDoorPolicy(settingsPath, allowVisibilityCarry) {
471
+ const existing = loadSettingsFile(settingsPath);
472
+ if (!existing?.sandbox)
473
+ return { removed: [] };
474
+ const { image, workspace, ...sandboxRest } = existing.sandbox;
475
+ const removed = [];
476
+ if (image?.workspaceMount !== undefined)
477
+ removed.push(RETIRED_KEYS.image);
478
+ if (workspace !== undefined)
479
+ removed.push(RETIRED_KEYS.workspace);
480
+ if (removed.length === 0)
481
+ return { removed };
482
+ const carry = allowVisibilityCarry &&
483
+ workspace?.doorPolicy === "trusted" &&
484
+ workspace.layout !== "full" &&
485
+ workspace.visibility === "private";
486
+ const { workspaceMount: _mount, ...imageRest } = image ?? {};
483
487
  const sandbox = {
484
488
  ...sandboxRest,
485
- ...(hasDefinedValue(image) ? { image } : {}),
486
- ...(choice ? { workspace: choice } : {}),
489
+ ...(hasDefinedValue(imageRest) ? { image: imageRest } : {}),
487
490
  };
488
- ensureDirExists(dirname(settingsPath));
489
- atomicWritePrivateFile(settingsPath, JSON.stringify(compactSettingsConfig({ ...existing, sandbox }), null, 2));
491
+ const next = {
492
+ ...existing,
493
+ sandbox,
494
+ ...(carry ? { office: { ...existing.office, visibility: "private" } } : {}),
495
+ };
496
+ atomicWritePrivateFile(settingsPath, JSON.stringify(compactSettingsConfig(next), null, 2));
497
+ return { removed, ...(carry ? { visibility: "private" } : {}) };
498
+ }
499
+ /**
500
+ * One-time removal of the retired door-policy settings from the global file
501
+ * and every registered office (ADR 0008). Run with the daemon stopped.
502
+ */
503
+ export function migrateLegacyDoorPolicy(workspace) {
504
+ const report = { global: [], conversations: [], skipped: [] };
505
+ try {
506
+ report.global = stripRetiredDoorPolicy(join(workspace.stateDir, "settings.json"), false).removed;
507
+ }
508
+ catch (error) {
509
+ report.skipped.push({
510
+ key: "global",
511
+ reason: error instanceof Error ? error.message : String(error),
512
+ });
513
+ }
514
+ for (const record of listRegisteredOffices(workspace.stateDir)) {
515
+ const office = workspace.office(record);
516
+ const settingsPath = join(office.stateDir, "settings.json");
517
+ if (!existsSync(settingsPath))
518
+ continue;
519
+ try {
520
+ const result = stripRetiredDoorPolicy(settingsPath, true);
521
+ if (result.removed.length > 0)
522
+ report.conversations.push({ key: office.key, ...result });
523
+ }
524
+ catch (error) {
525
+ report.skipped.push({
526
+ key: office.key,
527
+ reason: error instanceof Error ? error.message : String(error),
528
+ });
529
+ }
530
+ }
531
+ return report;
490
532
  }
491
533
  //# sourceMappingURL=config.js.map