@unisonlabs/sixminute-admin 0.1.617 → 0.1.670-next

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,7 +55,6 @@ sixminute-admin tier set --env production --tenant tenant_... --tier standard
55
55
  sixminute-admin versions --env production --tenant tenant_...
56
56
  sixminute-admin entries purge --env staging --tenant tenant_... --author member_... --demo --dry-run
57
57
  sixminute-admin research export --env production --tenant tenant_... --from 2026-09-01 --to 2026-09-08 --out ./out
58
- sixminute-admin activity-type list --env production --tenant tenant_...
59
58
  sixminute-admin member list --env production --tenant tenant_...
60
59
  sixminute-admin matters import --env production --tenant tenant_... --from-file matters.json
61
60
  sixminute-admin matter list --env production --tenant tenant_... --all
@@ -21,7 +21,7 @@ import { homedir } from "node:os";
21
21
  import { fileURLToPath } from "node:url";
22
22
 
23
23
  // tools/admin/src/build-info.ts
24
- var BUILT = { version: "0.1.617", commit: "9332e005679d8639cc55297ce08e6c881aa3dc74", surface: "1d814431cdc5d665" };
24
+ var BUILT = { version: "0.1.670-next", commit: "c5855dcbd6535d427a6e119639961120c75de9f7", surface: "95a24975187b108d" };
25
25
 
26
26
  // tools/admin/src/run.ts
27
27
  import { rmSync as rmSync3 } from "node:fs";
@@ -4059,6 +4059,7 @@ var ObservationSchema = exports_external.object({
4059
4059
  signals: SignalsSchema,
4060
4060
  input_text: exports_external.string().default(""),
4061
4061
  input_chars: exports_external.number().int().min(0).default(0),
4062
+ input_marks: exports_external.array(exports_external.tuple([TimestampSchema, exports_external.number().int().nonnegative()])).default([]),
4062
4063
  clicks: exports_external.array(CaptureClickSchema).default([]),
4063
4064
  entry_id: EntryIdSchema.nullable(),
4064
4065
  recording_id: RecordingIdSchema.nullable().default(null)
@@ -4106,16 +4107,6 @@ var OperatorAuditQuerySchema = exports_external.object({
4106
4107
  });
4107
4108
  var OperatorAuditListSchema = exports_external.object({ actions: exports_external.array(OperatorActionSchema) });
4108
4109
  // packages/contracts/src/vocabulary.ts
4109
- var ActivityTypeKeySchema = exports_external.string().regex(/^[A-Za-z0-9_-]{1,40}$/, "an activity type key is 1 to 40 letters, digits, underscores or hyphens, such as A103 or draft-revise");
4110
- var ActivityTypeSourceSchema = exports_external.enum(["published", "firm"]);
4111
- var ActivityTypeSchema = exports_external.object({
4112
- key: ActivityTypeKeySchema,
4113
- title: exports_external.string().min(1),
4114
- description: exports_external.string().min(1),
4115
- active: exports_external.boolean().default(true),
4116
- position: exports_external.number().int().default(0),
4117
- source: ActivityTypeSourceSchema.default("firm")
4118
- });
4119
4110
  var AttributeKeySchema = exports_external.string().regex(/^[a-z][a-z0-9_]{0,39}$/, "an attribute key is a lower-case machine name: a letter, then letters, digits or underscores, at most 40");
4120
4111
  var RESERVED_ATTRIBUTE_KEYS = ["utbms_task", "utbms_activity"];
4121
4112
  var VocabularySourceSchema = exports_external.enum(["firm", "connector"]);
@@ -4318,6 +4309,19 @@ function readMatterRecord(raw) {
4318
4309
  };
4319
4310
  }
4320
4311
 
4312
+ // packages/contracts/src/compat.ts
4313
+ var ActivityTypeKeySchema = exports_external.string().regex(/^[A-Za-z0-9_-]{1,40}$/, "an activity type key is 1 to 40 letters, digits, underscores or hyphens, such as A103 or draft-revise");
4314
+ var ActivityTypeSourceSchema = exports_external.enum(["published", "firm"]);
4315
+ var ActivityTypeSchema = exports_external.object({
4316
+ key: ActivityTypeKeySchema,
4317
+ title: exports_external.string().min(1),
4318
+ description: exports_external.string().min(1),
4319
+ active: exports_external.boolean().default(true),
4320
+ position: exports_external.number().int().default(0),
4321
+ source: ActivityTypeSourceSchema.default("firm")
4322
+ });
4323
+ var JudgmentPipelineSchema = exports_external.enum(["standard", "jev"]);
4324
+
4321
4325
  // packages/contracts/src/entry.ts
4322
4326
  var EntryStatusSchema = exports_external.enum(["draft", "released"]);
4323
4327
  var AssignmentSchema = exports_external.enum(["model", "user", "none"]);
@@ -4354,7 +4358,7 @@ var AsJudgedSchema = EntryContentFields.omit({
4354
4358
  updated_at: true,
4355
4359
  released_at: true
4356
4360
  }).extend({
4357
- activity_type: ActivityTypeKeySchema.nullable().default(null),
4361
+ activity_type: ActivityTypeKeySchema.nullable().optional(),
4358
4362
  judged_at: TimestampSchema
4359
4363
  });
4360
4364
  var AS_JUDGED_FIELDS = Object.keys(AsJudgedSchema.shape);
@@ -4797,6 +4801,7 @@ var NARRATIVE_GUIDANCE_MAX_CHARS = 1500;
4797
4801
  var GUIDANCE_CONTROL = /[\u0000-\u0009\u000B-\u001F\u007F-\u009F]/;
4798
4802
  var NarrativeMaxCharsSchema = exports_external.number().int().min(40).max(1023);
4799
4803
  var NarrativeGuidanceSchema = exports_external.string().trim().max(NARRATIVE_GUIDANCE_MAX_CHARS).refine((text) => !GUIDANCE_CONTROL.test(text), { message: "guidance holds no control character but a newline" });
4804
+ var FirmAlwaysOnSchema = exports_external.enum(["member_choice", "enforced"]);
4800
4805
  var FirmSettingsSchema = exports_external.object({
4801
4806
  unit_minutes: UnitMinutesSchema.default(6),
4802
4807
  narrative: exports_external.object({
@@ -4804,7 +4809,8 @@ var FirmSettingsSchema = exports_external.object({
4804
4809
  language: NarrativeLanguageSchema.default("en"),
4805
4810
  guidance: NarrativeGuidanceSchema.default(""),
4806
4811
  lowered_to_system: exports_external.object({ kind: ConnectorKindSchema, at: TimestampSchema }).nullable().default(null)
4807
- }).default({})
4812
+ }).default({}),
4813
+ capture: exports_external.object({ always_on: FirmAlwaysOnSchema.default("member_choice") }).default({})
4808
4814
  }).default({});
4809
4815
  var FirmSettingsPatchSchema = exports_external.object({
4810
4816
  unit_minutes: UnitMinutesSchema.optional(),
@@ -4812,7 +4818,8 @@ var FirmSettingsPatchSchema = exports_external.object({
4812
4818
  max_chars: NarrativeMaxCharsSchema.nullable().optional(),
4813
4819
  language: NarrativeLanguageSchema.optional(),
4814
4820
  guidance: NarrativeGuidanceSchema.optional()
4815
- }).optional()
4821
+ }).optional(),
4822
+ capture: exports_external.object({ always_on: FirmAlwaysOnSchema.optional() }).optional()
4816
4823
  });
4817
4824
  var TenantSchema = exports_external.object({
4818
4825
  id: TenantIdSchema,
@@ -4878,7 +4885,6 @@ var MeSystemLinkSchema = exports_external.object({
4878
4885
  name: exports_external.string().min(1),
4879
4886
  code: exports_external.string().min(1).nullable()
4880
4887
  });
4881
- var JudgmentPipelineSchema = exports_external.enum(["standard", "jev"]);
4882
4888
  var MeSchema = exports_external.object({
4883
4889
  user: UserSchema,
4884
4890
  tenant: TenantSchema.extend({
@@ -5586,9 +5592,6 @@ var ConfigModelsSchema = exports_external.object({
5586
5592
  write: exports_external.string().min(1)
5587
5593
  });
5588
5594
  var JudgeTunablesSchema = exports_external.object({
5589
- windowMinutes: exports_external.number(),
5590
- edgeSearchMinutes: exports_external.number(),
5591
- renderBudgetChars: exports_external.number(),
5592
5595
  shortlistSize: exports_external.number(),
5593
5596
  cardOpeningChars: exports_external.number(),
5594
5597
  cardChangedChars: exports_external.number(),
@@ -5600,31 +5603,39 @@ var JudgeTunablesSchema = exports_external.object({
5600
5603
  sampleIntervalSeconds: exports_external.number(),
5601
5604
  absentAfterMinutes: exports_external.number(),
5602
5605
  maxNarrativeChars: exports_external.number(),
5603
- judgeSamples: exports_external.number(),
5606
+ judgeSamples: exports_external.number()
5607
+ });
5608
+ var ServedJudgeTunablesSchema = JudgeTunablesSchema.extend({
5609
+ windowMinutes: exports_external.number(),
5610
+ edgeSearchMinutes: exports_external.number(),
5611
+ renderBudgetChars: exports_external.number(),
5604
5612
  activitySamples: exports_external.number()
5605
5613
  });
5606
5614
  var ConfigPromptsSchema = exports_external.object({
5607
5615
  label: exports_external.string().min(1),
5608
- activity: exports_external.string().min(1),
5616
+ activity: exports_external.string().min(1).optional(),
5609
5617
  narrative: exports_external.string().min(1)
5610
5618
  });
5611
- var ConfigVocabulariesSchema = exports_external.object({
5612
- activity_types: exports_external.array(ActivityTypeSchema).min(1, "a bundle carries at least one activity type: it is what a firm with no list is judged from").superRefine((types2, ctx) => {
5613
- const seen = new Map;
5614
- types2.forEach((type, index) => {
5615
- const first = seen.get(type.key);
5616
- if (first === undefined) {
5617
- seen.set(type.key, index);
5618
- return;
5619
- }
5620
- ctx.addIssue({
5621
- code: exports_external.ZodIssueCode.custom,
5622
- path: [index, "key"],
5623
- message: `${type.key} is already an activity type of this bundle, at index ${first}`
5624
- });
5619
+ var ServedConfigPromptsSchema = ConfigPromptsSchema.extend({ activity: exports_external.string().min(1) });
5620
+ var PublishedActivityTypesSchema = exports_external.array(ActivityTypeSchema).min(1, "a bundle carries at least one activity type: it is what a firm with no list is judged from").superRefine((types2, ctx) => {
5621
+ const seen = new Map;
5622
+ types2.forEach((type, index) => {
5623
+ const first = seen.get(type.key);
5624
+ if (first === undefined) {
5625
+ seen.set(type.key, index);
5626
+ return;
5627
+ }
5628
+ ctx.addIssue({
5629
+ code: exports_external.ZodIssueCode.custom,
5630
+ path: [index, "key"],
5631
+ message: `${type.key} is already an activity type of this bundle, at index ${first}`
5625
5632
  });
5626
- })
5633
+ });
5627
5634
  });
5635
+ var ConfigVocabulariesSchema = exports_external.object({
5636
+ activity_types: PublishedActivityTypesSchema.optional()
5637
+ });
5638
+ var ServedConfigVocabulariesSchema = exports_external.object({ activity_types: PublishedActivityTypesSchema });
5628
5639
  var ConfigBundleSchema = exports_external.object({
5629
5640
  version: ConfigVersionSchema,
5630
5641
  generated_at: TimestampSchema,
@@ -5633,6 +5644,11 @@ var ConfigBundleSchema = exports_external.object({
5633
5644
  prompts: ConfigPromptsSchema,
5634
5645
  vocabularies: ConfigVocabulariesSchema
5635
5646
  });
5647
+ var ServedConfigBundleSchema = ConfigBundleSchema.extend({
5648
+ judge: ServedJudgeTunablesSchema,
5649
+ prompts: ServedConfigPromptsSchema,
5650
+ vocabularies: ServedConfigVocabulariesSchema
5651
+ });
5636
5652
  // packages/contracts/src/recording.ts
5637
5653
  var RecordingSchema = exports_external.object({
5638
5654
  id: RecordingIdSchema,
@@ -5810,6 +5826,11 @@ var InstalledAppSchema = exports_external.object({
5810
5826
  identities: exports_external.array(exports_external.string().min(1)).min(1),
5811
5827
  icon: exports_external.string().regex(/^iVBORw0KGgo[A-Za-z0-9+/]*={0,2}$/, { message: "an icon is a PNG as base64" }).nullable()
5812
5828
  });
5829
+ var LocalAlwaysOnSchema = exports_external.object({
5830
+ on: exports_external.boolean(),
5831
+ enforced: exports_external.boolean()
5832
+ });
5833
+ var ALWAYS_ON_OFF = { on: false, enforced: false };
5813
5834
  var LocalSettingsSchema = exports_external.object({
5814
5835
  capture_enabled: exports_external.boolean(),
5815
5836
  excluded_bundles: exports_external.array(exports_external.string().min(1)),
@@ -5822,7 +5843,8 @@ var LocalSettingsSchema = exports_external.object({
5822
5843
  on_since: TimestampSchema.nullable(),
5823
5844
  until: TimestampSchema.nullable(),
5824
5845
  folder: exports_external.string().min(1).nullable()
5825
- }).default({ allowed: false, on: false, on_since: null, until: null, folder: null })
5846
+ }).default({ allowed: false, on: false, on_since: null, until: null, folder: null }),
5847
+ always_on: LocalAlwaysOnSchema.default(ALWAYS_ON_OFF)
5826
5848
  });
5827
5849
  var LocalSettingsPatchSchema = exports_external.object({
5828
5850
  capture_enabled: exports_external.boolean().optional(),
@@ -5830,6 +5852,7 @@ var LocalSettingsPatchSchema = exports_external.object({
5830
5852
  excluded_sites: exports_external.array(SiteSchema).optional(),
5831
5853
  add_excluded_bundles: exports_external.array(exports_external.string().min(1)).optional(),
5832
5854
  add_excluded_sites: exports_external.array(SiteSchema).optional(),
5855
+ always_on: exports_external.boolean().optional(),
5833
5856
  raw_archive: exports_external.object({
5834
5857
  on: exports_external.boolean(),
5835
5858
  reason: RawArchiveReasonSchema.extract(["refused", "disk_low"]).optional()
@@ -5881,6 +5904,10 @@ var LocalOpenRecordingSchema = exports_external.object({
5881
5904
  id: RecordingIdSchema,
5882
5905
  started_at: TimestampSchema
5883
5906
  });
5907
+ var LocalFormingSchema = exports_external.object({
5908
+ from: TimestampSchema,
5909
+ to: TimestampSchema
5910
+ });
5884
5911
  var LocalStatusSchema = exports_external.object({
5885
5912
  version: exports_external.string().min(1),
5886
5913
  started_at: TimestampSchema,
@@ -5896,7 +5923,9 @@ var LocalStatusSchema = exports_external.object({
5896
5923
  member_id: MemberIdSchema.nullable().default(null),
5897
5924
  config_version: ConfigVersionSchema.nullable().default(null),
5898
5925
  api_url: exports_external.string().nullable().default(null),
5899
- update_required: exports_external.boolean().optional()
5926
+ update_required: exports_external.boolean().optional(),
5927
+ forming: LocalFormingSchema.nullable().default(null),
5928
+ always_on: LocalAlwaysOnSchema.default(ALWAYS_ON_OFF)
5900
5929
  });
5901
5930
  var LocalRecordingsSchema = exports_external.array(RecordingSchema);
5902
5931
  var LocalRecordingStopSchema = exports_external.object({
@@ -5986,7 +6015,7 @@ var RunSchema = exports_external.object({
5986
6015
  to_at: TimestampSchema,
5987
6016
  verdict: VerdictSchema,
5988
6017
  matter_id: MatterIdSchema.nullable().default(null),
5989
- activity_type: ActivityTypeKeySchema.nullable().default(null),
6018
+ activity_type: ActivityTypeKeySchema.nullable().optional(),
5990
6019
  attributes: EntryAttributesSchema.default({}),
5991
6020
  cell_text: exports_external.array(IntervalTextItemSchema).nullable().default(null),
5992
6021
  mini_narratives: exports_external.array(IntervalTextItemSchema).optional(),
@@ -6001,9 +6030,9 @@ var RunSchema = exports_external.object({
6001
6030
  }).refine((r) => r.verdict === "matter" === (r.matter_id !== null), {
6002
6031
  message: "a matter id belongs to a `matter` verdict and to no other",
6003
6032
  path: ["matter_id"]
6004
- }).refine((r) => WORK_VERDICTS.includes(r.verdict) ? r.activity_type !== null && r.narrative !== null && r.narrative !== "" : r.activity_type === null && r.narrative === null, {
6005
- message: "a run that is work carries an activity type and a narrative; an absent run carries neither",
6006
- path: ["activity_type"]
6033
+ }).refine((r) => WORK_VERDICTS.includes(r.verdict) ? r.narrative !== null && (r.narrative !== "" || r.failed) : r.narrative === null, {
6034
+ message: "a run that is work carries a narrative; an absent run carries none",
6035
+ path: ["narrative"]
6007
6036
  }).refine((r) => WORK_VERDICTS.includes(r.verdict) || Object.keys(r.attributes).length === 0 && r.cell_text === null, {
6008
6037
  message: "an absent run is never an entry, so it carries no proposed attributes and no judged text",
6009
6038
  path: ["attributes"]
@@ -6736,21 +6765,6 @@ is required; without one every command answers 403.
6736
6765
  --dry-run prints every row it would remove and writes nothing; without
6737
6766
  it and without --yes the command prints the same list and refuses.
6738
6767
 
6739
- sixminute-admin activity-type add --env <env> --tenant tenant_... --key A103 --title "Draft/revise" --description "..." [--json]
6740
- Writes one activity type, whole. The activity type is the CUT KEY: the
6741
- activity call answers one per cell from this list and the day is cut
6742
- where it changes. It never reaches an entry, a screen or a practice
6743
- system, and the length of the list is the one granularity knob a firm
6744
- has. A firm with no rows at all is judged from the published eleven,
6745
- and its first write adopts those eleven as its own rows before it
6746
- applies; a firm trims them by retiring. A new key goes after the
6747
- firm's last and a key the firm holds keeps its place, so there is no
6748
- --position.
6749
- sixminute-admin activity-type list --env <env> --tenant tenant_... [--json]
6750
- sixminute-admin activity-type retire A110 --env <env> --tenant tenant_... [--json]
6751
- Writes active false on the row the firm holds. It sends no DELETE:
6752
- a day already judged on that key keeps its runs.
6753
-
6754
6768
  sixminute-admin attribute add --env <env> --tenant tenant_... --key utbms_task --label "UTBMS task" [--required] [--proposed] [--default-set aset_a,aset_b] [--json]
6755
6769
  Writes one attribute, whole: a bounded single-select field on an entry,
6756
6770
  which is what a firm calls its codes. --default-set names the sets a
@@ -7016,7 +7030,7 @@ async function runAdmin(argv, deps) {
7016
7030
  return { code: 0, lines: [`sixminute-admin ${deps.build.version} (API ${deps.build.commit}, operator surface ${deps.build.surface})`] };
7017
7031
  }
7018
7032
  const oneWord = ["login", "logout", "whoami", "doctor", "versions", "audit"].includes(group);
7019
- const vocabulary2 = group === "activity-type" || group === "attribute" || group === "matter" && subcommand === "sets";
7033
+ const vocabulary2 = group === "attribute" || group === "matter" && subcommand === "sets";
7020
7034
  const threeDeep = group === "tenant" && subcommand === "internal";
7021
7035
  let flagArgv;
7022
7036
  const positionals = [];
@@ -7422,7 +7436,6 @@ async function runVocabulary(run2, group, subcommand, action, positionals) {
7422
7436
  return expectOk(answer, `${method} ${base}${path}`);
7423
7437
  };
7424
7438
  const done = (payload, lines) => render(run2, payload, [...head === null ? [] : [head], ...lines]);
7425
- const activityTypes = async () => exports_external.array(ActivityTypeSchema).parse(await firm("GET", "/activity-types"));
7426
7439
  const attributes = async () => exports_external.array(AttributeSchema).parse(await firm("GET", "/attributes"));
7427
7440
  const keyOf = (command, why) => {
7428
7441
  const positional = positionals[0];
@@ -7433,39 +7446,6 @@ async function runVocabulary(run2, group, subcommand, action, positionals) {
7433
7446
  return named;
7434
7447
  throw new AdminUsageError(`${command} takes the key as its argument, or --key: ${why}`);
7435
7448
  };
7436
- if (group === "activity-type") {
7437
- if (subcommand === "add") {
7438
- if (flags.values.has("position")) {
7439
- throw new AdminUsageError("--position is not taken on activity-type add: a new activity type goes after the firm's last");
7440
- }
7441
- const row = ActivityTypeSchema.parse({
7442
- key: required(flags, "key", "an activity type is named by its key, which is what the request renders"),
7443
- title: required(flags, "title", "the short name of the kind of work"),
7444
- description: required(flags, "description", "one sentence, and it is what the activity call reads")
7445
- });
7446
- const written = ActivityTypeSchema.parse(await firm("PUT", `/activity-types/${enc(row.key)}`, row));
7447
- return done({ activity_type: written }, [
7448
- `activity type ${written.key} ${written.title} ${written.active ? "active" : "retired"}`
7449
- ]);
7450
- }
7451
- if (subcommand === "list") {
7452
- const rows = await activityTypes();
7453
- return done({ activity_types: rows }, [
7454
- `${rows.length} activity type(s)`,
7455
- ...rows.map((row) => ` ${row.key} ${row.title} ${row.active ? "active" : "retired"}`)
7456
- ]);
7457
- }
7458
- if (subcommand === "retire") {
7459
- const key = keyOf("activity-type retire", "which activity type to retire");
7460
- const rows = await activityTypes();
7461
- const row = rows.find((one) => one.key === key);
7462
- if (row === undefined) {
7463
- throw new AdminUsageError(`this firm has no active activity type ${key}; it holds ${rows.map((one) => one.key).join(", ") || "none"}`);
7464
- }
7465
- const written = ActivityTypeSchema.parse(await firm("PUT", `/activity-types/${enc(key)}`, { ...row, active: false }));
7466
- return done({ activity_type: written }, [`activity type ${written.key} retired (active false). Nothing was deleted.`]);
7467
- }
7468
- }
7469
7449
  if (group === "attribute" && subcommand === "set") {
7470
7450
  if (action === "put") {
7471
7451
  const file = required(flags, "from-file", "the options are a document, not a flag: see tools/admin/examples/");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unisonlabs/sixminute-admin",
3
- "version": "0.1.617",
3
+ "version": "0.1.670-next",
4
4
  "description": "Sixminute operator tool: the admin commands of the Sixminute API, run with your own operator sign-in.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {