@haus-tech/haus-workflow 4.1.0 → 4.2.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.
@@ -0,0 +1,188 @@
1
+ ---
2
+ name: slack-cowork
3
+ description: Speglar en Slack-kanals canvases till en lokal projektmapp, håller dem synkade och skapar nya. Använd den här skillen när användaren vill koppla upp sessionen mot en Slack-kanal, hämta ner eller "suga ner" canvases, arbeta med utkast lokalt innan de publiceras, pusha ändringar tillbaka till Slack, eller skapa en ny canvas i en kanal. Använd den också i början av en session som gäller ett projekt med en kopplad Slack-kanal — då behöver du synka och läsa av vad som ändrats sedan sist innan något annat arbete påbörjas. Utlöses av fraser som "koppla upp mot #kanal", "synka kanalen", "läs in canvasarna", "pusha till Slack", "publicera utkastet", "vad har hänt i kanalen", "slack-cowork".
4
+ ---
5
+
6
+ # slack-cowork
7
+
8
+ Gör en Slack-kanal till en lokal arbetsyta. Utkast lever som markdown på disk där iteration är snabb och osynlig för andra. Slack är publiceringsytan — dit går bara det som medvetet skickas upp.
9
+
10
+ ## Krav
11
+
12
+ Skillen behöver tre saker: Slack-kopplingen påslagen i chatten, ett skrivbart filsystem, och underagenter för nedladdningen.
13
+
14
+ | Miljö | Stöd |
15
+ | --------------------------- | -------------------------------------------------------------------------------------------- |
16
+ | Cowork, moln med delad mapp | Fullt |
17
+ | Cowork, på egen dator | Fullt |
18
+ | Claude Code | Fullt |
19
+ | claude.ai-chatt | Delvis — canvases går att läsa och uppdatera, men ingen lokal spegling och inga underagenter |
20
+
21
+ Saknas filsystem eller underagenter: säg det innan du börjar, och erbjud den delmängd som fungerar — läsa en canvas och uppdatera den direkt. Bygg inte mappstrukturen halvvägs.
22
+
23
+ ## Varför skillen ser ut som den gör
24
+
25
+ Tre förhållanden formar hela designen. Förstår du dem blir resten självklart.
26
+
27
+ **Sessioner har inget minne.** Arbetet lever bara vidare om det ligger i kanalen eller på disken. Därför börjar varje session med en synk, och därför är det värt att vara noggrann med att skriva ner beslut.
28
+
29
+ **Innehåll passerar alltid genom sammanhanget.** Det finns ingen ledning från Slack till filsystemet som går förbi dig. En canvas på 43 KB kostar ungefär 11 000 tokens att hämta. Därför sker nedladdning i underagenter som skriver till disk och bara rapporterar tillbaka en rad.
30
+
31
+ **Slack berättar inte vem som ändrat vad inne i en canvas.** Ingen upphovsinformation per sektion finns att hämta. Därför bygger konfliktdetekteringen på lokala ögonblicksbilder i `.snapshot/`. Den mappen är hela säkerhetsmekanismen.
32
+
33
+ ## Mappar och register
34
+
35
+ Speglingen ligger i projektets egen mapp, eftersom kanalens dokument hör ihop med projektets övriga material och ska följa med när mappen delas.
36
+
37
+ **Varje canvas har exakt en lokal arbetsfil.** Det är den viktigaste regeln i hela skillen. Finns två filer med samma innehåll vet varken du eller användaren vilken som ska redigeras, och nästa session gissar fel. Manifestets `lokal_fil` pekar ut den enda arbetsfilen; sökvägen är relativ projektmappens rot och får peka var som helst i projektet.
38
+
39
+ ```
40
+ <projektmapp>/
41
+ ├── forvaltningsmodellen.md # arbetsfil, låg redan här — redigera denna
42
+ ├── genomforande-arbetsdokument.md # arbetsfil
43
+ └── slack/<kanalnamn>/
44
+ ├── manifest.json
45
+ ├── canvas/<slug>.md # ENDAST dokument som föddes i Slack
46
+ ├── .snapshot/<slug>.md # som Slack såg ut vid senaste synk — rör aldrig
47
+ ├── historik.md # löpande logg, nyaste överst
48
+ └── historik-arkiv.md
49
+ ```
50
+
51
+ `canvas/`-mappen är till för dokument hämtade från Slack som saknar lokal förlaga. Ett dokument som redan fanns lokalt och konverterats till canvas stannar där det låg — att kopiera in det under `canvas/` skapar just den tvetydighet regeln finns för att undvika.
52
+
53
+ Ett register i `.slack-cowork.json` mappar kanal till projektmapp och pekar ut vilken kanal som är aktiv. Det finns för att samma kanal aldrig ska speglas från två håll — två `.snapshot/` som båda tror sig vara sanningen ger tyst felaktig konfliktdetektering.
54
+
55
+ Registret läggs i roten av den delade mappen, inte i användarens hemkatalog. I Cowork når du användarens filer genom en enhetsbrygga vars hemkatalog är knuten till sessionen och försvinner med den; bara delade mappar överlever. Delas en rotmapp med flera projekt under sig, lägg registret där — då täcker det alla projekt i roten. Delas ett enskilt projekt, lägg det i projektmappen.
56
+
57
+ Leta efter registret i roten av varje delad mapp innan du antar att ingen kanal är ansluten.
58
+
59
+ Scheman för register och manifest finns i `references/synk.md`. Läs den filen innan du skriver något av dem.
60
+
61
+ ## Flöden
62
+
63
+ ### Anslut en kanal
64
+
65
+ När användaren ber dig koppla upp mot en kanal:
66
+
67
+ 1. Slå upp kanalen med `slack_search_channels`. Sätt `channel_types="public_channel,private_channel"` — verktyget söker annars bara publika kanaler, och de flesta arbetskanaler är privata.
68
+ 2. Kontrollera registret. Är kanalen redan speglad någon annanstans — säg det och fråga innan du gör något mer. Skapa aldrig en andra spegling.
69
+ 3. Inventera kanalens dokument med `slack_search_public_and_private`: `content_types="files"`, frågan `type:canvases in:<#KANAL_ID>`, `include_context=false` och `response_format="concise"`. De två sista håller nere det som dras in i sammanhanget — du behöver bara metadata här.
70
+ 4. Skapa mappstrukturen och manifestet, ladda ner allt enligt mönstret nedan.
71
+ 5. Rapportera vad som hämtades: antal, titlar, ägare, storlek.
72
+
73
+ **Paginera alltid.** Sökningen returnerar högst 20 träffar per anrop. Följ `next_cursor` tills den tar slut. En ofullständig inventering är värre än ingen alls: dokument som inte kom med flaggas vid nästa synk som borttagna ur Slack, trots att de finns kvar.
74
+
75
+ Inventera även `type:lists in:<#KANAL_ID>` och för in eventuella listor i manifestet med status `endast_index`. Kopplingen har inga verktyg för att läsa eller skriva Slack-listor — bara canvases. Säg det rakt ut när du redovisar dem, så att ingen tror att de går att arbeta med.
76
+
77
+ ### Synka vid sessionsstart
78
+
79
+ Gör detta _innan_ något annat arbete påbörjas. Poängen är inte att hämta filer utan att användaren ska få veta vad som hänt sedan sist innan hen fattar beslut.
80
+
81
+ 1. Inventera kanalen på nytt och jämför mot manifestet.
82
+ 2. Hämta det som är nytt eller vars ändringsdatum är nyare än manifestets. Hoppa över det oförändrade — efter första synken är de flesta sessioner nästan gratis.
83
+ 3. Finns ett dokument lokalt men inte längre i Slack: flagga det. Radera aldrig lokalt material på eget bevåg. Kontrollera först att inventeringen paginerats färdigt och att dokumentet inte skapats så nyligen att sökindexet inte hunnit med.
84
+
85
+ Leta samtidigt efter dubbletter: en fil någon annanstans i projektet med nästan identiskt innehåll som en registrerad arbetsfil. Välj inte åt användaren vilken som gäller — visa båda sökvägarna och fråga. Dubbletter uppstår lätt vid konvertering och är tysta tills någon redigerar fel fil.
86
+
87
+ 4. Läs kanalhistoriken sedan senaste synk med `slack_read_channel` och lägg en kort sammanfattning överst i `historik.md`. Beslut fattas ofta i chatten och hinner aldrig in i dokumenten — det är därför historiken är värd att spara.
88
+
89
+ Sätt `oldest` till tidpunkten för senaste synk. Parametern tar en **Unix-timestamp**, medan manifestet lagrar ISO 8601 — konvertera. Utan `oldest` får du bara de senaste 100 meddelandena och längre luckor försvinner tyst. Är luckan större än 100 meddelanden, paginera med `cursor`.
90
+
91
+ 5. Rapportera driften: vad som ändrats, av vem, när, och vilka lokala filer som nu avviker.
92
+
93
+ Växer `historik.md` förbi ungefär 50 KB, flytta de äldsta posterna till `historik-arkiv.md`.
94
+
95
+ ### Nedladdningsmönstret
96
+
97
+ Starta en underagent per dokument som ska hämtas, parallellt i samma tur. Ge varje agent i uppdrag att:
98
+
99
+ - anropa `slack_read_canvas` med dokumentets ID
100
+ - skriva innehållet till `canvas/<slug>.md` och en identisk kopia till `.snapshot/<slug>.md`
101
+ - returnera **endast** en rad JSON med nycklarna `id`, `titel`, `sokvag`, `storlek_kb`, `antal_sektioner`
102
+
103
+ Agentens svar är returvärdet, inte ett meddelande till en människa. Innehållet ska aldrig komma tillbaka i svaret — hela poängen är att det brinner i agentens sammanhang och inte i ditt.
104
+
105
+ Behövs inga nedladdningar, starta inga agenter.
106
+
107
+ När ett dokument faktiskt ska bearbetas läser du den lokala filen på vanligt sätt. Ha inte fler än två–tre stora dokument aktiva samtidigt.
108
+
109
+ ### Arbeta lokalt
110
+
111
+ Ingen Slack-kontakt alls. Redigera markdown-filerna under `canvas/` fritt. Det är här iterationen ska ske — billigt, snabbt och utan att halvfärdiga resonemang syns för teamet.
112
+
113
+ ### Pusha till Slack
114
+
115
+ Push sker på uttrycklig order — "pusha", "publicera", "lägg upp". Aldrig automatiskt, eftersom canvasen är något användaren medvetet visar för sitt team.
116
+
117
+ 1. Läs canvasen färskt med `slack_read_canvas`. Du behöver både dess nuvarande innehåll och färska sektions-ID:n.
118
+ 2. Jämför i tre led per sektion: lokal fil, `.snapshot/`, och Slack. `references/synk.md` beskriver utfallen.
119
+ 3. Lint:a innehållet mot canvas-markdown enligt `references/canvas-markdown.md`. Ett utkast som bryter mot reglerna går sönder vid push, ofta tyst.
120
+ 4. Skicka alla ändringar i ett enda `slack_update_canvas` med flera operationer i `sections`. De tillämpas atomiskt mot samma ögonblicksbild. Taket är 100 operationer — behövs fler, dela upp och läs om sektions-ID:n mellan varje omgång, eftersom de ändras vid varje skrivning.
121
+ 5. Skriv om `.snapshot/` och uppdatera manifestet.
122
+
123
+ **Sektions-ID:n är färskvara.** De ändras vid varje skrivning. Steg 1 måste ske omedelbart före steg 4 — aldrig från minnet, aldrig från en tidigare tur. Använder du ett gammalt ID skriver du över fel sektion.
124
+
125
+ ### Konflikter
126
+
127
+ Har samma sektion ändrats både lokalt och i Slack: **stoppa hela pushen och fråga.**
128
+
129
+ Visa båda versionerna sida vid sida och låt användaren avgöra — lokal, fjärr, eller sammanslagning. Pusha inte de okonfliktade sektionerna under tiden; ett halvpushat dokument är svårare att reda ut än ett opushat.
130
+
131
+ Detta är skillens viktigaste skyddsräcke. Du kan inte se vem som skrivit vad, så en gissning här är en gissning om någon annans arbete.
132
+
133
+ ### Skapa en ny canvas
134
+
135
+ 1. `slack_create_canvas` med titel och innehåll.
136
+ 2. Posta länken i kanalen med `slack_send_message` så teamet ser den.
137
+ 3. Lägg till i manifestet och skriv lokal fil plus snapshot.
138
+
139
+ `slack_create_canvas` tar ingen kanalparameter — canvasen skapas fristående. Det är först när länken postas i kanalen som den blir en kanalfil och dyker upp i inventeringen.
140
+
141
+ **Sökindexet släpar några minuter.** En nyss skapad canvas syns inte direkt i `type:canvases in:<#KANAL_ID>` även om allt gått rätt till. Flagga den därför aldrig som saknad vid samma eller nästkommande synk — vänta tills den hunnit indexeras. Skriv in den i manifestet direkt; inventeringen kommer ikapp.
142
+
143
+ Vill användaren dessutom ha canvasen som flik i kanalen får hen fästa den manuellt. Det går inte via kopplingen.
144
+
145
+ ### Konvertera en lokal fil till canvas
146
+
147
+ När en befintlig markdown-fil ska bli en canvas:
148
+
149
+ 1. Lint:a innehållet enligt `references/canvas-markdown.md`. Rätta struktur, aldrig sak.
150
+ 2. Använd filens första rubrik som `title` och utelämna den ur `content` — Slack sätter titeln själv.
151
+ 3. Skapa canvasen och posta länken i kanalen.
152
+ 4. **Skriv tillbaka den lintade texten till källfilen** och lägg en identisk kopia i `.snapshot/`. Källfilen blir arbetsfilen.
153
+ 5. Registrera den i manifestet med `lokal_fil` pekande på källfilen och `ursprung: "lokal"`.
154
+
155
+ Steg 4 är lätt att göra fel. Lintningen ändrar texten — listmarkörer, tomrader — och görs den bara på vägen upp avviker källfilen direkt från Slack. Nästa push visar då skillnader som ingen människa orsakat.
156
+
157
+ Kopiera aldrig källfilen till `canvas/`. Två filer med samma innehåll är precis det problem den här skillen finns för att undvika.
158
+
159
+ ### Föreslå synk
160
+
161
+ Du får föreslå en push när ett arbetssteg framstår som avslutat eller ett beslut fattats. Håll förslaget kort och peka på vad som skulle publiceras:
162
+
163
+ > Avsnitt 4 har fått två låsta beslut sedan senaste synken. Pusha upp?
164
+
165
+ Utför aldrig pushen på eget bevåg. Förslaget är en påminnelse, inte en begäran om tyst samtycke.
166
+
167
+ ## Avgränsa alltid sökningen till kanalen
168
+
169
+ `slack_search_public_and_private` når allt användaren har åtkomst till — privata kanaler, alla DM, personliga anteckningskanaler. Filtrera därför **alltid** med `in:<#KANAL_ID>`.
170
+
171
+ Utan filtret drar du in kundkonversationer, lösenord och annat som varken hör till uppgiften eller bör hamna i sammanhanget. Det är inte en teknisk begränsning utan en fråga om att inte läsa mer än uppgiften kräver.
172
+
173
+ ## Flera kanaler
174
+
175
+ En aktiv kanal åt gången. Push- och konfliktlogiken är tillståndsberoende, och parallella kanaler mångdubblar sätten att skriva till fel ställe.
176
+
177
+ Att _läsa_ från andra kanaler som referens går bra. Skriv aldrig utanför den aktiva kanalen utan att användaren uttryckligen bytt.
178
+
179
+ ## Git för snapshots
180
+
181
+ Valfritt per kanal via `git_snapshot` i registret, avstängt som standard. Är projektmappen ett git-repo och flaggan påslagen: commita `.snapshot/` efter varje synk med ett genererat meddelande.
182
+
183
+ Fallerar git med lås- eller behörighetsfel beror det oftast på att mappen nås via enhetsbryggan från en molnsession. Det är miljön, inte skillen. Säg det, och föreslå antingen att flaggan stängs av eller att sessionen körs på användarens egen dator.
184
+
185
+ ## Referensfiler
186
+
187
+ - `references/synk.md` — register- och manifestscheman, trevägsjämförelsen i detalj, konfliktdialogen. Läs innan du skriver manifest eller genomför en push.
188
+ - `references/canvas-markdown.md` — den tillåtna delmängden av markdown och hur vanliga fel rättas. Läs före varje push och innan du skapar en ny canvas.
@@ -0,0 +1,160 @@
1
+ # Canvas-markdown
2
+
3
+ Canvas-markdown är en delmängd av vanlig markdown. Ett lokalt utkast som bryter mot reglerna nedan går sönder vid push — ibland med felmeddelande, ibland tyst genom att formatering försvinner.
4
+
5
+ Gå igenom listan före varje push och innan du skapar en ny canvas. Rätta automatiskt där det är entydigt; fråga där en rättning skulle ändra innebörden.
6
+
7
+ ## Innehåll
8
+
9
+ Rubriker · Listor · Tabeller · Referenser och länkar · Datum · Block och avgränsare · Layouter och callouts · Innehållsförteckningar · Vanliga fel och rättningar
10
+
11
+ _Innehållsförteckningen ovan är avsiktligt utan länkar — se avsnittet om innehållsförteckningar nedan._
12
+
13
+ ## Rubriker
14
+
15
+ Endast `#`, `##` och `###`. Djupare nivåer underkänns.
16
+
17
+ Har utkastet `####` finns två rimliga rättningar: höj hela hierarkin ett steg om dokumentet har utrymme, eller gör om nivån till fetstilt brödtext. Välj det senare när dokumentet redan använder alla tre nivåerna meningsfullt.
18
+
19
+ Rubriker får inte ligga inuti listpunkter.
20
+
21
+ ## Listor
22
+
23
+ Listpunkter får bara innehålla stycken med inline-formatering — fet, kursiv, `kod`, länkar.
24
+
25
+ Inte tillåtet i listpunkter:
26
+
27
+ - kodblock
28
+ - rubriker
29
+ - blockcitat
30
+
31
+ Nästlade listor får inte blanda typ. En numrerad lista kan bara innehålla numrerade underlistor; en punktlista bara punktade. Blandar utkastet, gör om underlistan till samma typ som föräldern.
32
+
33
+ Kodblock, blockcitat och rubriker måste skiljas från listor med tomrad.
34
+
35
+ Kryssrutor fungerar: `- [ ]` och `- [x]`.
36
+
37
+ ## Tabeller
38
+
39
+ Vanlig markdown-tabellsyntax fungerar.
40
+
41
+ Radbrytning i en cell skrivs som `<br>` — aldrig som faktisk radbrytning, den bryter tabellen.
42
+
43
+ Escape-sekvenser i celler (`\>`, `\*`, `\-`, `\#`) ska bevaras exakt.
44
+
45
+ Blockcitat får förekomma i celler men bara med ren text och inline-formatering.
46
+
47
+ Tabeller får inte ligga i layouter eller callouts.
48
+
49
+ ## Referenser och länkar
50
+
51
+ | Vad | Skrivs som |
52
+ | --------- | ------------------------------------- |
53
+ | Användare | `![](@U15CTCJ83)` |
54
+ | Kanal | `![](#C15CTCJ83)` |
55
+ | Länk | `[text](https://exempel.se)` |
56
+ | Bild | `![alt](https://exempel.se/bild.png)` |
57
+
58
+ Vinkelparenteser är fel i alla dessa fall. `<@U123>` och `<#C123>` renderas inte — de blir synlig råtext. Detta gäller även inuti citerad text.
59
+
60
+ Använd alltid kanalens ID, aldrig dess namn.
61
+
62
+ En användarreferens på egen rad renderas som ett större profilkort; inline blir den formaterad text. Välj efter avsikt.
63
+
64
+ Tillåtna URL-scheman: `http`, `https`, `mailto`, `tel`, `ftp`, `slack`, samt relativa sökvägar som börjar med `/`. Andra scheman tas bort tyst.
65
+
66
+ Länkar ska inte omges av vinkelparenteser.
67
+
68
+ ## Datum
69
+
70
+ Datum skrivs `![](slack_date:ÅÅÅÅ-MM-DD)` och ingenting annat på samma rad. Ingen veckodag, ingen efterföljande datumtext.
71
+
72
+ Rätt:
73
+
74
+ ```
75
+ ## ![](slack_date:2026-08-14)
76
+ ```
77
+
78
+ Fel:
79
+
80
+ ```
81
+ ## ![](slack_date:2026-08-14) 14 augusti – fredag
82
+ ```
83
+
84
+ Detta gäller även deadlines och milstolpar i löpande text.
85
+
86
+ ## Block och avgränsare
87
+
88
+ Avgränsare (`---`, `***`, `___`) endast på toppnivå.
89
+
90
+ Blockcitat får innehålla stycken, rubriker, listor och kodblock — men inte avgränsare, bilder, kort, callouts, kolumner, tabeller eller andra blockcitat.
91
+
92
+ Slack-emoji fungerar: `:tada:`, `:large_green_circle:`.
93
+
94
+ ## Layouter och callouts
95
+
96
+ Callout:
97
+
98
+ ```
99
+ ::: {.callout}
100
+ Innehållet
101
+ :::
102
+ ```
103
+
104
+ Layout med kolumner, högst tre:
105
+
106
+ ```
107
+ ::: {.layout}
108
+ ::: {.column}
109
+ Första kolumnen
110
+ :::
111
+ ::: {.column}
112
+ Andra kolumnen
113
+ :::
114
+ :::
115
+ ```
116
+
117
+ Tabeller och callouts fungerar inte inuti layouter. Callouts kan inte nästlas i andra element.
118
+
119
+ Använd callouts sparsamt — till varningar och förutsättningar, inte som allmän betoning.
120
+
121
+ ## Innehållsförteckningar
122
+
123
+ Rena ankarlänkar (`[Rubrik](#rubrik)`) stöds inte. De tas bort tyst vid push — texten blir kvar men blir oklickbar.
124
+
125
+ En fungerande intern länk använder canvasens egen URL med sektions-ID:
126
+
127
+ ```
128
+ [Principerna](https://<workspace>.slack.com/docs/<team_id>/<file_id>?focus_section_id=<section_id>)
129
+ ```
130
+
131
+ Sektions-ID:n hämtas ur `section_id_mapping` från `slack_read_canvas`. De ändras vid varje skrivning, så en innehållsförteckning byggd så här måste byggas om vid varje push där sektioner tillkommer eller försvinner.
132
+
133
+ Det gör innehållsförteckningar dyra att underhålla. Har ett lokalt utkast en förteckning med ankarlänkar: fråga om den ska byggas om med riktiga sektionslänkar eller skrivas om utan länkar. Skriv inte tyst bort den.
134
+
135
+ ## Slack-filer
136
+
137
+ Filer med URL under `*.slack.com/files/*` bäddas in som `![](filreferens)`. På egen rad blir det ett kort, inline blir det klickbar text.
138
+
139
+ Använd inte den syntaxen för filer som ligger någon annanstans — där gäller vanlig länkformatering.
140
+
141
+ ## Vanliga fel och rättningar
142
+
143
+ | Fel i utkastet | Rättning |
144
+ | ------------------------------------- | ----------------------------------------------------------- |
145
+ | `#### Underrubrik` | `**Underrubrik**` som brödtext, eller höj hela hierarkin |
146
+ | `<@U01K3CTC6C8>` | `![](@U01K3CTC6C8)` |
147
+ | `<#C0BR16H72RE>` | `![](#C0BR16H72RE)` |
148
+ | `<https://exempel.se>` | `[exempel.se](https://exempel.se)` |
149
+ | Kodblock inuti listpunkt | Lyft ut kodblocket ur listan, med tomrad före och efter |
150
+ | Punktlista nästlad i numrerad | Gör om underlistan till numrerad |
151
+ | Faktisk radbrytning i tabellcell | `<br>` |
152
+ | `2026-08-14 (fredag)` som datumrubrik | `![](slack_date:2026-08-14)` |
153
+ | Tabell inuti callout | Flytta ut tabellen ur callouten |
154
+ | `[Avsnitt 3](#avsnitt-3)` | Sektionslänk med `?focus_section_id=`, eller ta bort länken |
155
+
156
+ ## Titelsektionen
157
+
158
+ Vid `slack_update_canvas` mot dokumentets första sektion — titeln — skickas endast en rad, högst 255 byte, utan radbrytningar. Brödtext som ska följa efter titeln skickas som en separat operation mot en egen sektion.
159
+
160
+ Vid `slack_create_canvas` sätts titeln i fältet `title` och ska inte upprepas i `content`.
@@ -0,0 +1,226 @@
1
+ # Synk, register och konflikter
2
+
3
+ Detaljerna bakom flödena i SKILL.md. Läs den här filen innan du skriver ett manifest eller genomför en push.
4
+
5
+ ## Innehåll
6
+
7
+ - [Registret](#registret)
8
+ - [Manifestet](#manifestet)
9
+ - [Slugar](#slugar)
10
+ - [Trevägsjämförelsen](#trevägsjämförelsen)
11
+ - [Konfliktdialogen](#konfliktdialogen)
12
+ - [Sektionshantering vid push](#sektionshantering-vid-push)
13
+ - [Nedladdning via underagenter](#nedladdning-via-underagenter)
14
+ - [Historikformat](#historikformat)
15
+ - [Återställning när snapshot saknas](#återställning-när-snapshot-saknas)
16
+
17
+ ## Registret
18
+
19
+ `.slack-cowork.json` i roten av en delad mapp är det enda skillen letar upp på egen hand. Allt annat hittas därifrån.
20
+
21
+ **Lägg det aldrig i hemkatalogen.** I Cowork nås användarens filer genom en enhetsbrygga där hemkatalogen är sessionsbunden — en sökväg som `/sessions/rcw-.../` finns inte kvar nästa gång. Bara delade mappar överlever. Registret hör därför hemma i roten av den delade mappen: är en rotmapp delad med flera projekt under sig ligger det där och täcker alla; är ett enskilt projekt delat ligger det i projektmappen.
22
+
23
+ Sök efter filen i roten av varje delad mapp innan du drar slutsatsen att ingen kanal är ansluten.
24
+
25
+ ```json
26
+ {
27
+ "kanaler": {
28
+ "C0BR16H72RE": {
29
+ "namn": "tech-business-development",
30
+ "projektmapp": "/Users/jonas/Dev/ClaudeCowork/New Tech Business Model",
31
+ "git_snapshot": false,
32
+ "ansluten": "2026-08-14T09:12:00+02:00"
33
+ }
34
+ },
35
+ "aktiv_kanal": "C0BR16H72RE"
36
+ }
37
+ ```
38
+
39
+ `aktiv_kanal` avgör vart skrivningar går. Läsning från andra kanaler är fri; push, canvasskapande och manifestuppdateringar sker bara mot den aktiva. Byte kräver uttrycklig order från användaren — sätt då om fältet och säg vilken kanal som nu gäller.
40
+
41
+ Pekar flera kanaler mot samma `projektmapp` får de egna undermappar under `slack/`. Det är tillåtet, men bara en åt gången kan vara aktiv.
42
+
43
+ Registret finns för att en kanal aldrig ska speglas från två projektmappar samtidigt. Två `.snapshot/` betyder två olika uppfattningar om vad Slack innehöll senast, och då blir konfliktdetekteringen fel utan att någon märker det.
44
+
45
+ Försöker någon ansluta en redan registrerad kanal från en annan mapp: avbryt, visa var den redan är speglad, och fråga. Flytt är ett medvetet beslut, inte något som ska ske i förbifarten.
46
+
47
+ ## Manifestet
48
+
49
+ `<projektmapp>/slack/<kanalnamn>/manifest.json`
50
+
51
+ ```json
52
+ {
53
+ "kanal": { "namn": "tech-business-development", "id": "C0BR16H72RE" },
54
+ "senaste_synk": "2026-08-14T09:12:00+02:00",
55
+ "dokument": [
56
+ {
57
+ "id": "F0BPV7VLGSH",
58
+ "titel": "Haus förvaltningsmodell",
59
+ "typ": "canvas",
60
+ "agare": "jonas.landgard",
61
+ "andrad": "2026-08-14T08:01:49+02:00",
62
+ "lokal_fil": "forvaltningsmodellen.md",
63
+ "snapshot": ".snapshot/haus-forvaltningsmodell.md",
64
+ "status": "synkad",
65
+ "ursprung": "lokal"
66
+ }
67
+ ]
68
+ }
69
+ ```
70
+
71
+ `lokal_fil` är relativ projektmappens rot och får peka var som helst i projektet. Det är manifestet, inte mappstrukturen, som avgör vilken fil som hör till vilken canvas.
72
+
73
+ `ursprung` är `lokal` för dokument som fanns som fil innan de blev canvas — de ligger kvar där de låg — och `slack` för dokument hämtade från kanalen, som placeras under `canvas/<slug>.md`.
74
+
75
+ `snapshot` är relativ kanalmappen och använder alltid slugen, oavsett vad arbetsfilen heter.
76
+
77
+ **Skapa aldrig en andra kopia av en arbetsfil.** Två filer med samma innehåll gör det omöjligt att veta vilken som ska redigeras, och felet märks först när någon arbetat en stund i fel fil. Hittar du en dubblett vid synk: visa båda sökvägarna och fråga vilken som gäller — välj inte åt användaren.
78
+
79
+ `status` är ett av:
80
+
81
+ | Värde | Betyder |
82
+ | ------------------ | ----------------------------------------------------------- |
83
+ | `synkad` | Lokal fil, snapshot och Slack är identiska |
84
+ | `lokala_ändringar` | Lokal fil avviker från snapshot; Slack oförändrad |
85
+ | `fjärrändringar` | Slack avviker från snapshot; lokal fil oförändrad |
86
+ | `konflikt` | Båda avviker från snapshot |
87
+ | `endast_index` | Dokumentet är känt men kan inte läsas — gäller Slack-listor |
88
+ | `saknas_i_slack` | Finns lokalt men hittades inte vid senaste inventering |
89
+
90
+ Sätt aldrig `saknas_i_slack` utan att först ha paginerat inventeringen färdigt. Den näst vanligaste orsaken till felaktig flaggning är en nyss skapad canvas: Slacks sökindex släpar några minuter, så ett dokument som skapades under samma session kan saknas i inventeringen trots att det finns. Vänta till en senare synk innan du drar slutsatser om det.
91
+
92
+ ## Slugar
93
+
94
+ Filnamn härleds från titeln: gemener, mellanslag till bindestreck, å/ä till a och ö till o, övriga specialtecken bort.
95
+
96
+ "Haus förvaltningsmodell" blir `haus-forvaltningsmodell.md`.
97
+
98
+ Slugen används för snapshot-filen och för dokument som hämtats från Slack. En arbetsfil som fanns lokalt först behåller sitt eget namn — `forvaltningsmodellen.md` förblir `forvaltningsmodellen.md` även om canvasen heter "Haus förvaltningsmodell" och snapshotet `haus-forvaltningsmodell.md`. Kopplingen görs i manifestet, inte genom namnlikhet.
99
+
100
+ Byter dokumentet titel i Slack, behåll den lokala filen och dess namn — döp inte om, eftersom lokala referenser och git-historik då bryts. Uppdatera bara `titel` i manifestet.
101
+
102
+ Kolliderar två slugar, lägg till dokumentets sista fyra ID-tecken.
103
+
104
+ ## Trevägsjämförelsen
105
+
106
+ Jämför per sektion mellan tre versioner: **L** (lokal fil), **S** (snapshot) och **F** (fjärr, det Slack innehåller nu).
107
+
108
+ | L mot S | F mot S | Åtgärd |
109
+ | ---------- | -------------------------- | -------------------------------------- |
110
+ | ändrad | oförändrad | Pusha L till Slack |
111
+ | oförändrad | ändrad | Skriv F till lokal fil |
112
+ | ändrad | ändrad, men identisk med L | Ingen åtgärd — samma resultat |
113
+ | ändrad | ändrad, annorlunda | **Konflikt** — fråga |
114
+ | oförändrad | oförändrad | Ingen åtgärd |
115
+ | saknas i L | finns | Fråga innan radering i Slack |
116
+ | finns i L | saknas i F | Sektionen är borttagen i Slack — fråga |
117
+ | — | ny sektion | Behåll, skriv till lokal fil |
118
+
119
+ Två principer bakom tabellen:
120
+
121
+ **Radera aldrig utan att fråga.** En sektion som saknas lokalt kan lika gärna bero på att någon i Slack lagt till den efter senaste synken som på att den medvetet tagits bort.
122
+
123
+ **Identiska ändringar är ingen konflikt.** Har båda sidor råkat göra samma ändring finns inget att lösa.
124
+
125
+ ## Konfliktdialogen
126
+
127
+ Vid konflikt: avbryt hela pushen. Pusha inte de okonfliktade sektionerna heller — ett halvpushat dokument är svårare att reda ut än ett opushat, och användaren kan vilja ändra sitt lokala utkast efter att ha sett vad någon annan skrivit.
128
+
129
+ Presentera så här:
130
+
131
+ ```
132
+ Konflikt i "Haus förvaltningsmodell", avsnitt 3 – Principerna
133
+
134
+ Din lokala version:
135
+ > Risk höjer pris. Det som rör behörighet, pengar eller personuppgifter
136
+ > kostar mer än sin storlek.
137
+
138
+ I Slack (ändrad av Viktoria Brandel, 14 aug 09:41):
139
+ > Risk påverkar pris. Behörighet, betalning och personuppgifter bär
140
+ > ett större ansvar och prissätts därefter.
141
+
142
+ Vilken gäller – din, Viktorias, eller ska de vävas ihop?
143
+ ```
144
+
145
+ Ta med vem som ändrat och när där det går att få fram ur kanalhistoriken. Slack ger ingen upphovsinformation per sektion, men Slackbots kanalnotiser ("N made updates to a canvas tab") ger ofta tillräckligt för att namnge personen.
146
+
147
+ Är flera sektioner i konflikt: visa alla innan du frågar, så att användaren kan bedöma helheten.
148
+
149
+ ## Sektionshantering vid push
150
+
151
+ `slack_read_canvas` returnerar `section_id_mapping` — en karta från sektions-ID till innehåll. Dessa ID:n ändras vid varje skrivning.
152
+
153
+ Därför gäller: läs omedelbart före skrivning, i samma tur. Aldrig från minnet, aldrig från en tidigare tur, aldrig från ett tidigare svar i samma konversation.
154
+
155
+ Skicka alla ändringar i ett enda `slack_update_canvas` med flera poster i `sections`. De tillämpas atomiskt mot samma ögonblicksbild, vilket är både snabbare och säkrare än flera anrop i följd.
156
+
157
+ Operationstyper:
158
+
159
+ | `edit_type` | Effekt |
160
+ | ----------- | ---------------------------- |
161
+ | `replace` | Ersätter sektionens innehåll |
162
+ | `append` | Lägger till efter sektionen |
163
+ | `prepend` | Lägger till före sektionen |
164
+ | `delete` | Tar bort sektionen |
165
+
166
+ Högst 100 operationer per anrop. Behövs fler: dela upp i omgångar och läs om sektions-ID:n mellan varje, eftersom de ändras vid varje skrivning. Säg till användaren att pushen sker i flera steg — atomiciteten gäller bara inom en omgång.
167
+
168
+ En rubrik och innehållet under den är skilda sektioner. `replace` mot en rubrik ändrar bara rubriken, inte texten under. Ska ett helt avsnitt bytas ut krävs operationer mot både rubriken och dess brödtext. Byter du texten i en rubrik måste rubrikmarkören följa med i `content` — skickar du `Principerna` i stället för `## Principerna` blir rubriken brödtext.
169
+
170
+ En hel lista eller kryssrutelista är **en** sektion. Att ändra en enda punkt innebär att hela listan skickas som `replace`.
171
+
172
+ Titelsektionen är dokumentets första. Den tar endast en rad utan radbrytningar, högst 255 byte.
173
+
174
+ ## Nedladdning via underagenter
175
+
176
+ Starta en agent per dokument, alla i samma tur så de körs parallellt.
177
+
178
+ Uppdraget till varje agent:
179
+
180
+ ```
181
+ Hämta Slack-canvas <ID> med slack_read_canvas.
182
+ Svaret innehåller dokumentets markdown och en karta över sektions-ID:n.
183
+ Skriv markdown-innehållet oförändrat till <projektmapp>/slack/<kanal>/canvas/<slug>.md
184
+ och en identisk kopia till <projektmapp>/slack/<kanal>/.snapshot/<slug>.md
185
+ Returnera endast en rad JSON: {"id","titel","sokvag","storlek_kb","antal_sektioner"}
186
+ Returnera aldrig dokumentets innehåll.
187
+ ```
188
+
189
+ Sista raden är avgörande. Agentens svar är ett returvärde, inte ett meddelande till en människa — kommer innehållet tillbaka har hela mönstret varit meningslöst, eftersom kostnaden då hamnar i huvudsessionens sammanhang ändå.
190
+
191
+ Skriv filer med de verktyg som når rätt filsystem: i Cowork mot användarens dator via enhetsbryggan, i Claude Code direkt.
192
+
193
+ ## Historikformat
194
+
195
+ `historik.md`, nyaste överst, en post per synk:
196
+
197
+ ```markdown
198
+ ## 2026-08-14 09:12
199
+
200
+ **Ändrat sedan 2026-08-13 16:40**
201
+
202
+ - "Haus förvaltningsmodell" uppdaterad av jonas.landgard 08:01 — avsnitt 4, beslut 3 och 4 låsta
203
+ - Ny canvas: "Paketering befintliga kunder" av Viktoria Brandel
204
+
205
+ **Diskussion i kanalen**
206
+
207
+ Viktoria invände mot ordet "förvaltning" i kundkommunikation — signalerar
208
+ underhållsläge när halva erbjudandet är aktiv utveckling. Ligger kvar som
209
+ öppet beslut 1.
210
+ ```
211
+
212
+ Sammanfatta hellre än att citera. Poängen är att en ny session snabbt ska förstå läget, inte att arkivera varje meddelande.
213
+
214
+ Vid ungefär 50 KB: flytta de äldsta posterna till `historik-arkiv.md` och notera flytten överst i arkivfilen.
215
+
216
+ ## Återställning när snapshot saknas
217
+
218
+ Saknas `.snapshot/` för ett dokument går konflikter inte att upptäcka. Gissa inte.
219
+
220
+ Behandla dokumentet som en förstagångssynk:
221
+
222
+ 1. Hämta Slack-versionen till `.snapshot/`.
223
+ 2. Finns en lokal fil som avviker: visa skillnaderna och låt användaren avgöra vad som gäller innan något pushas.
224
+ 3. Har det aldrig funnits en lokal fil: skriv Slack-versionen till båda platserna.
225
+
226
+ Det är också skälet till att `git_snapshot` finns som möjlighet — ett git-repo gör snapshot-mappen återställbar efter en olycka.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haus-tech/haus-workflow",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Haus AI workflow CLI for Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {