@skrr-ai/cli 0.1.36 → 0.1.37

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 (152) hide show
  1. package/README.md +17 -4
  2. package/dist/commands/agents/actions/create.d.ts +5 -0
  3. package/dist/commands/agents/actions/create.js +26 -0
  4. package/dist/commands/agents/actions/update.d.ts +5 -0
  5. package/dist/commands/agents/actions/update.js +24 -0
  6. package/dist/commands/agents/api-actions/add.d.ts +41 -0
  7. package/dist/commands/agents/api-actions/add.js +202 -0
  8. package/dist/commands/agents/api-actions/index.d.ts +28 -0
  9. package/dist/commands/agents/api-actions/index.js +77 -0
  10. package/dist/commands/agents/api-actions/remove.d.ts +14 -0
  11. package/dist/commands/agents/api-actions/remove.js +36 -0
  12. package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
  13. package/dist/commands/agents/avatar/default/apply.js +56 -0
  14. package/dist/commands/agents/avatar/default/index.d.ts +18 -0
  15. package/dist/commands/agents/avatar/default/index.js +44 -0
  16. package/dist/commands/agents/avatar/default/set.d.ts +23 -0
  17. package/dist/commands/agents/avatar/default/set.js +95 -0
  18. package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
  19. package/dist/commands/agents/avatar/library/delete.js +47 -0
  20. package/dist/commands/agents/avatar/library/index.d.ts +16 -0
  21. package/dist/commands/agents/avatar/library/index.js +56 -0
  22. package/dist/commands/agents/avatar/presets.d.ts +19 -0
  23. package/dist/commands/agents/avatar/presets.js +56 -0
  24. package/dist/commands/agents/categories/create.d.ts +14 -0
  25. package/dist/commands/agents/categories/create.js +46 -0
  26. package/dist/commands/agents/categories/delete.d.ts +13 -0
  27. package/dist/commands/agents/categories/delete.js +33 -0
  28. package/dist/commands/agents/categories/index.d.ts +20 -0
  29. package/dist/commands/agents/categories/index.js +82 -0
  30. package/dist/commands/agents/categories/update.d.ts +22 -0
  31. package/dist/commands/agents/categories/update.js +59 -0
  32. package/dist/commands/agents/create.d.ts +10 -0
  33. package/dist/commands/agents/create.js +57 -3
  34. package/dist/commands/agents/ensure-default.d.ts +27 -0
  35. package/dist/commands/agents/ensure-default.js +65 -0
  36. package/dist/commands/agents/mute.d.ts +16 -0
  37. package/dist/commands/agents/mute.js +38 -0
  38. package/dist/commands/agents/pin.d.ts +16 -0
  39. package/dist/commands/agents/pin.js +38 -0
  40. package/dist/commands/agents/tools/auth.d.ts +19 -0
  41. package/dist/commands/agents/tools/auth.js +41 -0
  42. package/dist/commands/agents/tools/calls.d.ts +18 -0
  43. package/dist/commands/agents/tools/calls.js +54 -0
  44. package/dist/commands/agents/tools/index.d.ts +20 -0
  45. package/dist/commands/agents/tools/index.js +77 -0
  46. package/dist/commands/agents/unmute.d.ts +16 -0
  47. package/dist/commands/agents/unmute.js +38 -0
  48. package/dist/commands/agents/unpin.d.ts +16 -0
  49. package/dist/commands/agents/unpin.js +38 -0
  50. package/dist/commands/agents/update.d.ts +12 -0
  51. package/dist/commands/agents/update.js +64 -3
  52. package/dist/commands/followups/act.d.ts +22 -0
  53. package/dist/commands/followups/act.js +102 -0
  54. package/dist/commands/followups/cancel.d.ts +17 -0
  55. package/dist/commands/followups/cancel.js +40 -0
  56. package/dist/commands/followups/checkin.d.ts +27 -0
  57. package/dist/commands/followups/checkin.js +107 -0
  58. package/dist/commands/followups/list.d.ts +24 -0
  59. package/dist/commands/followups/list.js +90 -0
  60. package/dist/commands/followups/remind.d.ts +26 -0
  61. package/dist/commands/followups/remind.js +106 -0
  62. package/dist/commands/followups/reschedule.d.ts +15 -0
  63. package/dist/commands/followups/reschedule.js +48 -0
  64. package/dist/commands/followups/resolve.d.ts +23 -0
  65. package/dist/commands/followups/resolve.js +54 -0
  66. package/dist/commands/followups/show.d.ts +12 -0
  67. package/dist/commands/followups/show.js +45 -0
  68. package/dist/commands/followups/watch.d.ts +51 -0
  69. package/dist/commands/followups/watch.js +207 -0
  70. package/dist/commands/goals/labels/add.js +19 -2
  71. package/dist/commands/goals/labels/remove.js +22 -2
  72. package/dist/commands/labels/list.d.ts +24 -1
  73. package/dist/commands/labels/list.js +62 -19
  74. package/dist/commands/memory/governance/index.d.ts +21 -0
  75. package/dist/commands/memory/governance/index.js +64 -0
  76. package/dist/commands/memory/governance/set.d.ts +24 -0
  77. package/dist/commands/memory/governance/set.js +95 -0
  78. package/dist/commands/memory/provenance.d.ts +18 -0
  79. package/dist/commands/memory/provenance.js +66 -0
  80. package/dist/commands/spaces/create.d.ts +3 -0
  81. package/dist/commands/spaces/create.js +32 -2
  82. package/dist/commands/spaces/labels/add.js +19 -2
  83. package/dist/commands/spaces/labels/remove.js +22 -2
  84. package/dist/commands/spaces/show.js +2 -0
  85. package/dist/commands/spaces/update.d.ts +5 -0
  86. package/dist/commands/spaces/update.js +41 -4
  87. package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
  88. package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +45 -0
  89. package/dist/commands/tasks/complete.d.ts +1 -0
  90. package/dist/commands/tasks/complete.js +8 -1
  91. package/dist/commands/tasks/create.d.ts +3 -0
  92. package/dist/commands/tasks/create.js +34 -2
  93. package/dist/commands/tasks/expectations/assess.d.ts +11 -0
  94. package/dist/commands/tasks/expectations/assess.js +85 -14
  95. package/dist/commands/tasks/expectations.js +19 -2
  96. package/dist/commands/tasks/labels/attach.js +20 -3
  97. package/dist/commands/tasks/labels/detach.js +21 -3
  98. package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
  99. package/dist/commands/tasks/lifecycle/attach.js +47 -0
  100. package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
  101. package/dist/commands/tasks/lifecycle/definitions.js +40 -0
  102. package/dist/commands/tasks/lifecycle/detach.d.ts +12 -0
  103. package/dist/commands/tasks/lifecycle/detach.js +32 -0
  104. package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
  105. package/dist/commands/tasks/lifecycle/history.js +38 -0
  106. package/dist/commands/tasks/lifecycle/migrate.d.ts +12 -0
  107. package/dist/commands/tasks/lifecycle/migrate.js +29 -0
  108. package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
  109. package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
  110. package/dist/commands/tasks/lifecycle/reopen.d.ts +13 -0
  111. package/dist/commands/tasks/lifecycle/reopen.js +34 -0
  112. package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
  113. package/dist/commands/tasks/lifecycle/show.js +27 -0
  114. package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
  115. package/dist/commands/tasks/lifecycle/start.js +30 -0
  116. package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
  117. package/dist/commands/tasks/lifecycle/transition.js +78 -0
  118. package/dist/commands/tasks/move.d.ts +1 -0
  119. package/dist/commands/tasks/move.js +31 -0
  120. package/dist/commands/tasks/result/submit.js +11 -1
  121. package/dist/commands/tasks/review-queue.d.ts +29 -0
  122. package/dist/commands/tasks/review-queue.js +165 -0
  123. package/dist/commands/tasks/show.js +42 -0
  124. package/dist/commands/tasks/update.d.ts +1 -0
  125. package/dist/commands/tasks/update.js +47 -0
  126. package/dist/lib/agent-actions.d.ts +36 -10
  127. package/dist/lib/agent-actions.js +63 -9
  128. package/dist/lib/agent-config.d.ts +11 -0
  129. package/dist/lib/agent-config.js +85 -3
  130. package/dist/lib/agent-pin-mute.d.ts +24 -0
  131. package/dist/lib/agent-pin-mute.js +17 -0
  132. package/dist/lib/agent-visual-refs.d.ts +6 -0
  133. package/dist/lib/agent-visual-refs.js +142 -0
  134. package/dist/lib/first-party-harness-agent.js +7 -0
  135. package/dist/lib/followups.d.ts +107 -0
  136. package/dist/lib/followups.js +102 -0
  137. package/dist/lib/label-ref.d.ts +95 -0
  138. package/dist/lib/label-ref.js +163 -0
  139. package/dist/lib/label-scope.d.ts +2 -2
  140. package/dist/lib/label-scope.js +3 -3
  141. package/dist/lib/task-closure.d.ts +32 -0
  142. package/dist/lib/task-closure.js +106 -0
  143. package/dist/lib/task-lifecycle-output.d.ts +14 -0
  144. package/dist/lib/task-lifecycle-output.js +101 -0
  145. package/dist/lib/tasks.d.ts +3 -0
  146. package/dist/lib/tasks.js +31 -0
  147. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
  148. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
  149. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  150. package/dist/node_modules/@skrr-ai/data-provider/index.js +5079 -4546
  151. package/oclif.manifest.json +20216 -16002
  152. package/package.json +16 -4
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
+ const label_ref_1 = require("../../../lib/label-ref");
6
7
  class GoalsLabelsRemove extends base_command_1.BaseCommand {
7
8
  static description = 'Detach a label from a goal';
8
9
  static examples = [
@@ -14,16 +15,35 @@ class GoalsLabelsRemove extends base_command_1.BaseCommand {
14
15
  };
15
16
  static flags = {
16
17
  json: core_1.Flags.boolean({ description: 'Output the updated goal as JSON' }),
17
- label: core_1.Flags.string({ description: 'Label ID to detach', required: true }),
18
+ label: core_1.Flags.string({
19
+ description: 'Label — id, or a name from `skrr labels list --applicable-to goal`. An unknown name is refused, never created.',
20
+ required: true,
21
+ }),
18
22
  };
19
23
  async run() {
20
24
  this.requireAuth();
21
25
  const { args, flags } = await this.parse(GoalsLabelsRemove);
22
26
  // Detach is intentionally permissive server-side: you can remove a label
23
27
  // you can no longer read, so a revoked label never gets stuck on a goal.
28
+ // A name is resolved against the DECLARED vocabulary; an unknown one is
29
+ // refused with the near misses named, never created. See lib/label-ref.
30
+ let labelId = flags.label;
31
+ try {
32
+ [labelId] = await (0, label_ref_1.resolveLabelRefs)([flags.label], {
33
+ applicableTo: 'goal',
34
+ ...(process.env.OVERSKY_WORKSPACE_ID
35
+ ? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
36
+ : {}),
37
+ });
38
+ }
39
+ catch (err) {
40
+ if (err instanceof label_ref_1.LabelRefError)
41
+ this.error(err.message, { exit: 1 });
42
+ this.handleApiError(err);
43
+ }
24
44
  let result;
25
45
  try {
26
- result = await data_provider_1.dataService.removeLabelFromGoal({ goalId: args.id, labelId: flags.label });
46
+ result = await data_provider_1.dataService.removeLabelFromGoal({ goalId: args.id, labelId });
27
47
  }
28
48
  catch (err) {
29
49
  this.handleApiError(err);
@@ -1,11 +1,34 @@
1
1
  import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * `labels list` — every label you can actually USE, by default.
4
+ *
5
+ * This used to default to `--scope user` and show one scope at a time, which
6
+ * is a faithful rendering of `GET /api/labels` and a poor answer to the
7
+ * question people ask. `scope` is an OWNERSHIP boundary, not a filter anyone
8
+ * browses by: a workspace-scoped label is attachable by every member, so
9
+ * leaving it out of the default view means the vocabulary you are told about
10
+ * is smaller than the one you have.
11
+ *
12
+ * It had a measurable cost. Three workspace-scoped labels existed and were
13
+ * invisible to the bare command, so nobody knew they were there — which is
14
+ * part of why the label system shipped complete and went unused, and why a
15
+ * second `dogfood` nearly got created beside one that already existed.
16
+ *
17
+ * `--scope` still narrows to exactly one scope, so every explicit invocation
18
+ * behaves as it always did. Only the bare command changed, and it changed to
19
+ * a superset.
20
+ *
21
+ * The merge itself is `lib/label-ref.collectLabelVocabulary` — the same
22
+ * function `--label <name>` resolves through. A separate copy here is how the
23
+ * name you can type and the name you can see start to disagree.
24
+ */
2
25
  export default class LabelsList extends BaseCommand {
3
26
  static description: string;
4
27
  static examples: string[];
5
28
  static flags: {
29
+ scope: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
6
30
  'applicable-to': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
31
  'include-archived': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
- scope: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
32
  'scope-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
33
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
34
  };
@@ -5,17 +5,48 @@ const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
6
  const format_1 = require("../../lib/format");
7
7
  const label_scope_1 = require("../../lib/label-scope");
8
+ const label_ref_1 = require("../../lib/label-ref");
9
+ /**
10
+ * `labels list` — every label you can actually USE, by default.
11
+ *
12
+ * This used to default to `--scope user` and show one scope at a time, which
13
+ * is a faithful rendering of `GET /api/labels` and a poor answer to the
14
+ * question people ask. `scope` is an OWNERSHIP boundary, not a filter anyone
15
+ * browses by: a workspace-scoped label is attachable by every member, so
16
+ * leaving it out of the default view means the vocabulary you are told about
17
+ * is smaller than the one you have.
18
+ *
19
+ * It had a measurable cost. Three workspace-scoped labels existed and were
20
+ * invisible to the bare command, so nobody knew they were there — which is
21
+ * part of why the label system shipped complete and went unused, and why a
22
+ * second `dogfood` nearly got created beside one that already existed.
23
+ *
24
+ * `--scope` still narrows to exactly one scope, so every explicit invocation
25
+ * behaves as it always did. Only the bare command changed, and it changed to
26
+ * a superset.
27
+ *
28
+ * The merge itself is `lib/label-ref.collectLabelVocabulary` — the same
29
+ * function `--label <name>` resolves through. A separate copy here is how the
30
+ * name you can type and the name you can see start to disagree.
31
+ */
8
32
  class LabelsList extends base_command_1.BaseCommand {
9
- static description = 'List labels in a scope';
33
+ static description = 'List labels — every scope you can use, unless --scope narrows it';
10
34
  static examples = [
11
35
  '<%= config.bin %> labels list',
12
36
  '<%= config.bin %> labels list --applicable-to space',
37
+ '<%= config.bin %> labels list --scope user',
13
38
  '<%= config.bin %> labels list --scope workspace --scope-id <workspace-id>',
14
39
  '<%= config.bin %> labels list --include-archived --json',
15
40
  ];
16
41
  static flags = {
17
42
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
18
43
  ...label_scope_1.labelScopeFlags,
44
+ // No default, unlike the shared flag: its absence is what selects the
45
+ // merged view, so "not passed" and "passed user" must stay distinguishable.
46
+ scope: core_1.Flags.string({
47
+ description: 'Narrow to ONE scope. Omit to list every scope you can use.',
48
+ options: ['user', 'workspace'],
49
+ }),
19
50
  'applicable-to': core_1.Flags.string({
20
51
  description: 'Only labels applicable to this entity type',
21
52
  options: [...label_scope_1.LABEL_APPLICABLE],
@@ -25,38 +56,49 @@ class LabelsList extends base_command_1.BaseCommand {
25
56
  async run() {
26
57
  this.requireAuth();
27
58
  const { flags } = await this.parse(LabelsList);
28
- let scope;
29
- try {
30
- scope = (0, label_scope_1.resolveLabelScope)(flags);
31
- }
32
- catch (err) {
33
- this.error(err.message, { exit: 1 });
34
- }
35
- let response;
59
+ const applicableTo = flags['applicable-to'];
60
+ let items = [];
36
61
  try {
37
- response = await data_provider_1.dataService.getLabels({
38
- ...scope,
39
- ...(flags['applicable-to']
40
- ? { applicableTo: flags['applicable-to'] }
41
- : {}),
42
- ...(flags['include-archived'] ? { includeArchived: true } : {}),
43
- });
62
+ if (flags.scope) {
63
+ const scope = (0, label_scope_1.resolveLabelScope)(flags);
64
+ const response = (await data_provider_1.dataService.getLabels({
65
+ ...scope,
66
+ ...(applicableTo ? { applicableTo } : {}),
67
+ ...(flags['include-archived'] ? { includeArchived: true } : {}),
68
+ }));
69
+ items = response?.data ?? [];
70
+ }
71
+ else {
72
+ items = await (0, label_ref_1.collectLabelVocabulary)({
73
+ ...(applicableTo ? { applicableTo } : {}),
74
+ ...(process.env.OVERSKY_WORKSPACE_ID
75
+ ? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
76
+ : {}),
77
+ ...(flags['include-archived'] ? { includeArchived: true } : {}),
78
+ });
79
+ }
44
80
  }
45
81
  catch (err) {
82
+ if (err instanceof Error && !('status' in err))
83
+ this.error(err.message, { exit: 1 });
46
84
  this.handleApiError(err);
47
85
  }
48
86
  if (flags.json) {
49
- this.log(JSON.stringify(response, null, 2));
87
+ this.log(JSON.stringify({ data: items }, null, 2));
50
88
  return;
51
89
  }
52
- const items = response?.data ?? [];
53
90
  if (items.length === 0) {
54
- this.log('No labels.');
91
+ this.log(flags.scope
92
+ ? 'No labels in this scope.'
93
+ : 'No labels you can use. Create one with `labels create --name <name> --applicable-to <entity>`.');
55
94
  return;
56
95
  }
57
96
  const rows = items.map((l) => ({
58
97
  id: String(l.id ?? '-'),
59
98
  name: String(l.name ?? '-'),
99
+ // Where it lives decides who else sees it, and it is the one column the
100
+ // old single-scope view never had to show.
101
+ scope: String(l.scope ?? '-'),
60
102
  color: String(l.color ?? '-'),
61
103
  appliesTo: Array.isArray(l.applicableTo) ? l.applicableTo.join(',') : '-',
62
104
  used: String(l.usageCount ?? 0),
@@ -65,6 +107,7 @@ class LabelsList extends base_command_1.BaseCommand {
65
107
  (0, format_1.renderTable)(rows, [
66
108
  { key: 'id', header: 'ID' },
67
109
  { key: 'name', header: 'NAME', maxWidth: 32 },
110
+ { key: 'scope', header: 'SCOPE' },
68
111
  { key: 'color', header: 'COLOR' },
69
112
  { key: 'appliesTo', header: 'APPLIES TO' },
70
113
  { key: 'used', header: 'USED' },
@@ -0,0 +1,21 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * An agent's memory POLICY: which pools its runtime may read and write, how long
4
+ * retained facts are governed, and what deletion means.
5
+ *
6
+ * Its own route rather than a corner of `PATCH /api/agents/:id`, and the CLI
7
+ * uses the same door the web does. The distinction the route draws — and this
8
+ * command surfaces — is between a policy an owner has DELIBERATELY saved and the
9
+ * defaults an unconfigured agent reads as. Mongoose materializes the leaf
10
+ * defaults on every new agent row, so "has a policy" cannot be answered by the
11
+ * field being present; only `updatedAt` says a human decided something.
12
+ */
13
+ export default class MemoryGovernanceShow extends BaseCommand {
14
+ static description: string;
15
+ static examples: string[];
16
+ static flags: {
17
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ };
20
+ run(): Promise<void>;
21
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const agent_resolver_1 = require("../../../lib/agent-resolver");
7
+ /**
8
+ * An agent's memory POLICY: which pools its runtime may read and write, how long
9
+ * retained facts are governed, and what deletion means.
10
+ *
11
+ * Its own route rather than a corner of `PATCH /api/agents/:id`, and the CLI
12
+ * uses the same door the web does. The distinction the route draws — and this
13
+ * command surfaces — is between a policy an owner has DELIBERATELY saved and the
14
+ * defaults an unconfigured agent reads as. Mongoose materializes the leaf
15
+ * defaults on every new agent row, so "has a policy" cannot be answered by the
16
+ * field being present; only `updatedAt` says a human decided something.
17
+ */
18
+ class MemoryGovernanceShow extends base_command_1.BaseCommand {
19
+ static description = "Show an agent's memory governance policy";
20
+ static examples = [
21
+ '<%= config.bin %> memory governance --agent <agent-id>',
22
+ '<%= config.bin %> memory governance --agent <agent-id> --json',
23
+ ];
24
+ static flags = {
25
+ agent: core_1.Flags.string({
26
+ description: 'Agent ID (falls back to OVERSKY_AGENT_ID, then your primary agent)',
27
+ }),
28
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
29
+ };
30
+ async run() {
31
+ this.requireAuth();
32
+ const { flags } = await this.parse(MemoryGovernanceShow);
33
+ let agentId;
34
+ try {
35
+ agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
36
+ }
37
+ catch (err) {
38
+ this.error(err.message, { exit: 1 });
39
+ }
40
+ let policy;
41
+ try {
42
+ policy = await data_provider_1.dataService.getAgentMemoryGovernance(agentId);
43
+ }
44
+ catch (err) {
45
+ this.handleApiError(err);
46
+ }
47
+ if (flags.json) {
48
+ this.log(this.agentJson(agentId, policy));
49
+ return;
50
+ }
51
+ const p = policy;
52
+ this.log(`Memory governance for agent ${agentId}`);
53
+ this.log(` Read scopes: ${(p.allowedReadScopes ?? []).join(', ') || '-'}`);
54
+ this.log(` Write scopes: ${(p.allowedWriteScopes ?? []).join(', ') || '-'}`);
55
+ this.log(` Retention: ${p.retentionDays ?? '-'} days`);
56
+ this.log(` On deletion: ${p.deletionMode ?? '-'}`);
57
+ this.log(` Shared memory: ${p.requireEvidenceForSharedMemory ? 'requires evidence' : 'no evidence required'}`);
58
+ this.log('');
59
+ this.log(p.updatedAt
60
+ ? `Configured ${String(p.updatedAt).slice(0, 10)}.`
61
+ : 'Never configured — these are the defaults a run reads, not a saved policy.');
62
+ }
63
+ }
64
+ exports.default = MemoryGovernanceShow;
@@ -0,0 +1,24 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Change an agent's memory policy. Requires EDIT on the agent.
4
+ *
5
+ * PARTIAL by design and worth being explicit about: the route merges over the
6
+ * leaves an owner has actually set, so omitting a flag leaves that leaf unset
7
+ * rather than freezing today's default into the row. That is why `--read-scope`
8
+ * REPLACES the list instead of adding to it — a list flag that appended would
9
+ * make "only agent memory" unreachable once anything wider had been granted.
10
+ */
11
+ export default class MemoryGovernanceSet extends BaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static flags: {
15
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ 'read-scope': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ 'write-scope': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ 'retention-days': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ 'deletion-mode': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ 'require-evidence': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
22
+ };
23
+ run(): Promise<void>;
24
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const agent_resolver_1 = require("../../../lib/agent-resolver");
7
+ const MEMORY_SCOPES = ['agent', 'user', 'workspace'];
8
+ /**
9
+ * Change an agent's memory policy. Requires EDIT on the agent.
10
+ *
11
+ * PARTIAL by design and worth being explicit about: the route merges over the
12
+ * leaves an owner has actually set, so omitting a flag leaves that leaf unset
13
+ * rather than freezing today's default into the row. That is why `--read-scope`
14
+ * REPLACES the list instead of adding to it — a list flag that appended would
15
+ * make "only agent memory" unreachable once anything wider had been granted.
16
+ */
17
+ class MemoryGovernanceSet extends base_command_1.BaseCommand {
18
+ static description = "Change an agent's memory governance policy (requires EDIT)";
19
+ static examples = [
20
+ '<%= config.bin %> memory governance set --agent <agent-id> --retention-days 90',
21
+ '<%= config.bin %> memory governance set --agent <agent-id> --read-scope agent --read-scope workspace',
22
+ '<%= config.bin %> memory governance set --agent <agent-id> --deletion-mode delete --no-require-evidence',
23
+ ];
24
+ static flags = {
25
+ agent: core_1.Flags.string({ description: 'Agent ID' }),
26
+ 'read-scope': core_1.Flags.string({
27
+ description: 'Memory pool the runtime may READ (repeatable; replaces the list)',
28
+ options: [...MEMORY_SCOPES],
29
+ multiple: true,
30
+ }),
31
+ 'write-scope': core_1.Flags.string({
32
+ description: 'Memory pool the runtime may WRITE (repeatable; replaces the list)',
33
+ options: [...MEMORY_SCOPES],
34
+ multiple: true,
35
+ }),
36
+ 'retention-days': core_1.Flags.integer({
37
+ description: 'How long retained facts are governed (1-3650)',
38
+ }),
39
+ 'deletion-mode': core_1.Flags.string({
40
+ description: 'What deletion means for this agent',
41
+ options: ['archive', 'delete'],
42
+ }),
43
+ 'require-evidence': core_1.Flags.boolean({
44
+ description: 'Require evidence before a fact enters shared memory',
45
+ allowNo: true,
46
+ }),
47
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
48
+ };
49
+ async run() {
50
+ this.requireAuth();
51
+ const { flags } = await this.parse(MemoryGovernanceSet);
52
+ const patch = {
53
+ ...(flags['read-scope'] === undefined
54
+ ? {}
55
+ : { allowedReadScopes: flags['read-scope'] }),
56
+ ...(flags['write-scope'] === undefined
57
+ ? {}
58
+ : { allowedWriteScopes: flags['write-scope'] }),
59
+ ...(flags['retention-days'] === undefined ? {} : { retentionDays: flags['retention-days'] }),
60
+ ...(flags['deletion-mode'] === undefined
61
+ ? {}
62
+ : { deletionMode: flags['deletion-mode'] }),
63
+ ...(flags['require-evidence'] === undefined
64
+ ? {}
65
+ : { requireEvidenceForSharedMemory: flags['require-evidence'] }),
66
+ };
67
+ if (Object.keys(patch).length === 0) {
68
+ this.error('Nothing to change. Pass at least one of --read-scope, --write-scope, ' +
69
+ '--retention-days, --deletion-mode, --require-evidence.', { exit: 1 });
70
+ }
71
+ let agentId;
72
+ try {
73
+ agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
74
+ }
75
+ catch (err) {
76
+ this.error(err.message, { exit: 1 });
77
+ }
78
+ let policy;
79
+ try {
80
+ policy = await data_provider_1.dataService.updateAgentMemoryGovernance(agentId, patch);
81
+ }
82
+ catch (err) {
83
+ this.handleApiError(err);
84
+ }
85
+ if (flags.json) {
86
+ this.log(this.agentJson(agentId, policy));
87
+ return;
88
+ }
89
+ this.log(`Updated memory governance for agent ${agentId}.`);
90
+ this.log(` Read scopes: ${(policy.allowedReadScopes ?? []).join(', ') || '-'}`);
91
+ this.log(` Write scopes: ${(policy.allowedWriteScopes ?? []).join(', ') || '-'}`);
92
+ this.log(` Retention: ${policy.retentionDays ?? '-'} days`);
93
+ }
94
+ }
95
+ exports.default = MemoryGovernanceSet;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * Where an agent's stored memories came from.
4
+ *
5
+ * The other half of governance: a policy says what a runtime MAY remember, and
6
+ * this says what it actually did and on whose evidence. Read-only, VIEW on the
7
+ * agent.
8
+ */
9
+ export default class MemoryProvenance extends BaseCommand {
10
+ static description: string;
11
+ static examples: string[];
12
+ static flags: {
13
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../base-command");
6
+ const agent_resolver_1 = require("../../lib/agent-resolver");
7
+ const format_1 = require("../../lib/format");
8
+ /**
9
+ * Where an agent's stored memories came from.
10
+ *
11
+ * The other half of governance: a policy says what a runtime MAY remember, and
12
+ * this says what it actually did and on whose evidence. Read-only, VIEW on the
13
+ * agent.
14
+ */
15
+ class MemoryProvenance extends base_command_1.BaseCommand {
16
+ static description = "Show where an agent's stored memories came from";
17
+ static examples = [
18
+ '<%= config.bin %> memory provenance --agent <agent-id>',
19
+ '<%= config.bin %> memory provenance --agent <agent-id> --limit 50 --json',
20
+ ];
21
+ static flags = {
22
+ agent: core_1.Flags.string({ description: 'Agent ID' }),
23
+ limit: core_1.Flags.integer({ description: 'How many entries to return' }),
24
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
25
+ };
26
+ async run() {
27
+ this.requireAuth();
28
+ const { flags } = await this.parse(MemoryProvenance);
29
+ let agentId;
30
+ try {
31
+ agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
32
+ }
33
+ catch (err) {
34
+ this.error(err.message, { exit: 1 });
35
+ }
36
+ let response;
37
+ try {
38
+ response = await data_provider_1.dataService.getAgentMemoryProvenance(agentId, flags.limit === undefined ? undefined : { limit: flags.limit });
39
+ }
40
+ catch (err) {
41
+ this.handleApiError(err);
42
+ }
43
+ if (flags.json) {
44
+ this.log(this.agentJson(agentId, response));
45
+ return;
46
+ }
47
+ const payload = response;
48
+ const entries = Array.isArray(response)
49
+ ? response
50
+ : (payload?.entries ?? []);
51
+ if (entries.length === 0) {
52
+ this.log(`No memory provenance recorded for agent ${agentId}.`);
53
+ return;
54
+ }
55
+ (0, format_1.renderTable)(entries.map((entry) => ({
56
+ key: String(entry.key ?? '-'),
57
+ source: String(entry.source ?? entry.origin ?? '-'),
58
+ at: entry.updated_at ? String(entry.updated_at).slice(0, 10) : '-',
59
+ })), [
60
+ { key: 'key', header: 'KEY', verbatim: true },
61
+ { key: 'source', header: 'SOURCE', maxWidth: 30 },
62
+ { key: 'at', header: 'UPDATED' },
63
+ ], (line) => this.log(line));
64
+ }
65
+ }
66
+ exports.default = MemoryProvenance;
@@ -9,7 +9,10 @@ export default class SpacesCreate extends BaseCommand {
9
9
  description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
10
  status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
11
  color: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ icon: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ 'icon-color': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
14
  'lead-agent': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ team: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
16
  'target-date': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
17
  goal: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
18
  label: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const outbox_1 = require("../../lib/outbox");
6
6
  const api_fetch_1 = require("../../lib/api-fetch");
7
7
  const base_command_1 = require("../../base-command");
8
+ const label_ref_1 = require("../../lib/label-ref");
8
9
  const web_url_1 = require("../../lib/web-url");
9
10
  const prompt_1 = require("../../lib/prompt");
10
11
  const created_line_1 = require("../../lib/created-line");
@@ -13,6 +14,7 @@ class SpacesCreate extends base_command_1.BaseCommand {
13
14
  static examples = [
14
15
  '<%= config.bin %> spaces create --title "Q2 Launch"',
15
16
  '<%= config.bin %> spaces create --title "Support" --status in_progress --color "#4f46e5"',
17
+ '<%= config.bin %> spaces create --title "Launch" --icon Rocket --icon-color "#2DD4BF"',
16
18
  '<%= config.bin %> spaces create --title "Research" --lead-agent <agent-id>',
17
19
  '<%= config.bin %> spaces create --title "Frontend" --parent <space-id>',
18
20
  '<%= config.bin %> spaces create --title "Private notes" --parent <space-id> --no-inherit-access',
@@ -27,11 +29,18 @@ class SpacesCreate extends base_command_1.BaseCommand {
27
29
  description: core_1.Flags.string({ description: 'Space description' }),
28
30
  status: core_1.Flags.string({ description: 'Space status', options: [...data_provider_1.SPACE_STATUSES] }),
29
31
  color: core_1.Flags.string({ description: 'Space color (hex, e.g. #4f46e5)' }),
32
+ icon: core_1.Flags.string({
33
+ description: 'Space icon — a curated icon name (e.g. Rocket, Star) or an emoji',
34
+ }),
35
+ 'icon-color': core_1.Flags.string({
36
+ description: 'Color applied to the space icon (hex, e.g. #2DD4BF)',
37
+ }),
30
38
  'lead-agent': core_1.Flags.string({ description: 'Space Leader agent ID' }),
39
+ team: core_1.Flags.string({ description: 'Team ID to attach this space to' }),
31
40
  'target-date': core_1.Flags.string({ description: 'Target date (ISO string)' }),
32
41
  goal: core_1.Flags.string({ description: 'Goal ID to link (repeatable)', multiple: true }),
33
42
  label: core_1.Flags.string({
34
- description: 'Label ID to attach (repeatable, max 50). Must be applicable to spaces. After creation use `spaces labels add/remove`.',
43
+ description: 'Label to attach (repeatable, max 50) — id, or a name from `skrr labels list --applicable-to space`. An unknown name is refused, never created. After creation use `spaces labels add/remove`.',
35
44
  multiple: true,
36
45
  }),
37
46
  'group-chat': core_1.Flags.string({ description: 'Group chat ID to link this space to' }),
@@ -53,15 +62,36 @@ class SpacesCreate extends base_command_1.BaseCommand {
53
62
  catch (err) {
54
63
  this.error(err.message, { exit: 1 });
55
64
  }
65
+ // A name is resolved against the DECLARED vocabulary before the create, so
66
+ // a typo fails here — cheaply, with the near misses named — rather than
67
+ // minting a second spelling of a label somebody already has.
68
+ let resolvedLabelIds;
69
+ try {
70
+ const ids = await (0, label_ref_1.resolveLabelRefs)(flags.label, {
71
+ applicableTo: 'space',
72
+ ...(process.env.OVERSKY_WORKSPACE_ID
73
+ ? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
74
+ : {}),
75
+ });
76
+ resolvedLabelIds = ids.length > 0 ? ids : undefined;
77
+ }
78
+ catch (err) {
79
+ if (err instanceof label_ref_1.LabelRefError)
80
+ this.error(err.message, { exit: 1 });
81
+ this.handleApiError(err);
82
+ }
56
83
  const payload = (0, prompt_1.mergeDefined)(body, {
57
84
  title: flags.title,
58
85
  description: flags.description,
59
86
  status: flags.status,
60
87
  color: flags.color,
88
+ icon: flags.icon,
89
+ iconColor: flags['icon-color'],
61
90
  leadAgentId: flags['lead-agent'],
91
+ teamId: flags.team,
62
92
  targetDate: flags['target-date'],
63
93
  goalIds: flags.goal,
64
- labelIds: flags.label,
94
+ labelIds: resolvedLabelIds,
65
95
  groupChatId: flags['group-chat'],
66
96
  parentSpaceId: flags.parent,
67
97
  inheritAccess: flags['inherit-access'],
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
+ const label_ref_1 = require("../../../lib/label-ref");
6
7
  const web_url_1 = require("../../../lib/web-url");
7
8
  class SpacesLabelsAdd extends base_command_1.BaseCommand {
8
9
  static description = 'Attach a label to a space';
@@ -16,7 +17,7 @@ class SpacesLabelsAdd extends base_command_1.BaseCommand {
16
17
  static flags = {
17
18
  json: core_1.Flags.boolean({ description: 'Output the updated space as JSON' }),
18
19
  label: core_1.Flags.string({
19
- description: 'Label ID — must be applicable to spaces (see `skrr labels list --applicable-to space`)',
20
+ description: 'Label — id, or a name from `skrr labels list --applicable-to space`. An unknown name is refused, never created.',
20
21
  required: true,
21
22
  }),
22
23
  };
@@ -26,9 +27,25 @@ class SpacesLabelsAdd extends base_command_1.BaseCommand {
26
27
  // `spaces update` deliberately refuses labelIds — the server routes label
27
28
  // changes through this atomic $addToSet endpoint so concurrent edits can't
28
29
  // clobber each other. Re-attaching an already-attached label is a no-op.
30
+ // A name is resolved against the DECLARED vocabulary; an unknown one is
31
+ // refused with the near misses named, never created. See lib/label-ref.
32
+ let labelId = flags.label;
33
+ try {
34
+ [labelId] = await (0, label_ref_1.resolveLabelRefs)([flags.label], {
35
+ applicableTo: 'space',
36
+ ...(process.env.OVERSKY_WORKSPACE_ID
37
+ ? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
38
+ : {}),
39
+ });
40
+ }
41
+ catch (err) {
42
+ if (err instanceof label_ref_1.LabelRefError)
43
+ this.error(err.message, { exit: 1 });
44
+ this.handleApiError(err);
45
+ }
29
46
  let result;
30
47
  try {
31
- result = await data_provider_1.dataService.addLabelToSpace({ spaceId: args.id, labelId: flags.label });
48
+ result = await data_provider_1.dataService.addLabelToSpace({ spaceId: args.id, labelId });
32
49
  }
33
50
  catch (err) {
34
51
  this.handleApiError(err);