@aemonge-dev/pi-stardeck 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/demo/pi-stardeck.tape +6 -3
- package/docs/architecture.md +2 -1
- package/package.json +2 -3
- package/packages/pi-stardeck/index.ts +0 -10
- package/packages/pi-stardeck/src/deck.ts +30 -52
- package/packages/pi-stardeck/src/title-state.ts +63 -136
- package/packages/status/README.md +20 -34
- package/packages/status/index.ts +28 -143
- package/packages/status/src/active-work.ts +16 -109
- package/packages/status/src/config.ts +1 -3
- package/packages/status/src/ledger.ts +1 -7
- package/packages/status/src/openspec.ts +25 -17
- package/packages/status/src/publisher.ts +30 -91
- package/packages/status/src/reducer.ts +2 -36
- package/packages/status/src/room-aim.ts +151 -0
- package/packages/status/src/title-state.ts +43 -135
- package/packages/status/src/types.ts +7 -8
- package/src/index.ts +0 -2
- package/packages/pi-stardeck/src/activity-age.ts +0 -184
- package/packages/work-state/README.md +0 -33
- package/packages/work-state/index.ts +0 -160
- package/packages/work-state/package.json +0 -33
- package/packages/work-state/src/focus.ts +0 -100
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "work-state",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"description": "OpenSpec focus entry owner for the pi-stardeck cockpit",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"keywords": [
|
|
8
|
-
"pi-package",
|
|
9
|
-
"pi-extension",
|
|
10
|
-
"work-state",
|
|
11
|
-
"openspec"
|
|
12
|
-
],
|
|
13
|
-
"engines": {
|
|
14
|
-
"node": ">=22.19.0"
|
|
15
|
-
},
|
|
16
|
-
"scripts": {
|
|
17
|
-
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,mjs,cjs,mts,cts}\" --ignore-path .prettierignore",
|
|
18
|
-
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,mjs,cjs,mts,cts}\" --ignore-path .prettierignore",
|
|
19
|
-
"typecheck": "tsc --noEmit",
|
|
20
|
-
"test": "node --test --experimental-strip-types test/*.test.ts",
|
|
21
|
-
"check": "npm run format:check && npm run typecheck && npm test"
|
|
22
|
-
},
|
|
23
|
-
"pi": {
|
|
24
|
-
"extensions": [
|
|
25
|
-
"./index.ts"
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
"peerDependencies": {
|
|
29
|
-
"@earendil-works/pi-ai": "*",
|
|
30
|
-
"@earendil-works/pi-coding-agent": "*",
|
|
31
|
-
"typebox": "*"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
export const OPEN_SPEC_FOCUS_ENTRY_TYPE = 'galactica-status.openspec-focus.v1';
|
|
2
|
-
|
|
3
|
-
export type TaskOpenSpecFocus = {
|
|
4
|
-
mode: 'task';
|
|
5
|
-
change: string;
|
|
6
|
-
taskId: string;
|
|
7
|
-
awaitingValidation: boolean;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type OpenSpecFocus = { mode: 'none' } | TaskOpenSpecFocus;
|
|
11
|
-
|
|
12
|
-
export const NO_OPEN_SPEC_FOCUS: OpenSpecFocus = { mode: 'none' };
|
|
13
|
-
|
|
14
|
-
const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/gu;
|
|
15
|
-
|
|
16
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
17
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function normalizeTitlePart(value: string): string {
|
|
21
|
-
return value.replace(CONTROL_CHARACTERS, ' ').replace(/\s+/gu, ' ').trim();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function explicitId(value: unknown): string | undefined {
|
|
25
|
-
if (typeof value !== 'string') return undefined;
|
|
26
|
-
const normalized = normalizeTitlePart(value);
|
|
27
|
-
return normalized || undefined;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function taskFocus(
|
|
31
|
-
change: unknown,
|
|
32
|
-
taskId: unknown,
|
|
33
|
-
awaitingValidation?: unknown,
|
|
34
|
-
): TaskOpenSpecFocus | undefined {
|
|
35
|
-
const normalizedChange = explicitId(change);
|
|
36
|
-
const normalizedTaskId = explicitId(taskId);
|
|
37
|
-
if (!normalizedChange || !normalizedTaskId) return undefined;
|
|
38
|
-
return {
|
|
39
|
-
mode: 'task',
|
|
40
|
-
change: normalizedChange,
|
|
41
|
-
taskId: normalizedTaskId,
|
|
42
|
-
awaitingValidation: awaitingValidation === true,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function parseOpenSpecFocus(value: unknown): OpenSpecFocus | undefined {
|
|
47
|
-
if (!isRecord(value)) return undefined;
|
|
48
|
-
if (value.mode === 'none') return NO_OPEN_SPEC_FOCUS;
|
|
49
|
-
if (value.mode !== 'task') return undefined;
|
|
50
|
-
return taskFocus(value.change, value.taskId, value.awaitingValidation);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function restoreOpenSpecFocus(entries: readonly unknown[]): OpenSpecFocus {
|
|
54
|
-
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
55
|
-
const entry = entries[index];
|
|
56
|
-
if (
|
|
57
|
-
!isRecord(entry) ||
|
|
58
|
-
entry.type !== 'custom' ||
|
|
59
|
-
entry.customType !== OPEN_SPEC_FOCUS_ENTRY_TYPE
|
|
60
|
-
) {
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const focus = parseOpenSpecFocus(entry.data);
|
|
64
|
-
if (focus) return focus;
|
|
65
|
-
}
|
|
66
|
-
return NO_OPEN_SPEC_FOCUS;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function taskflowRunFocus(input: unknown): TaskOpenSpecFocus | undefined {
|
|
70
|
-
if (!isRecord(input) || input.action !== 'run' || !isRecord(input.args)) {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
const focus = taskFocus(input.args.change, input.args.task);
|
|
74
|
-
return focus && focus.change !== 'none' && focus.taskId !== 'none'
|
|
75
|
-
? focus
|
|
76
|
-
: undefined;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** Task identity (mode · change · taskId) — the replace-safeguard's
|
|
80
|
-
* question; the validation flag is state, not identity. */
|
|
81
|
-
export function sameTaskFocus(left: OpenSpecFocus, right: OpenSpecFocus): boolean {
|
|
82
|
-
if (left.mode !== right.mode) return false;
|
|
83
|
-
return (
|
|
84
|
-
left.mode === 'none' ||
|
|
85
|
-
(right.mode === 'task' &&
|
|
86
|
-
left.change === right.change &&
|
|
87
|
-
left.taskId === right.taskId)
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function sameOpenSpecFocus(left: OpenSpecFocus, right: OpenSpecFocus): boolean {
|
|
92
|
-
if (left.mode !== right.mode) return false;
|
|
93
|
-
return (
|
|
94
|
-
left.mode === 'none' ||
|
|
95
|
-
(right.mode === 'task' &&
|
|
96
|
-
left.change === right.change &&
|
|
97
|
-
left.taskId === right.taskId &&
|
|
98
|
-
left.awaitingValidation === right.awaitingValidation)
|
|
99
|
-
);
|
|
100
|
-
}
|