@harness-lab/cli 0.2.6 → 0.2.8
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/assets/workshop-bundle/SKILL.md +29 -0
- package/assets/workshop-bundle/bundle-manifest.json +11 -11
- package/assets/workshop-bundle/content/facilitation/master-guide.md +94 -3
- package/assets/workshop-bundle/content/project-briefs/code-review-helper.md +10 -10
- package/assets/workshop-bundle/content/talks/context-is-king.md +35 -3
- package/assets/workshop-bundle/docs/harness-cli-foundation.md +15 -1
- package/assets/workshop-bundle/workshop-blueprint/README.md +3 -2
- package/assets/workshop-bundle/workshop-blueprint/agenda.json +58 -16
- package/assets/workshop-bundle/workshop-blueprint/day-structure.md +28 -3
- package/assets/workshop-bundle/workshop-skill/facilitator.md +88 -0
- package/package.json +1 -1
- package/src/client.js +15 -0
- package/src/run-cli.js +117 -2
|
@@ -215,6 +215,18 @@ This is a facilitator-only command — do not surface to participants.
|
|
|
215
215
|
Show the current instance state, agenda phase, facilitator list, and team count.
|
|
216
216
|
Requires active facilitator session.
|
|
217
217
|
|
|
218
|
+
### `workshop facilitator list-instances`
|
|
219
|
+
|
|
220
|
+
List the facilitator-visible workshop instance registry.
|
|
221
|
+
Prefer invoking `harness workshop list-instances` over raw API scripts or local session-file inspection.
|
|
222
|
+
Use this when the facilitator needs to discover what currently exists on a shared dashboard before choosing an explicit instance for reset, update, or agenda work.
|
|
223
|
+
|
|
224
|
+
### `workshop facilitator show-instance <instance-id>`
|
|
225
|
+
|
|
226
|
+
Inspect one explicit workshop instance.
|
|
227
|
+
Prefer invoking `harness workshop show-instance <instance-id>` over raw API scripts.
|
|
228
|
+
Use this when the facilitator needs the full record for one instance rather than the deployment-default runtime status returned by `workshop facilitator status`.
|
|
229
|
+
|
|
218
230
|
### `workshop facilitator grant <email> <role>`
|
|
219
231
|
|
|
220
232
|
Grant a Neon Auth user access to the current workshop instance.
|
|
@@ -249,6 +261,16 @@ Prefer invoking `harness workshop update-instance` over raw API scripts.
|
|
|
249
261
|
Use this when the facilitator wants to correct or refine date, venue, room, address, or event title without resetting the instance.
|
|
250
262
|
Support `contentLang` changes explicitly so facilitators can choose workshop delivery language per instance without changing admin UI language.
|
|
251
263
|
|
|
264
|
+
Facilitator discovery rule:
|
|
265
|
+
- for routine discovery, use `harness workshop list-instances` and `harness workshop show-instance`
|
|
266
|
+
- do not read local CLI session files or improvise authenticated `node -e` fetch scripts unless you are diagnosing the CLI itself
|
|
267
|
+
|
|
268
|
+
### `workshop facilitator reset-instance <instance-id>`
|
|
269
|
+
|
|
270
|
+
Reset one existing workshop instance from the selected blueprint template. Requires facilitator session.
|
|
271
|
+
Prefer invoking `harness workshop reset-instance` over raw API scripts.
|
|
272
|
+
Use this when the facilitator wants fresh canonical agenda, runner, and presenter content for a live instance and accepts that local runtime state will be reinitialized.
|
|
273
|
+
|
|
252
274
|
### `workshop facilitator remove-instance`
|
|
253
275
|
|
|
254
276
|
Remove a workshop instance from the active list without deleting its archive history. Requires facilitator session.
|
|
@@ -267,6 +289,13 @@ Inspect and edit the local agenda copy for one workshop instance. Requires facil
|
|
|
267
289
|
|
|
268
290
|
Inspect and edit presenter scenes for one workshop instance. This includes listing scenes for an agenda item, creating a new scene, editing content, changing default scene, reordering scenes, and enabling or hiding scenes. Requires facilitator session.
|
|
269
291
|
|
|
292
|
+
Rules for rich scenes:
|
|
293
|
+
- keep scenes agenda-linked and room-facing rather than inventing a freeform slide deck
|
|
294
|
+
- prefer one dominant voice per scene and one main idea per scene
|
|
295
|
+
- use reviewed local blueprint assets for reusable visuals instead of ad hoc remote image URLs
|
|
296
|
+
- treat runtime scene edits as instance-local until a maintainer deliberately publishes them back into the repo
|
|
297
|
+
- when richer scene authoring or promotion is involved, follow `docs/presenter-rich-scene-authoring.md`
|
|
298
|
+
|
|
270
299
|
### `workshop facilitator archive`
|
|
271
300
|
|
|
272
301
|
Archive the current workshop instance with optional notes.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": 1,
|
|
3
3
|
"bundleName": "harness-lab-workshop",
|
|
4
|
-
"bundleVersion": "0.2.
|
|
5
|
-
"contentHash": "
|
|
4
|
+
"bundleVersion": "0.2.8",
|
|
5
|
+
"contentHash": "6194a59089ff94131b647282c1b5e7574a6a9d112c48b4b9d58b600f5775736a",
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"path": "content/challenge-cards/.gitkeep",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"path": "content/facilitation/master-guide.md",
|
|
37
|
-
"sha256": "
|
|
37
|
+
"sha256": "f0edc5eef8c7bc0efc67672e184edecce46fa5fd5e9820cfda0b28fbb8cb1a8f"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "content/project-briefs/.gitkeep",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"path": "content/project-briefs/code-review-helper.md",
|
|
45
|
-
"sha256": "
|
|
45
|
+
"sha256": "3e174ff0d097fe132088774042f9db58c9c2494613d66950bdd423116bd7986d"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"path": "content/project-briefs/devtoolbox-cli.md",
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"path": "content/talks/context-is-king.md",
|
|
101
|
-
"sha256": "
|
|
101
|
+
"sha256": "4d0972fefac067de0b8803698b44bdf8ab0bee64b181d50d1ac5e26a92eb7089"
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
"path": "docs/harness-cli-foundation.md",
|
|
105
|
-
"sha256": "
|
|
105
|
+
"sha256": "f3b6125a4575c27dcb7b88474003f2a9b189a4b1b25bfaa462861571b69f7a51"
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"path": "docs/learner-reference-gallery.md",
|
|
@@ -134,11 +134,11 @@
|
|
|
134
134
|
},
|
|
135
135
|
{
|
|
136
136
|
"path": "SKILL.md",
|
|
137
|
-
"sha256": "
|
|
137
|
+
"sha256": "de24b73c431855143630f6d312d9bb2af0a16178c2c70f928c5c3a426e569777"
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"path": "workshop-blueprint/agenda.json",
|
|
141
|
-
"sha256": "
|
|
141
|
+
"sha256": "91b4037578ce61d172e09941089b97180322552cb42bb52de87b3956e60b1ed0"
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
"path": "workshop-blueprint/control-surfaces.md",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
},
|
|
147
147
|
{
|
|
148
148
|
"path": "workshop-blueprint/day-structure.md",
|
|
149
|
-
"sha256": "
|
|
149
|
+
"sha256": "ffecae258211cef2430112ca25e1ff59658cac729ea2a07b9cac48e9a2a6244e"
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
"path": "workshop-blueprint/edit-boundaries.md",
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
"path": "workshop-blueprint/README.md",
|
|
161
|
-
"sha256": "
|
|
161
|
+
"sha256": "badb477ecfef7df163ec41c72c39e04bcde2a5a723c1b01bf2e91ed38924e903"
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
164
|
"path": "workshop-blueprint/teaching-spine.md",
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
},
|
|
183
183
|
{
|
|
184
184
|
"path": "workshop-skill/facilitator.md",
|
|
185
|
-
"sha256": "
|
|
185
|
+
"sha256": "f0e977df5979d0d218eabad026b66ecefa90802c71dc8a9468959334570f1c1c"
|
|
186
186
|
},
|
|
187
187
|
{
|
|
188
188
|
"path": "workshop-skill/follow-up-package.md",
|
|
@@ -4,19 +4,55 @@
|
|
|
4
4
|
|
|
5
5
|
### Cíl
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Spustit den jako room-facing launch pro celý workshop, ne jako provozní brief k dopoledni.
|
|
8
8
|
|
|
9
9
|
### Klíčová message
|
|
10
10
|
|
|
11
|
-
> „Dnes nejde o to být nejrychlejší. Jde o to
|
|
11
|
+
> „Dnes nejde o to být nejrychlejší. Jde o to postavit práci tak, aby ji cizí tým dokázal převzít a posunout dál.“
|
|
12
12
|
|
|
13
13
|
### Co potřebuje zaznít
|
|
14
14
|
|
|
15
|
-
-
|
|
15
|
+
- Nezačínáme tool demo ani soutěž v promptování.
|
|
16
|
+
- Budeme se učit, stavět, předávat i přebírat. Ten oblouk dne je záměr workshopu.
|
|
16
17
|
- Jde o práci s agentem tak, aby po vás zůstával použitelný kontext.
|
|
17
18
|
- Odpolední část prověří, jestli repo opravdu unese převzetí dalším týmem.
|
|
18
19
|
- Pokud nějaké důležité pravidlo žije jen v hovoru u stolu, ještě neexistuje.
|
|
19
20
|
|
|
21
|
+
### Doporučený sled beatů
|
|
22
|
+
|
|
23
|
+
1. day-opening promise
|
|
24
|
+
2. proč na tom záleží právě teď
|
|
25
|
+
3. analogie typu Lego duck: stejné ingredience, různé použitelné výsledky
|
|
26
|
+
4. krátká pohybová aktivace podle zkušenosti s AI agenty
|
|
27
|
+
5. první pracovní kontrakt pro Build fázi 1
|
|
28
|
+
|
|
29
|
+
### Lego-duck analogie
|
|
30
|
+
|
|
31
|
+
Použijte ji krátce a věcně.
|
|
32
|
+
|
|
33
|
+
Pointa:
|
|
34
|
+
|
|
35
|
+
- stejný agent neznamená stejný výsledek
|
|
36
|
+
- kvalitu neurčuje samotný model
|
|
37
|
+
- kontext, mantinely a ověřování jsou součást výsledku
|
|
38
|
+
|
|
39
|
+
Nevést jako zábavnou odbočku. Vést jako vysvětlení, proč je harness engineering tvůrčí a inženýrská disciplína zároveň.
|
|
40
|
+
|
|
41
|
+
### Pohybová aktivace
|
|
42
|
+
|
|
43
|
+
Použijte krátké rozdělení místnosti podle aktuální zkušenosti s AI agenty:
|
|
44
|
+
|
|
45
|
+
- používám skoro denně
|
|
46
|
+
- používám, ale opatrně
|
|
47
|
+
- jsem spíš na startu
|
|
48
|
+
- jsem skeptický, ale chci důkaz
|
|
49
|
+
|
|
50
|
+
Pravidla:
|
|
51
|
+
|
|
52
|
+
- ne dělat z toho networking kolo
|
|
53
|
+
- stačí přesun a 2 krátké hlasy
|
|
54
|
+
- pointa není seniorita, ale kalibrace místnosti a signál, že den je participativní
|
|
55
|
+
|
|
20
56
|
### Co má facilitátor průběžně vracet
|
|
21
57
|
|
|
22
58
|
- „Kde by to našel další tým bez vás?“
|
|
@@ -24,6 +60,61 @@ Nastavit energii dne a jasně pojmenovat, o čem workshop je.
|
|
|
24
60
|
- „Je `AGENTS.md` mapa, nebo už se z něj stává dump?“
|
|
25
61
|
- „Jaký je další bezpečný krok pro cizího člověka nebo agenta?“
|
|
26
62
|
|
|
63
|
+
### První pracovní kontrakt
|
|
64
|
+
|
|
65
|
+
Po launchi potřebuje místnost ještě jednu konkrétní věc:
|
|
66
|
+
|
|
67
|
+
- co má být po prvním build bloku opravdu vidět
|
|
68
|
+
- co nestačí jen slíbit
|
|
69
|
+
|
|
70
|
+
Do oběda má být vidět:
|
|
71
|
+
|
|
72
|
+
- repo a `README`, které dávají smysl cizímu člověku
|
|
73
|
+
- `AGENTS.md` jako krátká mapa
|
|
74
|
+
- plan nebo jasně vedená implementační stopa
|
|
75
|
+
- první explicitní check před dalším generováním
|
|
76
|
+
|
|
77
|
+
## Context is King talk
|
|
78
|
+
|
|
79
|
+
### Cíl
|
|
80
|
+
|
|
81
|
+
Proměnit energii z openingu v přesnou tezi a čistý most do Build fáze 1.
|
|
82
|
+
|
|
83
|
+
### Klíčová message
|
|
84
|
+
|
|
85
|
+
> „Kontext je páka, ne kosmetika.“
|
|
86
|
+
|
|
87
|
+
### Co potřebuje zaznít
|
|
88
|
+
|
|
89
|
+
- Neučíme se lépe promptovat. Učíme se postavit repo a workflow, ve kterém agent i cizí tým dokážou bezpečně pokračovat.
|
|
90
|
+
- `AGENTS.md`, skills, runbooky a checks jsou týmová infrastruktura, ne polish navíc.
|
|
91
|
+
- Team lead nestojí modelu za zády a nediktuje další větu každých třicet sekund.
|
|
92
|
+
- Po talku se tým vrací k repu s mapou, planem a prvním checkem, ne s lovem na chytřejší prompt.
|
|
93
|
+
|
|
94
|
+
### Mikro-cvičení
|
|
95
|
+
|
|
96
|
+
Použijte stejný malý task ve dvou podmínkách:
|
|
97
|
+
|
|
98
|
+
1. prompt blob
|
|
99
|
+
2. krátké zadání s `Goal`, `Context`, `Constraints`, `Done When`
|
|
100
|
+
|
|
101
|
+
Nenechte to sklouznout do debaty o tom, který model je chytřejší.
|
|
102
|
+
|
|
103
|
+
Pointa:
|
|
104
|
+
|
|
105
|
+
- přenos záměru
|
|
106
|
+
- přenos mantinelů
|
|
107
|
+
- přenos done criteria
|
|
108
|
+
|
|
109
|
+
### Most do Build fáze 1
|
|
110
|
+
|
|
111
|
+
Na konci talku má být jasné:
|
|
112
|
+
|
|
113
|
+
- teorie tím končí
|
|
114
|
+
- tým se vrací k repu
|
|
115
|
+
- nejdřív vzniká mapa a první explicitní check
|
|
116
|
+
- teprve potom dává smysl další feature motion
|
|
117
|
+
|
|
27
118
|
## Build fáze 1
|
|
28
119
|
|
|
29
120
|
### Viditelný milestone board
|
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
## Problém
|
|
4
4
|
|
|
5
|
-
Code review bývá nevyrovnané. Některé změny projdou s dobrým checklistem a jasným popisem rizik, jiné bez společného rámce. Reviewer pak improvizuje, autor neví, co má ověřit předem, a tým ztrácí konzistenci
|
|
5
|
+
Code review bývá nevyrovnané. Některé změny projdou s dobrým checklistem a jasným popisem rizik, jiné bez společného rámce. Reviewer pak improvizuje, autor neví, co má ověřit předem, a tým ztrácí konzistenci právě tam, kde by měl být nejpřesnější.
|
|
6
6
|
|
|
7
|
-
Vaším úkolem je navrhnout nástroj, který z diffu nebo změny vytvoří použitelný review checklist.
|
|
7
|
+
Vaším úkolem je navrhnout nástroj, který z diffu nebo změny vytvoří použitelný review checklist a zároveň jasně oddělí jistotu, heuristiku a místa, kde je pořád potřeba lidský úsudek.
|
|
8
8
|
|
|
9
9
|
## User stories
|
|
10
10
|
|
|
11
|
-
- Jako reviewer chci z diffu rychle získat checklist rizik, otázek a míst, na která se zaměřit.
|
|
12
|
-
- Jako autor změny chci vědět, co mám
|
|
11
|
+
- Jako reviewer chci z diffu rychle získat checklist změněných hranic, rizik, otázek a míst, na která se zaměřit.
|
|
12
|
+
- Jako autor změny chci vědět, co mám ověřit ještě před samotným review.
|
|
13
13
|
- Jako tým po rotaci chci navázat na heuristiky, které původní tým objevil, místo abych je znovu vymýšlel.
|
|
14
14
|
|
|
15
15
|
## Architektonické poznámky
|
|
16
16
|
|
|
17
|
-
- Může jít o CLI, web nebo jednoduchý skript. Důležitý je jasný tok `diff →
|
|
18
|
-
- Musí být zřejmé, jaké vstupy nástroj
|
|
19
|
-
- Přidejte seed diff nebo `examples/`, aby šlo workflow lokálně ověřit.
|
|
20
|
-
-
|
|
17
|
+
- Může jít o CLI, web nebo jednoduchý skript. Důležitý je jasný tok `diff → rubric → checklist`.
|
|
18
|
+
- Musí být zřejmé, jaké vstupy nástroj očekává, co umí označit jistě a co naopak zůstává heuristické.
|
|
19
|
+
- Přidejte seed diff nebo `examples/`, aby šlo workflow lokálně ověřit a další tým rychle přidal nové pravidlo.
|
|
20
|
+
- Nástroj má pomáhat reviewerovi, ne předstírat neomylnost.
|
|
21
21
|
|
|
22
22
|
## Hotovo když
|
|
23
23
|
|
|
24
24
|
- Nástroj vytvoří review checklist ze seed diffu.
|
|
25
|
-
- Výstup odlišuje jistá zjištění od
|
|
25
|
+
- Výstup odlišuje jistá zjištění od doporučení, hypotéz a bodů pro lidský úsudek.
|
|
26
26
|
- Je jasné, jak přidat nové pravidlo nebo heuristiku bez dlouhého onboardingu.
|
|
27
27
|
- Další tým může během několika minut pokračovat v rozvoji bez chaosu.
|
|
28
28
|
|
|
29
29
|
## První krok pro agenta
|
|
30
30
|
|
|
31
|
-
Nezačínej kódem. Nejdřív napiš
|
|
31
|
+
Nezačínej kódem. Nejdřív napiš review rubric, tok vstupů a definici toho, co znamená dobrý checklist. Ukaž, kde je jistota, kde heuristika a co musí posoudit člověk. Teprve potom navrhni první implementační slice.
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# Context is King
|
|
2
2
|
|
|
3
|
-
## Otevírací
|
|
3
|
+
## Otevírací modul
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Tenhle workshop skill i dashboard vznikly stejným způsobem, jakým dnes budeme pracovat my: s AI agentem, ale s důrazem na kontext. Nejde mi o prodej nástroje. Jde mi o to ukázat disciplínu, která z nástroje dělá použitelného spolupracovníka.
|
|
6
|
+
|
|
7
|
+
Rámec pro room launch:
|
|
8
|
+
|
|
9
|
+
- dnes nezačínáme tool demo ani soutěž v promptování
|
|
10
|
+
- budeme se učit, stavět, předávat i přebírat
|
|
11
|
+
- odpoledne se ukáže, co z práce přežije bez nás
|
|
6
12
|
|
|
7
13
|
## Klíčová linka
|
|
8
14
|
|
|
@@ -12,9 +18,26 @@ Moje hlavní věta pro dnešek:
|
|
|
12
18
|
|
|
13
19
|
> Neučíme se "lépe promptovat". Učíme se postavit repo a workflow, ve kterém agent i cizí tým dokážou bezpečně pokračovat.
|
|
14
20
|
|
|
21
|
+
## Analogický beat
|
|
22
|
+
|
|
23
|
+
Když dáte lidem stejné kostky, nevznikne jedna správná kachna. Stejně tak ze stejného modelu nevzniká jedna správná práce. Rozdíl nedělá jen model. Rozdíl dělá kontext, mantinely, ověřování a představivost týmu.
|
|
24
|
+
|
|
25
|
+
Pointa analogie:
|
|
26
|
+
|
|
27
|
+
- stejný agent neznamená stejný výsledek
|
|
28
|
+
- kvalitu neurčuje samotný model
|
|
29
|
+
- pracovní systém kolem agenta je součást výsledku
|
|
30
|
+
|
|
15
31
|
## Mikro-cvičení
|
|
16
32
|
|
|
17
|
-
Všichni dostanou stejný malý
|
|
33
|
+
Všichni dostanou stejný malý task. Jedna varianta bude prompt blob. Druhá varianta bude krátké zadání se 4 prvky a s odkazem na kontext zapsaný v repu. Pak porovnáme výsledky. Nehledáme „nejhezčí prompt“. Hledáme způsob práce, který přenese záměr, omezení a done criteria i do dalšího kroku.
|
|
34
|
+
|
|
35
|
+
4 prvky pro druhou variantu:
|
|
36
|
+
|
|
37
|
+
- Goal
|
|
38
|
+
- Context
|
|
39
|
+
- Constraints
|
|
40
|
+
- Done When
|
|
18
41
|
|
|
19
42
|
## Hlavní teze
|
|
20
43
|
|
|
@@ -37,6 +60,15 @@ Všichni dostanou stejný malý úkol. Jedna varianta bude prompt blob. Druhá v
|
|
|
37
60
|
- Když agent dělá víc, já musím lépe ověřovat.
|
|
38
61
|
- Handoff není závěr dne. Je to průběžná podmínka celé práce.
|
|
39
62
|
|
|
63
|
+
## Most do Build fáze 1
|
|
64
|
+
|
|
65
|
+
Po tomhle talku se tým nemá vracet k repu s pocitem, že potřebuje jen chytřejší prompt. Má se vracet s jedním jasným očekáváním:
|
|
66
|
+
|
|
67
|
+
- nejdřív krátká mapa v repu
|
|
68
|
+
- potom plan
|
|
69
|
+
- potom první explicitní check
|
|
70
|
+
- teprve potom další feature motion
|
|
71
|
+
|
|
40
72
|
## Závěr
|
|
41
73
|
|
|
42
74
|
Odpoledne nezažijete jen to, že „AI někdy funguje a někdy ne“. Zažijete, jak moc výsledek závisí na kvalitě pracovního systému, který kolem agenta postavíte.
|
|
@@ -8,7 +8,7 @@ Current implementation in this repo:
|
|
|
8
8
|
|
|
9
9
|
- lives in the repository `harness-cli/` package and ships publicly as `@harness-lab/cli`
|
|
10
10
|
- distributes a portable participant workshop skill bundle through `harness skill install`
|
|
11
|
-
- covers `auth login/logout/status` plus `workshop status/create-instance/update-instance/prepare/remove-instance/archive/phase set`
|
|
11
|
+
- covers `auth login/logout/status` plus `workshop status/list-instances/show-instance/create-instance/update-instance/reset-instance/prepare/remove-instance/archive/phase set`
|
|
12
12
|
- targets the existing shared dashboard facilitator APIs
|
|
13
13
|
- is tested for browser/device auth, local-dev Basic Auth fallback, and cookie-backed Neon bootstrap fallback
|
|
14
14
|
- stores sessions in a local file under `HARNESS_CLI_HOME` or `~/.harness` by default
|
|
@@ -39,8 +39,11 @@ Required commands:
|
|
|
39
39
|
- `harness auth logout`
|
|
40
40
|
- `harness auth status`
|
|
41
41
|
- `harness workshop status`
|
|
42
|
+
- `harness workshop list-instances`
|
|
43
|
+
- `harness workshop show-instance <instance-id>`
|
|
42
44
|
- `harness workshop create-instance`
|
|
43
45
|
- `harness workshop update-instance`
|
|
46
|
+
- `harness workshop reset-instance <instance-id>`
|
|
44
47
|
- `harness workshop archive`
|
|
45
48
|
- `harness workshop prepare`
|
|
46
49
|
- `harness workshop remove-instance`
|
|
@@ -88,8 +91,13 @@ Current target-selection order:
|
|
|
88
91
|
|
|
89
92
|
Current command posture:
|
|
90
93
|
|
|
94
|
+
- explicit workspace-discovery commands:
|
|
95
|
+
- `harness workshop list-instances`
|
|
96
|
+
- explicit target required:
|
|
97
|
+
- `harness workshop show-instance <instance-id>`
|
|
91
98
|
- explicit target required:
|
|
92
99
|
- `harness workshop update-instance <instance-id>`
|
|
100
|
+
- `harness workshop reset-instance <instance-id>`
|
|
93
101
|
- `harness workshop prepare <instance-id>`
|
|
94
102
|
- `harness workshop remove-instance <instance-id>`
|
|
95
103
|
- explicit target is the created resource:
|
|
@@ -103,6 +111,7 @@ Current discoverability path:
|
|
|
103
111
|
|
|
104
112
|
- facilitators can inspect available workshop instances through the dashboard workspace view
|
|
105
113
|
- the same platform-scoped list lives behind the authenticated instances API surface at `/api/workshop/instances`
|
|
114
|
+
- the CLI should expose that list directly so facilitator skills do not need session-file inspection or raw authenticated scripts for routine discovery
|
|
106
115
|
|
|
107
116
|
For the current facilitator lifecycle slice:
|
|
108
117
|
|
|
@@ -115,6 +124,11 @@ Current step-up posture:
|
|
|
115
124
|
- the existing CLI command set (`workshop status/archive/phase set`) may run on a valid brokered device session
|
|
116
125
|
- future higher-risk commands such as facilitator grant/revoke or destructive instance mutations should require a fresh browser approval window rather than silently reusing an older CLI session
|
|
117
126
|
|
|
127
|
+
Content refresh posture:
|
|
128
|
+
|
|
129
|
+
- after changing authored participant-facing sources in `workshop-skill/`, `content/`, or `workshop-blueprint/`, refresh the portable bundle and verify it before shipping facilitator or participant guidance
|
|
130
|
+
- when those changes must land in already-created workshop instances, `workshop reset-instance` is the intended re-import path
|
|
131
|
+
|
|
118
132
|
## Session Storage Posture
|
|
119
133
|
|
|
120
134
|
Default storage backend:
|
|
@@ -39,7 +39,7 @@ Do not use this folder for live event state. Real dates, rooms, rosters, checkpo
|
|
|
39
39
|
### Structured data
|
|
40
40
|
|
|
41
41
|
- [`agenda.json`](agenda.json)
|
|
42
|
-
Public-readable workshop
|
|
42
|
+
Public-readable 10-phase mirror of the workshop day and workshop metadata.
|
|
43
43
|
|
|
44
44
|
## Related Runtime Documents
|
|
45
45
|
|
|
@@ -51,5 +51,6 @@ For maintainers working in the source repository, the runtime-facing structured
|
|
|
51
51
|
|
|
52
52
|
- `docs/workshop-content-language-architecture.md`
|
|
53
53
|
- `dashboard/lib/workshop-blueprint-agenda.json`
|
|
54
|
+
- `dashboard/lib/workshop-blueprint-localized-content.ts`
|
|
54
55
|
|
|
55
|
-
Treat those as maintainer/source-repo references, not as portable participant-bundle docs.
|
|
56
|
+
Treat those as maintainer/source-repo references, not as portable participant-bundle docs. The public `agenda.json` file should stay aligned with the same phase structure, but it is not the runtime import source.
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
2
|
+
"version": 2,
|
|
3
3
|
"blueprintId": "harness-lab-core-day",
|
|
4
4
|
"title": "Harness Lab",
|
|
5
|
-
"subtitle": "
|
|
5
|
+
"subtitle": "Public-readable 10-phase mirror of the Harness Lab workshop day",
|
|
6
|
+
"presentationMode": "public-readable-mirror",
|
|
7
|
+
"sourceNote": "Runtime imports come from dashboard/lib/workshop-blueprint-agenda.json plus dashboard/lib/workshop-blueprint-localized-content.ts.",
|
|
6
8
|
"principles": [
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
9
|
+
"Context before generation",
|
|
10
|
+
"Verification is the trust boundary",
|
|
11
|
+
"Work so another team can continue"
|
|
10
12
|
],
|
|
11
13
|
"phases": [
|
|
12
14
|
{
|
|
13
15
|
"id": "opening",
|
|
14
16
|
"order": 1,
|
|
15
|
-
"label": "
|
|
17
|
+
"label": "Opening and framing",
|
|
16
18
|
"startTime": "09:10",
|
|
17
19
|
"kind": "shared",
|
|
18
|
-
"goal": "
|
|
20
|
+
"goal": "Shift the room from prompt-hackathon expectations to continuation-quality discipline."
|
|
19
21
|
},
|
|
20
22
|
{
|
|
21
23
|
"id": "talk",
|
|
@@ -23,31 +25,71 @@
|
|
|
23
25
|
"label": "Context is King",
|
|
24
26
|
"startTime": "09:40",
|
|
25
27
|
"kind": "shared",
|
|
26
|
-
"goal": "
|
|
28
|
+
"goal": "Turn context into a precise thesis: AGENTS.md, plans, and checks are working infrastructure, not polish."
|
|
27
29
|
},
|
|
28
30
|
{
|
|
29
|
-
"id": "
|
|
31
|
+
"id": "demo",
|
|
30
32
|
"order": 3,
|
|
33
|
+
"label": "Demo",
|
|
34
|
+
"startTime": "10:05",
|
|
35
|
+
"kind": "shared",
|
|
36
|
+
"goal": "Show one compact workflow story: context, planning, implementation, review, and safe fallback moves."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "build-1",
|
|
40
|
+
"order": 4,
|
|
31
41
|
"label": "Build Phase 1",
|
|
32
42
|
"startTime": "10:30",
|
|
33
43
|
"kind": "team",
|
|
34
|
-
"goal": "
|
|
44
|
+
"goal": "Before lunch, get every team to a navigable repo, AGENTS.md, a plan, one explicit check, and a first reviewed slice."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "intermezzo-1",
|
|
48
|
+
"order": 5,
|
|
49
|
+
"label": "Intermezzo 1",
|
|
50
|
+
"startTime": "11:40",
|
|
51
|
+
"kind": "shared",
|
|
52
|
+
"goal": "Surface one change, one proof, and one next move from the room before lunch momentum slips."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "lunch-reset",
|
|
56
|
+
"order": 6,
|
|
57
|
+
"label": "Lunch Reset",
|
|
58
|
+
"startTime": "12:15",
|
|
59
|
+
"kind": "shared",
|
|
60
|
+
"goal": "Frame lunch as a handoff preparation point, not as a pause between unrelated workshop blocks."
|
|
35
61
|
},
|
|
36
62
|
{
|
|
37
63
|
"id": "rotation",
|
|
38
|
-
"order":
|
|
39
|
-
"label": "
|
|
64
|
+
"order": 7,
|
|
65
|
+
"label": "Continuation Shift",
|
|
40
66
|
"startTime": "13:30",
|
|
41
67
|
"kind": "team",
|
|
42
|
-
"goal": "
|
|
68
|
+
"goal": "Force silent repo reading, diagnosis, and explicit continuation before anyone edits code."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "build-2",
|
|
72
|
+
"order": 8,
|
|
73
|
+
"label": "Build Phase 2",
|
|
74
|
+
"startTime": "14:05",
|
|
75
|
+
"kind": "team",
|
|
76
|
+
"goal": "Turn continuation friction into better repo guidance, stronger checks, and clearer next moves."
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "intermezzo-2",
|
|
80
|
+
"order": 9,
|
|
81
|
+
"label": "Intermezzo 2",
|
|
82
|
+
"startTime": "15:05",
|
|
83
|
+
"kind": "shared",
|
|
84
|
+
"goal": "Name which repo signals actually saved time during continuation and which failures repeated."
|
|
43
85
|
},
|
|
44
86
|
{
|
|
45
87
|
"id": "reveal",
|
|
46
|
-
"order":
|
|
47
|
-
"label": "Reveal
|
|
88
|
+
"order": 10,
|
|
89
|
+
"label": "Reveal and reflection",
|
|
48
90
|
"startTime": "15:45",
|
|
49
91
|
"kind": "shared",
|
|
50
|
-
"goal": "
|
|
92
|
+
"goal": "Turn the day into reusable practice: what helped continuation, what failed, and what should change next week."
|
|
51
93
|
}
|
|
52
94
|
],
|
|
53
95
|
"runtimeImport": {
|
|
@@ -103,6 +103,31 @@ Habit installed:
|
|
|
103
103
|
- cleanup and codification are part of delivery
|
|
104
104
|
- repeated pain should become a better template, check, or runbook
|
|
105
105
|
|
|
106
|
+
## Narrative Spine
|
|
107
|
+
|
|
108
|
+
The day should not feel like separate agenda cards. Each phase should change what the room now understands and what it is ready to do next.
|
|
109
|
+
|
|
110
|
+
- `opening`:
|
|
111
|
+
Shift the room from "AI hackathon energy" to "continuation-quality discipline." The key belief is that handoff without verbal rescue is part of the assignment from the first hour.
|
|
112
|
+
- `talk`:
|
|
113
|
+
Shift the room from a vague sense that context matters to a precise thesis: harness engineering is team infrastructure, not prompt cosmetics.
|
|
114
|
+
- `demo`:
|
|
115
|
+
Shift the room from abstract agreement to an observable workflow. The room should see context, plan, implementation, and review as one repeatable system.
|
|
116
|
+
- `build-1`:
|
|
117
|
+
Shift teams from listening to evidence. Before lunch, the repo needs to show map, plan, one executable check, and one verified step.
|
|
118
|
+
- `intermezzo-1`:
|
|
119
|
+
Shift from isolated table work to shared learning. The room should hear concrete repo signals, not generic progress reporting.
|
|
120
|
+
- `lunch-reset`:
|
|
121
|
+
Shift from local progress to handoff readiness. Going to lunch without a readable next safe step should feel unfinished.
|
|
122
|
+
- `rotation`:
|
|
123
|
+
Shift from authorship to inheritance. The receiving team must read first, diagnose second, and edit only after it can explain the state.
|
|
124
|
+
- `build-2`:
|
|
125
|
+
Shift from frustration to codification. Weak continuation signals should turn into clearer repo guidance, stronger checks, and better runbooks.
|
|
126
|
+
- `intermezzo-2`:
|
|
127
|
+
Shift from anecdotes about the afternoon to concrete continuation evidence. The room should identify which repo signals actually saved time.
|
|
128
|
+
- `reveal`:
|
|
129
|
+
Shift from reflection to adoption. The close should turn signals from the day into next-week practice and into improvements to the reusable workshop blueprint.
|
|
130
|
+
|
|
106
131
|
## What Must Survive In The Repo
|
|
107
132
|
|
|
108
133
|
- goal and constraints
|
|
@@ -122,8 +147,8 @@ Habit installed:
|
|
|
122
147
|
- `AGENTS.md` as a table of contents that points to deeper sources of truth
|
|
123
148
|
- small, continuous garbage collection before bad patterns spread
|
|
124
149
|
|
|
125
|
-
##
|
|
150
|
+
## Agenda Mirror
|
|
126
151
|
|
|
127
|
-
The
|
|
152
|
+
The public-readable 10-phase mirror lives in [`agenda.json`](agenda.json).
|
|
128
153
|
|
|
129
|
-
Runtime workshop instances import from
|
|
154
|
+
Runtime workshop instances import from the maintained dashboard blueprint source pair and then track live phase position, reveal state, teams, and checkpoints locally in the private runtime layer.
|
|
@@ -65,6 +65,59 @@ Show:
|
|
|
65
65
|
- facilitator list with roles
|
|
66
66
|
- team count
|
|
67
67
|
|
|
68
|
+
Use this for the current default or selected workshop context.
|
|
69
|
+
If the facilitator needs the full workspace registry first, use `list-instances` instead of probing local session files or writing raw authenticated fetch scripts.
|
|
70
|
+
|
|
71
|
+
### `/workshop facilitator list-instances`
|
|
72
|
+
|
|
73
|
+
Preferred path:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
harness workshop list-instances
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Show:
|
|
80
|
+
- facilitator-visible instance ids
|
|
81
|
+
- template id
|
|
82
|
+
- status
|
|
83
|
+
- content language
|
|
84
|
+
- event title and room metadata when present
|
|
85
|
+
|
|
86
|
+
Raw API reference:
|
|
87
|
+
|
|
88
|
+
```http
|
|
89
|
+
GET {DASHBOARD_URL}/api/workshop/instances
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Rules:
|
|
93
|
+
- prefer this over inspecting local session files or composing one-off authenticated scripts
|
|
94
|
+
- use it when the facilitator needs to discover which live instances exist before reset, update, or scene work
|
|
95
|
+
- keep raw API usage as a diagnostic fallback, not the default operator workflow
|
|
96
|
+
|
|
97
|
+
### `/workshop facilitator show-instance <instance-id>`
|
|
98
|
+
|
|
99
|
+
Preferred path:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
harness workshop show-instance sample-workshop-demo-orbit
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Show:
|
|
106
|
+
- one explicit instance record
|
|
107
|
+
- summary metadata for quick operator inspection
|
|
108
|
+
- the full instance payload when the facilitator needs exact values before a mutation
|
|
109
|
+
|
|
110
|
+
Raw API reference:
|
|
111
|
+
|
|
112
|
+
```http
|
|
113
|
+
GET {DASHBOARD_URL}/api/workshop/instances/{instanceId}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Rules:
|
|
117
|
+
- use this when the facilitator needs one specific instance, not the deployment-default `workshop status`
|
|
118
|
+
- if the route returns `404`, the instance does not exist or is not visible to the facilitator
|
|
119
|
+
- prefer this over ad hoc authenticated scripts for routine discovery
|
|
120
|
+
|
|
68
121
|
### `/workshop facilitator grant <email> <role>`
|
|
69
122
|
|
|
70
123
|
Use the CLI-backed privileged request path. The skill should not handle auth bootstrap itself.
|
|
@@ -176,6 +229,33 @@ Rules:
|
|
|
176
229
|
- send only the fields you want to change
|
|
177
230
|
- do not use reset for an ordinary title, venue, or room correction
|
|
178
231
|
- if the route returns `400`, the payload is wrong; if it returns `404`, the instance does not exist
|
|
232
|
+
- use `--content-lang cs|en` when the facilitator intends to change the workshop delivery language for that instance
|
|
233
|
+
|
|
234
|
+
### `/workshop facilitator reset-instance <instance-id>`
|
|
235
|
+
|
|
236
|
+
Preferred path:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
harness workshop reset-instance sample-workshop-demo-orbit --template-id blueprint-default
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Raw API reference:
|
|
243
|
+
|
|
244
|
+
```http
|
|
245
|
+
PATCH {DASHBOARD_URL}/api/workshop/instances/{instanceId}
|
|
246
|
+
Content-Type: application/json
|
|
247
|
+
|
|
248
|
+
{
|
|
249
|
+
"action": "reset",
|
|
250
|
+
"templateId": "blueprint-default"
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Rules:
|
|
255
|
+
- use this when the goal is to re-import fresh blueprint-owned workshop content into an existing instance
|
|
256
|
+
- warn that reset archives current runtime state first and then clears live runtime state for the instance
|
|
257
|
+
- prefer `update-instance` for ordinary metadata corrections; reset is the high-impact operation
|
|
258
|
+
- if the facilitator does not specify a template, keep the current template unless there is a clear reason to switch
|
|
179
259
|
|
|
180
260
|
### `/workshop facilitator prepare`
|
|
181
261
|
|
|
@@ -291,6 +371,14 @@ Presenter scenes are agenda-linked, room-facing outputs for the facilitator and
|
|
|
291
371
|
- delete a local scene
|
|
292
372
|
- read and optionally edit `facilitatorNotes`, `sourceRefs`, and `blocks`
|
|
293
373
|
|
|
374
|
+
Rich-scene rules:
|
|
375
|
+
|
|
376
|
+
- keep presenter scenes agenda-linked; do not invent a separate slide-deck source of truth
|
|
377
|
+
- prefer one dominant voice and one main idea per scene
|
|
378
|
+
- for reusable visuals, prefer reviewed local blueprint assets and metadata over ad hoc remote image URLs
|
|
379
|
+
- runtime edits remain instance-local until a maintainer deliberately publishes them back into the repo
|
|
380
|
+
- when working in the source repo, use the maintainer playbook in `docs/presenter-rich-scene-authoring.md` for drafting, refinement, and publish-back
|
|
381
|
+
|
|
294
382
|
Per-instance route:
|
|
295
383
|
|
|
296
384
|
```http
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -90,6 +90,12 @@ export function createHarnessClient({ fetchFn, session }) {
|
|
|
90
90
|
getWorkshopStatus() {
|
|
91
91
|
return request("/api/workshop");
|
|
92
92
|
},
|
|
93
|
+
listWorkshopInstances() {
|
|
94
|
+
return request("/api/workshop/instances");
|
|
95
|
+
},
|
|
96
|
+
getWorkshopInstance(instanceId) {
|
|
97
|
+
return request(`/api/workshop/instances/${encodeURIComponent(instanceId)}`);
|
|
98
|
+
},
|
|
93
99
|
getAgenda() {
|
|
94
100
|
return request("/api/agenda");
|
|
95
101
|
},
|
|
@@ -108,6 +114,15 @@ export function createHarnessClient({ fetchFn, session }) {
|
|
|
108
114
|
body: { action: "update_metadata", ...input },
|
|
109
115
|
});
|
|
110
116
|
},
|
|
117
|
+
resetWorkshopInstance(instanceId, templateId) {
|
|
118
|
+
return request(`/api/workshop/instances/${encodeURIComponent(instanceId)}`, {
|
|
119
|
+
method: "PATCH",
|
|
120
|
+
body: {
|
|
121
|
+
action: "reset",
|
|
122
|
+
...(templateId ? { templateId } : {}),
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
},
|
|
111
126
|
prepareWorkshopInstance(instanceId) {
|
|
112
127
|
return request("/api/workshop", {
|
|
113
128
|
method: "POST",
|
package/src/run-cli.js
CHANGED
|
@@ -103,6 +103,7 @@ async function readRequiredCommandValue(io, flags, keys, promptLabel, fallbackVa
|
|
|
103
103
|
|
|
104
104
|
function buildWorkshopMetadataInput(flags) {
|
|
105
105
|
const input = {
|
|
106
|
+
contentLang: readStringFlag(flags, "content-lang", "content-language"),
|
|
106
107
|
eventTitle: readStringFlag(flags, "event-title", "title"),
|
|
107
108
|
city: readStringFlag(flags, "city"),
|
|
108
109
|
dateRange: readStringFlag(flags, "date-range", "date"),
|
|
@@ -122,6 +123,7 @@ function hasWorkshopMetadataInput(input) {
|
|
|
122
123
|
|
|
123
124
|
async function promptWorkshopMetadataInput(io) {
|
|
124
125
|
const prompts = [
|
|
126
|
+
["contentLang", "Content language (cs/en, leave blank to skip): "],
|
|
125
127
|
["eventTitle", "Event title (leave blank to skip): "],
|
|
126
128
|
["city", "City (leave blank to skip): "],
|
|
127
129
|
["dateRange", "Date range (leave blank to skip): "],
|
|
@@ -148,7 +150,9 @@ function summarizeWorkshopInstance(instance) {
|
|
|
148
150
|
|
|
149
151
|
return {
|
|
150
152
|
instanceId: instance?.id ?? null,
|
|
153
|
+
templateId: instance?.templateId ?? null,
|
|
151
154
|
status: instance?.status ?? null,
|
|
155
|
+
contentLang: workshopMeta.contentLang ?? null,
|
|
152
156
|
eventTitle: workshopMeta.eventTitle ?? null,
|
|
153
157
|
city: workshopMeta.city ?? null,
|
|
154
158
|
dateRange: workshopMeta.dateRange ?? null,
|
|
@@ -175,9 +179,12 @@ function printUsage(io, ui) {
|
|
|
175
179
|
"harness auth status",
|
|
176
180
|
"harness skill install [--target PATH] [--force]",
|
|
177
181
|
"harness workshop status",
|
|
182
|
+
"harness workshop list-instances",
|
|
183
|
+
"harness workshop show-instance <instance-id>",
|
|
178
184
|
"harness workshop archive [--notes TEXT]",
|
|
179
|
-
"harness workshop create-instance [<instance-id>] [--template-id ID] [--event-title TEXT] [--city CITY]",
|
|
180
|
-
"harness workshop update-instance <instance-id> [--event-title TEXT] [--city CITY]",
|
|
185
|
+
"harness workshop create-instance [<instance-id>] [--template-id ID] [--content-lang cs|en] [--event-title TEXT] [--city CITY]",
|
|
186
|
+
"harness workshop update-instance <instance-id> [--content-lang cs|en] [--event-title TEXT] [--city CITY]",
|
|
187
|
+
"harness workshop reset-instance <instance-id> [--template-id ID]",
|
|
181
188
|
"harness workshop prepare <instance-id>",
|
|
182
189
|
"harness workshop remove-instance <instance-id>",
|
|
183
190
|
"harness workshop phase set <phase-id>",
|
|
@@ -582,6 +589,67 @@ async function handleWorkshopStatus(io, ui, env, deps) {
|
|
|
582
589
|
}
|
|
583
590
|
}
|
|
584
591
|
|
|
592
|
+
async function handleWorkshopListInstances(io, ui, env, deps) {
|
|
593
|
+
const session = await requireSession(io, ui, env);
|
|
594
|
+
if (!session) {
|
|
595
|
+
return 1;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
try {
|
|
599
|
+
const client = createHarnessClient({ fetchFn: deps.fetchFn, session });
|
|
600
|
+
const result = await client.listWorkshopInstances();
|
|
601
|
+
const items = Array.isArray(result?.items) ? result.items.map((instance) => summarizeWorkshopInstance(instance)) : [];
|
|
602
|
+
ui.json("Workshop Instances", {
|
|
603
|
+
ok: true,
|
|
604
|
+
count: items.length,
|
|
605
|
+
items,
|
|
606
|
+
});
|
|
607
|
+
return 0;
|
|
608
|
+
} catch (error) {
|
|
609
|
+
if (error instanceof HarnessApiError) {
|
|
610
|
+
ui.status("error", `List instances failed: ${error.message}`, { stream: "stderr" });
|
|
611
|
+
return 1;
|
|
612
|
+
}
|
|
613
|
+
throw error;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async function handleWorkshopShowInstance(io, ui, env, positionals, flags, deps) {
|
|
618
|
+
const session = await requireSession(io, ui, env);
|
|
619
|
+
if (!session) {
|
|
620
|
+
return 1;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const instanceId = await readRequiredCommandValue(
|
|
624
|
+
io,
|
|
625
|
+
flags,
|
|
626
|
+
["id", "instance-id"],
|
|
627
|
+
"Instance id: ",
|
|
628
|
+
readOptionalPositional(positionals, 2),
|
|
629
|
+
);
|
|
630
|
+
if (!instanceId) {
|
|
631
|
+
ui.status("error", "Instance id is required.", { stream: "stderr" });
|
|
632
|
+
return 1;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
try {
|
|
636
|
+
const client = createHarnessClient({ fetchFn: deps.fetchFn, session });
|
|
637
|
+
const result = await client.getWorkshopInstance(instanceId);
|
|
638
|
+
ui.json("Workshop Instance", {
|
|
639
|
+
ok: true,
|
|
640
|
+
...summarizeWorkshopInstance(result.instance),
|
|
641
|
+
instance: result.instance,
|
|
642
|
+
});
|
|
643
|
+
return 0;
|
|
644
|
+
} catch (error) {
|
|
645
|
+
if (error instanceof HarnessApiError) {
|
|
646
|
+
ui.status("error", `Show instance failed: ${error.message}`, { stream: "stderr" });
|
|
647
|
+
return 1;
|
|
648
|
+
}
|
|
649
|
+
throw error;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
585
653
|
async function handleWorkshopArchive(io, ui, env, flags, deps) {
|
|
586
654
|
const session = await requireSession(io, ui, env);
|
|
587
655
|
if (!session) {
|
|
@@ -731,6 +799,41 @@ async function handleWorkshopPrepare(io, ui, env, positionals, flags, deps) {
|
|
|
731
799
|
}
|
|
732
800
|
}
|
|
733
801
|
|
|
802
|
+
async function handleWorkshopResetInstance(io, ui, env, positionals, flags, deps) {
|
|
803
|
+
const session = await requireSession(io, ui, env);
|
|
804
|
+
if (!session) {
|
|
805
|
+
return 1;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const instanceId = await readRequiredCommandValue(
|
|
809
|
+
io,
|
|
810
|
+
flags,
|
|
811
|
+
["id", "instance-id"],
|
|
812
|
+
"Instance id: ",
|
|
813
|
+
readOptionalPositional(positionals, 2),
|
|
814
|
+
);
|
|
815
|
+
if (!instanceId) {
|
|
816
|
+
ui.status("error", "Instance id is required.", { stream: "stderr" });
|
|
817
|
+
return 1;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
try {
|
|
821
|
+
const client = createHarnessClient({ fetchFn: deps.fetchFn, session });
|
|
822
|
+
const result = await client.resetWorkshopInstance(
|
|
823
|
+
instanceId,
|
|
824
|
+
readStringFlag(flags, "template-id", "template"),
|
|
825
|
+
);
|
|
826
|
+
ui.json("Workshop Reset Instance", result);
|
|
827
|
+
return 0;
|
|
828
|
+
} catch (error) {
|
|
829
|
+
if (error instanceof HarnessApiError) {
|
|
830
|
+
ui.status("error", `Reset instance failed: ${error.message}`, { stream: "stderr" });
|
|
831
|
+
return 1;
|
|
832
|
+
}
|
|
833
|
+
throw error;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
734
837
|
async function handleWorkshopRemoveInstance(io, ui, env, positionals, flags, deps) {
|
|
735
838
|
const session = await requireSession(io, ui, env);
|
|
736
839
|
if (!session) {
|
|
@@ -844,6 +947,14 @@ export async function runCli(argv, io, deps = {}) {
|
|
|
844
947
|
return handleWorkshopStatus(io, ui, io.env, mergedDeps);
|
|
845
948
|
}
|
|
846
949
|
|
|
950
|
+
if (scope === "workshop" && action === "list-instances") {
|
|
951
|
+
return handleWorkshopListInstances(io, ui, io.env, mergedDeps);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
if (scope === "workshop" && action === "show-instance") {
|
|
955
|
+
return handleWorkshopShowInstance(io, ui, io.env, positionals, flags, mergedDeps);
|
|
956
|
+
}
|
|
957
|
+
|
|
847
958
|
if (scope === "workshop" && action === "archive") {
|
|
848
959
|
return handleWorkshopArchive(io, ui, io.env, flags, mergedDeps);
|
|
849
960
|
}
|
|
@@ -856,6 +967,10 @@ export async function runCli(argv, io, deps = {}) {
|
|
|
856
967
|
return handleWorkshopUpdateInstance(io, ui, io.env, positionals, flags, mergedDeps);
|
|
857
968
|
}
|
|
858
969
|
|
|
970
|
+
if (scope === "workshop" && action === "reset-instance") {
|
|
971
|
+
return handleWorkshopResetInstance(io, ui, io.env, positionals, flags, mergedDeps);
|
|
972
|
+
}
|
|
973
|
+
|
|
859
974
|
if (scope === "workshop" && action === "prepare") {
|
|
860
975
|
return handleWorkshopPrepare(io, ui, io.env, positionals, flags, mergedDeps);
|
|
861
976
|
}
|