@software-dlc/cli 0.165.2 → 0.166.2

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 (37) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cli-org.d.ts.map +1 -1
  3. package/dist/cli-org.js +65 -62
  4. package/dist/cli-org.js.map +1 -1
  5. package/dist/local/app-org-reader.d.ts +8 -0
  6. package/dist/local/app-org-reader.d.ts.map +1 -1
  7. package/dist/local/app-org-reader.js +77 -11
  8. package/dist/local/app-org-reader.js.map +1 -1
  9. package/dist/local/app-queues.d.ts.map +1 -1
  10. package/dist/local/app-queues.js +8 -7
  11. package/dist/local/app-queues.js.map +1 -1
  12. package/dist/local/local-org-store.d.ts +8 -0
  13. package/dist/local/local-org-store.d.ts.map +1 -1
  14. package/dist/local/local-org-store.js +9 -1
  15. package/dist/local/local-org-store.js.map +1 -1
  16. package/dist/local/local-org.d.ts +9 -5
  17. package/dist/local/local-org.d.ts.map +1 -1
  18. package/dist/local/local-org.js +44 -33
  19. package/dist/local/local-org.js.map +1 -1
  20. package/dist/local/org-change.d.ts +90 -0
  21. package/dist/local/org-change.d.ts.map +1 -0
  22. package/dist/local/org-change.js +169 -0
  23. package/dist/local/org-change.js.map +1 -0
  24. package/dist/local/workspace-cli.d.ts +8 -4
  25. package/dist/local/workspace-cli.d.ts.map +1 -1
  26. package/dist/local/workspace-cli.js +10 -6
  27. package/dist/local/workspace-cli.js.map +1 -1
  28. package/dist/local/workspace-viewer-server.d.ts +5 -0
  29. package/dist/local/workspace-viewer-server.d.ts.map +1 -1
  30. package/dist/local/workspace-viewer-server.js +34 -4
  31. package/dist/local/workspace-viewer-server.js.map +1 -1
  32. package/package.json +1 -1
  33. package/viewer/assets/index-C7Yy02Wd.js +292 -0
  34. package/viewer/assets/index-DL11ZUBq.css +1 -0
  35. package/viewer/index.html +2 -2
  36. package/viewer/assets/index-BZKGDARF.css +0 -1
  37. package/viewer/assets/index-DigEC27q.js +0 -287
@@ -0,0 +1,90 @@
1
+ import type { OrgMember } from '@software-dlc/graph/computation';
2
+ import { changeLocalBinding, type LocalOrgRepository, type WorkflowRoles } from './local-org.js';
3
+ /**
4
+ * One change to the local org (osa-editors-viewer): what `sdlc org add`, `edit`, `remove`, `bind`
5
+ * and `unbind` do, as data. The CLI and the viewer's POST api/org-change both apply it with
6
+ * applyOrgChange, so their rules and refusals are one (osa_structure_ac_9).
7
+ */
8
+ export type OrgChangeKind = 'team' | 'job_function' | 'slot';
9
+ export type OrgChange = {
10
+ action: 'add';
11
+ kind: 'team';
12
+ key: string;
13
+ label?: string;
14
+ description?: string;
15
+ parent?: string;
16
+ } | {
17
+ action: 'add';
18
+ kind: 'job_function';
19
+ key: string;
20
+ label?: string;
21
+ description?: string;
22
+ parent?: string;
23
+ fills?: string[];
24
+ requires_person?: boolean;
25
+ escalable?: boolean;
26
+ } | {
27
+ action: 'add';
28
+ kind: 'slot';
29
+ key: string;
30
+ label?: string;
31
+ description?: string;
32
+ } | {
33
+ action: 'add';
34
+ kind: 'post';
35
+ key: string;
36
+ label?: string;
37
+ } | {
38
+ action: 'edit';
39
+ kind: 'team';
40
+ key: string;
41
+ label?: string;
42
+ description?: string;
43
+ parent?: string | null;
44
+ } | {
45
+ action: 'edit';
46
+ kind: 'job_function';
47
+ key: string;
48
+ label?: string;
49
+ description?: string;
50
+ parent?: string | null;
51
+ fills?: string[];
52
+ requires_person?: boolean;
53
+ escalable?: boolean;
54
+ } | {
55
+ action: 'edit';
56
+ kind: 'slot';
57
+ key: string;
58
+ label?: string;
59
+ description?: string;
60
+ } | {
61
+ action: 'remove';
62
+ kind: OrgChangeKind | 'post';
63
+ key: string;
64
+ } | {
65
+ action: 'bind';
66
+ slot: string;
67
+ posts: string[];
68
+ reason: string;
69
+ } | {
70
+ action: 'unbind';
71
+ slot: string;
72
+ };
73
+ /**
74
+ * The change a request body names, or a refusal saying what to send: an unknown action, kind or
75
+ * field is refused rather than dropped, so a change never does less than it asked.
76
+ */
77
+ export declare function parseOrgChange(value: unknown): OrgChange;
78
+ export type OrgChangeResult = {
79
+ changed: true;
80
+ root: string;
81
+ } | Awaited<ReturnType<typeof changeLocalBinding>>;
82
+ /**
83
+ * Applies one change to the repository's local org, as `actor`, checking the whole org in one
84
+ * transaction (changeLocalOrg, changeLocalBinding). A refusal throws its reason, and nothing changes.
85
+ */
86
+ export declare function applyOrgChange(repository: LocalOrgRepository, change: OrgChange, options: {
87
+ actor: OrgMember;
88
+ workflow: WorkflowRoles | null;
89
+ }): Promise<OrgChangeResult>;
90
+ //# sourceMappingURL=org-change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-change.d.ts","sourceRoot":"","sources":["../../src/local/org-change.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,169 @@
1
+ import { addJobFunction, addPost, addSlot, addTeam, changeLocalBinding, changeLocalOrg, editJobFunction, editSlot, editTeam, onOrg, removeDefinition, removePost } from './local-org.js';
2
+ const TEXT_LIMIT = 4_000;
3
+ const LIST_LIMIT = 64;
4
+ function isRecord(value) {
5
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
6
+ }
7
+ /** The fields each change takes beside `action`; any other is refused. */
8
+ const FIELDS = {
9
+ add: {
10
+ team: ['key', 'label', 'description', 'parent'],
11
+ job_function: ['key', 'label', 'description', 'parent', 'fills', 'requires_person', 'escalable'],
12
+ slot: ['key', 'label', 'description'],
13
+ post: ['key', 'label']
14
+ },
15
+ edit: {
16
+ team: ['key', 'label', 'description', 'parent'],
17
+ job_function: ['key', 'label', 'description', 'parent', 'fills', 'requires_person', 'escalable'],
18
+ slot: ['key', 'label', 'description']
19
+ },
20
+ remove: {
21
+ team: ['key'],
22
+ job_function: ['key'],
23
+ slot: ['key'],
24
+ post: ['key']
25
+ }
26
+ };
27
+ function text(body, field, required) {
28
+ const value = body[field];
29
+ if (value === undefined && !required)
30
+ return undefined;
31
+ if (typeof value !== 'string' || (required && !value.trim()))
32
+ throw new Error(`Send ${field} as ${required ? 'a non-empty string' : 'a string'}.`);
33
+ if (value.length > TEXT_LIMIT)
34
+ throw new Error(`${field} is longer than ${TEXT_LIMIT} characters.`);
35
+ return value;
36
+ }
37
+ function flag(body, field) {
38
+ const value = body[field];
39
+ if (value === undefined)
40
+ return undefined;
41
+ if (typeof value !== 'boolean')
42
+ throw new Error(`Send ${field} as true or false.`);
43
+ return value;
44
+ }
45
+ function list(body, field, required) {
46
+ const value = body[field];
47
+ if (value === undefined && !required)
48
+ return undefined;
49
+ if (!Array.isArray(value) ||
50
+ value.length > LIST_LIMIT ||
51
+ !value.every((entry) => typeof entry === 'string' && entry && entry.length <= TEXT_LIMIT))
52
+ throw new Error(`Send ${field} as a list of keys.`);
53
+ return value;
54
+ }
55
+ /**
56
+ * The change a request body names, or a refusal saying what to send: an unknown action, kind or
57
+ * field is refused rather than dropped, so a change never does less than it asked.
58
+ */
59
+ export function parseOrgChange(value) {
60
+ if (!isRecord(value))
61
+ throw new Error('Send the change as a JSON object.');
62
+ const { action, kind } = value;
63
+ const only = (fields) => {
64
+ for (const field of Object.keys(value))
65
+ if (!fields.includes(field))
66
+ throw new Error(`${String(action)} ${kind === undefined ? '' : `${String(kind)} `}does not take ${field}.`);
67
+ };
68
+ if (action === 'bind') {
69
+ only(['action', 'slot', 'posts', 'reason']);
70
+ return {
71
+ action,
72
+ slot: text(value, 'slot', true),
73
+ posts: list(value, 'posts', true),
74
+ reason: text(value, 'reason', false) ?? ''
75
+ };
76
+ }
77
+ if (action === 'unbind') {
78
+ only(['action', 'slot']);
79
+ return { action, slot: text(value, 'slot', true) };
80
+ }
81
+ if (action !== 'add' && action !== 'edit' && action !== 'remove')
82
+ throw new Error('Send action as add, edit, remove, bind or unbind.');
83
+ const fields = typeof kind === 'string' && Object.hasOwn(FIELDS[action], kind) ? FIELDS[action][kind] : null;
84
+ if (!fields)
85
+ throw new Error(`Send kind as one of ${Object.keys(FIELDS[action]).join(', ')}.`);
86
+ only(['action', 'kind', ...fields]);
87
+ const key = text(value, 'key', true);
88
+ if (action === 'remove')
89
+ return { action, kind: kind, key };
90
+ const shared = {
91
+ key,
92
+ ...(value.label !== undefined ? { label: text(value, 'label', false) } : {}),
93
+ ...(value.description !== undefined ? { description: text(value, 'description', false) } : {})
94
+ };
95
+ const parent = value.parent === undefined
96
+ ? {}
97
+ : value.parent === null && action === 'edit'
98
+ ? { parent: null }
99
+ : { parent: text(value, 'parent', true) };
100
+ if (kind === 'team')
101
+ return { action, kind, ...shared, ...parent };
102
+ if (kind === 'job_function') {
103
+ const fills = list(value, 'fills', false);
104
+ const requires_person = flag(value, 'requires_person');
105
+ const escalable = flag(value, 'escalable');
106
+ return {
107
+ action,
108
+ kind,
109
+ ...shared,
110
+ ...parent,
111
+ ...(fills !== undefined ? { fills } : {}),
112
+ ...(requires_person !== undefined ? { requires_person } : {}),
113
+ ...(escalable !== undefined ? { escalable } : {})
114
+ };
115
+ }
116
+ if (kind === 'post')
117
+ return { action: 'add', kind, key, ...(shared.label !== undefined ? { label: shared.label } : {}) };
118
+ return { action, kind: 'slot', ...shared };
119
+ }
120
+ /**
121
+ * Applies one change to the repository's local org, as `actor`, checking the whole org in one
122
+ * transaction (changeLocalOrg, changeLocalBinding). A refusal throws its reason, and nothing changes.
123
+ */
124
+ export async function applyOrgChange(repository, change, options) {
125
+ if (change.action === 'bind' || change.action === 'unbind') {
126
+ return changeLocalBinding(repository, {
127
+ slot: change.slot,
128
+ ...(change.action === 'bind' ? { posts: change.posts, reason: change.reason } : {}),
129
+ actor: options.actor,
130
+ workflow: options.workflow
131
+ });
132
+ }
133
+ const result = await changeLocalOrg(repository, (current, rows) => {
134
+ if (change.action === 'add') {
135
+ const graph = onOrg(current, change.kind === 'team');
136
+ if (change.kind === 'team') {
137
+ const { action: _action, kind: _kind, ...input } = change;
138
+ return { graph: addTeam(graph, input) };
139
+ }
140
+ if (change.kind === 'job_function') {
141
+ const { action: _action, kind: _kind, ...input } = change;
142
+ return { graph: addJobFunction(graph, input) };
143
+ }
144
+ if (change.kind === 'slot') {
145
+ const { action: _action, kind: _kind, ...input } = change;
146
+ return { graph: addSlot(graph, input) };
147
+ }
148
+ return {
149
+ graph: addPost(graph, { name: change.key, ...(change.label !== undefined ? { label: change.label } : {}) })
150
+ };
151
+ }
152
+ const graph = onOrg(current, false);
153
+ if (change.action === 'remove') {
154
+ return {
155
+ graph: change.kind === 'post' ? removePost(graph, change.key, rows) : removeDefinition(graph, change.kind, change.key, rows)
156
+ };
157
+ }
158
+ const { action: _action, kind: _kind, key, ...edit } = change;
159
+ if (change.kind === 'team')
160
+ return { graph: editTeam(graph, key, edit) };
161
+ if (change.kind === 'slot')
162
+ return { graph: editSlot(graph, key, edit) };
163
+ return { graph: editJobFunction(graph, key, edit) };
164
+ },
165
+ // Adding defines something new; only an edit or a removal can break a holder rule.
166
+ change.action === 'add' ? {} : { workflow: options.workflow });
167
+ return { changed: true, root: result.root };
168
+ }
169
+ //# sourceMappingURL=org-change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-change.js","sourceRoot":"","sources":["../../src/local/org-change.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,13 @@
1
1
  /**
2
- * The line `sdlc viewer` prints once it listens. The viewer makes no graph mutation. It writes
2
+ * The line `sdlc viewer` prints once it listens. The viewer makes no project graph mutation. It writes
3
3
  * view state, the pins, named in view_writes when the Threads panel can pin, and coordination
4
4
  * records named in coordination_writes when the engine has them: the user's Done on a task (status
5
5
  * user-done), and the Worktrees page's Merge (promote join main) and Remove (archive.py worktrees
6
- * --apply --only). page says which page answers the url: the React viewer, or the classic page when
7
- * no bundle is built.
6
+ * --apply --only). org_writes names the Org chart's editors (org-change), which write the
7
+ * repository's local org as sdlc org does. page says which page answers the url: the React viewer,
8
+ * or the classic page when no bundle is built.
8
9
  */
9
- export declare function viewerStartLine(url: string, pins: boolean, page?: 'react' | 'classic', userDone?: boolean, worktrees?: boolean): {
10
+ export declare function viewerStartLine(url: string, pins: boolean, page?: 'react' | 'classic', userDone?: boolean, worktrees?: boolean, org?: boolean): {
10
11
  page: "classic";
11
12
  note: string;
12
13
  version: number;
@@ -16,6 +17,7 @@ export declare function viewerStartLine(url: string, pins: boolean, page?: 'reac
16
17
  mutations: string;
17
18
  view_writes: string[];
18
19
  coordination_writes: string[];
20
+ org_writes: string[];
19
21
  } | {
20
22
  page: "react";
21
23
  classic: string;
@@ -26,6 +28,7 @@ export declare function viewerStartLine(url: string, pins: boolean, page?: 'reac
26
28
  mutations: string;
27
29
  view_writes: string[];
28
30
  coordination_writes: string[];
31
+ org_writes: string[];
29
32
  } | {
30
33
  version: number;
31
34
  status: string;
@@ -34,6 +37,7 @@ export declare function viewerStartLine(url: string, pins: boolean, page?: 'reac
34
37
  mutations: string;
35
38
  view_writes: string[];
36
39
  coordination_writes: string[];
40
+ org_writes: string[];
37
41
  };
38
42
  export declare function isLocalWorkspaceCommand(command: string | undefined, subcommand?: string): command is 'workspace' | 'topology' | 'integrate' | 'handoff' | 'resolver' | 'portable' | 'branch' | 'merge' | 'viewer' | 'variants' | 'remote';
39
43
  type LocalWorkspaceCommandInput = {
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-cli.d.ts","sourceRoot":"","sources":["../../src/local/workspace-cli.ts"],"names":[],"mappings":"AAiOA;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,EACb,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,EAC1B,QAAQ,UAAQ,EAChB,SAAS,UAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBlB;AAyDD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,IACN,WAAW,GACX,UAAU,GACV,WAAW,GACX,SAAS,GACT,UAAU,GACV,UAAU,GACV,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,CAoBX;AAED,KAAK,0BAA0B,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAu3CF,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAiKf"}
1
+ {"version":3,"file":"workspace-cli.d.ts","sourceRoot":"","sources":["../../src/local/workspace-cli.ts"],"names":[],"mappings":"AAiOA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,EACb,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,EAC1B,QAAQ,UAAQ,EAChB,SAAS,UAAQ,EACjB,GAAG,UAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBZ;AAyDD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,IACN,WAAW,GACX,UAAU,GACV,WAAW,GACX,SAAS,GACT,UAAU,GACV,UAAU,GACV,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,CAoBX;AAED,KAAK,0BAA0B,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAu3CF,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAqKf"}
@@ -141,14 +141,15 @@ function printJson(value) {
141
141
  console.log(JSON.stringify(value, null, 2));
142
142
  }
143
143
  /**
144
- * The line `sdlc viewer` prints once it listens. The viewer makes no graph mutation. It writes
144
+ * The line `sdlc viewer` prints once it listens. The viewer makes no project graph mutation. It writes
145
145
  * view state, the pins, named in view_writes when the Threads panel can pin, and coordination
146
146
  * records named in coordination_writes when the engine has them: the user's Done on a task (status
147
147
  * user-done), and the Worktrees page's Merge (promote join main) and Remove (archive.py worktrees
148
- * --apply --only). page says which page answers the url: the React viewer, or the classic page when
149
- * no bundle is built.
148
+ * --apply --only). org_writes names the Org chart's editors (org-change), which write the
149
+ * repository's local org as sdlc org does. page says which page answers the url: the React viewer,
150
+ * or the classic page when no bundle is built.
150
151
  */
151
- export function viewerStartLine(url, pins, page, userDone = false, worktrees = false) {
152
+ export function viewerStartLine(url, pins, page, userDone = false, worktrees = false, org = false) {
152
153
  return {
153
154
  version: 1,
154
155
  status: 'listening',
@@ -160,6 +161,7 @@ export function viewerStartLine(url, pins, page, userDone = false, worktrees = f
160
161
  ...(userDone ? ['user-done'] : []),
161
162
  ...(worktrees ? ['worktree-merge', 'worktree-remove'] : [])
162
163
  ],
164
+ org_writes: org ? ['org-change'] : [],
163
165
  ...(page === 'classic'
164
166
  ? {
165
167
  page,
@@ -1535,9 +1537,11 @@ export async function runLocalWorkspaceCommand(input) {
1535
1537
  releaseLinks,
1536
1538
  queues,
1537
1539
  app,
1538
- worktrees: worktrees?.current ? worktrees : undefined
1540
+ worktrees: worktrees?.current ? worktrees : undefined,
1541
+ // The Org chart page's editors write the repository's local org, as sdlc org does.
1542
+ orgChange: async (body) => (await import('./app-org-reader.js')).appOrgChanger({ cwd: process.cwd() })(body)
1539
1543
  });
1540
- printJson(viewerStartLine(viewer.url, Boolean(pin), viewer.page, Boolean(taskDone), Boolean(worktrees?.current)));
1544
+ printJson(viewerStartLine(viewer.url, Boolean(pin), viewer.page, Boolean(taskDone), Boolean(worktrees?.current), true));
1541
1545
  const stop = () => void viewer.close();
1542
1546
  process.once('SIGINT', stop);
1543
1547
  process.once('SIGTERM', stop);