M1 - Foundations #2
Merged@k33g wants to merge
feature/m1-foundations into mainMerged as
51f931f9a3ce.144 files changed
modified
.claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py +29 -26 | @@ -1,7 +1,9 @@ | ||
| 1 | 1 | """The description of docs/diagrams/packages.{drawio,svg} (Sidekicks, ADR 0003). |
| 2 | 2 | |
| 3 | 3 | python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams |
| 4 | - rsvg-convert -w 1200 -h 780 -o docs/diagrams/packages.png docs/diagrams/packages.svg | |
| 4 | + rsvg-convert -w 1200 -h 800 -o docs/diagrams/packages.png docs/diagrams/packages.svg | |
| 5 | + | |
| 6 | +Blue boxes exist; grey boxes are planned (their milestone is written in them). | |
| 5 | 7 | """ |
| 6 | 8 | import os |
| 7 | 9 | import sys |
| @@ -12,41 +14,42 @@ from flowgen import Diagram | ||
| 12 | 14 | OUT = sys.argv[1] if len(sys.argv) > 1 else "docs/diagrams" |
| 13 | 15 | |
| 14 | 16 | d = Diagram("packages", "Sidekicks — packages and dependencies", |
| 15 | - "arrows are imports · the frontend only talks to internal/app · nothing outside internal/acp sees the ACP SDK", height=780) | |
| 17 | + "arrows are imports · blue: exists (M1) · grey: planned · only main.go imports Wails", height=800) | |
| 16 | 18 | |
| 17 | 19 | # Row 1: the entry points. |
| 18 | -d.box(40, 100, 250, 115, "user", "💻", "frontend/", ["Svelte 5 · panels · Markdown", "CodeMirror · xterm.js"]) | |
| 19 | -d.box(475, 100, 250, 115, "decider", "🔀", "internal/app", ["Wails services bound to the UI", "typed events to the UI"], badge="★ only API of the UI") | |
| 20 | -d.box(910, 100, 250, 115, "data", "⚙️", "cmd/sidekicks", ["main: reads flags, wires", "the services, runs Wails"]) | |
| 20 | +d.box(40, 100, 250, 115, "user", "💻", "frontend/", ["Svelte 5 · panels · state", "generated TS bindings"]) | |
| 21 | +d.box(475, 100, 250, 115, "decider", "🔀", "internal/app", ["AgentService · ConfigService", "config ↔ agents glue"], badge="★ only API of the UI") | |
| 22 | +d.box(910, 100, 250, 115, "hook", "⚙️", "main.go (root)", ["flags · Wails app · window", "binds services and events"]) | |
| 21 | 23 | d.edge([(290, 157), (475, 157)], "bindings · events", at=(382, 157), lw=130, both=True) |
| 22 | 24 | d.edge([(910, 157), (725, 157)], "creates", at=(817, 157), lw=70) |
| 23 | 25 | |
| 24 | -# Row 2: the domain packages, all used by internal/app. | |
| 25 | -d.box(40, 300, 250, 110, "agent", "💬", "internal/channels", ["channels, members, routing", "@mentions · /agent:command"]) | |
| 26 | -d.box(330, 300, 250, 110, "agent", "🤖", "internal/agents", ["agent processes: lazy start,", "idle stop, limit, logs"]) | |
| 27 | -d.box(620, 300, 250, 110, "agent", "📋", "internal/config", ["load · validate · watch", "save with comments"]) | |
| 28 | -d.box(910, 300, 250, 110, "agent", "🧰", "internal/workspace", ["files + exec: local,", "container, sbx"]) | |
| 26 | +# Row 2: the domain packages used by internal/app. | |
| 27 | +d.box(40, 300, 250, 110, "data", "💬", "internal/channels", ["planned · M3", "channels, routing, @ and /"]) | |
| 28 | +d.box(330, 300, 250, 110, "agent", "🤖", "internal/agents", ["lazy start · LRU limit", "idle stop · states · logs"]) | |
| 29 | +d.box(620, 300, 250, 110, "agent", "📋", "internal/config", ["load · validate · locate", "default file · save · watch"]) | |
| 30 | +d.box(910, 300, 250, 110, "data", "🧰", "internal/workspace", ["planned · M4", "files + exec: local, container, sbx"]) | |
| 29 | 31 | for cx in (165, 455, 745, 1035): |
| 30 | 32 | d.edge([(600, 215), (600, 255), (cx, 255), (cx, 300)]) |
| 31 | 33 | d.edge([(290, 355), (330, 355)]) |
| 32 | 34 | d.edge([(580, 355), (620, 355)]) |
| 33 | 35 | |
| 34 | -# Row 3: what the domain packages build on. | |
| 35 | -d.box(40, 480, 250, 105, "agent", "📥", "internal/store", ["Pebble: channels, messages,", "session ids"]) | |
| 36 | -d.box(330, 480, 250, 105, "agent", "🔧", "internal/acp", ["ACP v1 client wrapper", "SDK types stay inside"]) | |
| 37 | -d.box(620, 480, 250, 105, "agent", "🛡️", "schema", ["config JSON Schema", "ValidateConfig()"]) | |
| 38 | -d.edge([(165, 410), (165, 480)]) | |
| 39 | -d.edge([(455, 410), (455, 480)]) | |
| 40 | -d.edge([(745, 410), (745, 480)]) | |
| 36 | +# Row 3: what they build on. | |
| 37 | +d.box(40, 490, 250, 105, "data", "📥", "internal/store", ["planned · M3", "Pebble: channels, messages"]) | |
| 38 | +d.box(330, 490, 250, 105, "agent", "🔧", "internal/acp", ["ACP v1 client over stdio", "SDK types stay inside"]) | |
| 39 | +d.box(620, 490, 250, 105, "agent", "🛡️", "schema", ["config JSON Schema", "ValidateConfig()"]) | |
| 40 | +d.box(910, 490, 250, 105, "agent", "📋", "internal/events", ["event names + payloads", "Emitter interface"]) | |
| 41 | +d.edge([(165, 410), (165, 490)]) | |
| 42 | +d.edge([(455, 410), (455, 490)]) | |
| 43 | +d.edge([(745, 410), (745, 490)]) | |
| 44 | +d.edge([(560, 410), (560, 450), (1035, 450), (1035, 490)], "emits", at=(950, 450), lw=60) | |
| 41 | 45 | |
| 42 | 46 | # Row 4: third-party modules and external processes. |
| 43 | -d.chip(40, 655, 250, 50, "cockroachdb/pebble/v2") | |
| 44 | -d.chip(330, 655, 250, 50, "coder/acp-go-sdk → mm -acp") | |
| 45 | -d.chip(620, 655, 250, 50, "jsonschema/v6 · yaml/v3") | |
| 46 | -d.chip(910, 655, 250, 50, "creack/pty · docker · sbx") | |
| 47 | -d.edge([(165, 585), (165, 655)]) | |
| 48 | -d.edge([(455, 585), (455, 655)], "stdio", at=(500, 620), lw=50) | |
| 49 | -d.edge([(745, 585), (745, 655)]) | |
| 50 | -d.edge([(1035, 410), (1035, 655)]) | |
| 51 | -d.text(600, 750, "Third-party modules in grey. Wails v3 is imported by cmd/sidekicks and internal/app only.", 12.5, italic=True) | |
| 47 | +d.chip(40, 670, 250, 50, "cockroachdb/pebble/v2") | |
| 48 | +d.chip(330, 670, 250, 50, "coder/acp-go-sdk → mm -acp") | |
| 49 | +d.chip(620, 670, 250, 50, "jsonschema/v6 · yaml/v3") | |
| 50 | +d.chip(910, 670, 250, 50, "fsnotify (config watch)") | |
| 51 | +d.edge([(165, 595), (165, 670)], dashed=True) | |
| 52 | +d.edge([(455, 595), (455, 670)], "stdio", at=(500, 632), lw=50) | |
| 53 | +d.edge([(745, 595), (745, 670)]) | |
| 54 | +d.text(600, 765, "internal/app also emits through internal/events; internal/config imports schema and fsnotify. Third-party modules in grey chips.", 12.5, italic=True) | |
| 52 | 55 | d.write(OUT) |
| @@ -1,7 +1,9 @@ | |||
| 1 | """The description of docs/diagrams/packages.{drawio,svg} (Sidekicks, ADR 0003). | 1 | """The description of docs/diagrams/packages.{drawio,svg} (Sidekicks, ADR 0003). |
| 2 | 2 | ||
| 3 | python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams | 3 | python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams |
| 4 | - rsvg-convert -w 1200 -h 780 -o docs/diagrams/packages.png docs/diagrams/packages.svg | 4 | + rsvg-convert -w 1200 -h 800 -o docs/diagrams/packages.png docs/diagrams/packages.svg |
| 5 | + | ||
| 6 | +Blue boxes exist; grey boxes are planned (their milestone is written in them). | ||
| 5 | """ | 7 | """ |
| 6 | import os | 8 | import os |
| 7 | import sys | 9 | import sys |
| @@ -12,41 +14,42 @@ from flowgen import Diagram | |||
| 12 | OUT = sys.argv[1] if len(sys.argv) > 1 else "docs/diagrams" | 14 | OUT = sys.argv[1] if len(sys.argv) > 1 else "docs/diagrams" |
| 13 | 15 | ||
| 14 | d = Diagram("packages", "Sidekicks — packages and dependencies", | 16 | d = Diagram("packages", "Sidekicks — packages and dependencies", |
| 15 | - "arrows are imports · the frontend only talks to internal/app · nothing outside internal/acp sees the ACP SDK", height=780) | 17 | + "arrows are imports · blue: exists (M1) · grey: planned · only main.go imports Wails", height=800) |
| 16 | 18 | ||
| 17 | # Row 1: the entry points. | 19 | # Row 1: the entry points. |
| 18 | -d.box(40, 100, 250, 115, "user", "💻", "frontend/", ["Svelte 5 · panels · Markdown", "CodeMirror · xterm.js"]) | 20 | +d.box(40, 100, 250, 115, "user", "💻", "frontend/", ["Svelte 5 · panels · state", "generated TS bindings"]) |
| 19 | -d.box(475, 100, 250, 115, "decider", "🔀", "internal/app", ["Wails services bound to the UI", "typed events to the UI"], badge="★ only API of the UI") | 21 | +d.box(475, 100, 250, 115, "decider", "🔀", "internal/app", ["AgentService · ConfigService", "config ↔ agents glue"], badge="★ only API of the UI") |
| 20 | -d.box(910, 100, 250, 115, "data", "⚙️", "cmd/sidekicks", ["main: reads flags, wires", "the services, runs Wails"]) | 22 | +d.box(910, 100, 250, 115, "hook", "⚙️", "main.go (root)", ["flags · Wails app · window", "binds services and events"]) |
| 21 | d.edge([(290, 157), (475, 157)], "bindings · events", at=(382, 157), lw=130, both=True) | 23 | d.edge([(290, 157), (475, 157)], "bindings · events", at=(382, 157), lw=130, both=True) |
| 22 | d.edge([(910, 157), (725, 157)], "creates", at=(817, 157), lw=70) | 24 | d.edge([(910, 157), (725, 157)], "creates", at=(817, 157), lw=70) |
| 23 | 25 | ||
| 24 | -# Row 2: the domain packages, all used by internal/app. | 26 | +# Row 2: the domain packages used by internal/app. |
| 25 | -d.box(40, 300, 250, 110, "agent", "💬", "internal/channels", ["channels, members, routing", "@mentions · /agent:command"]) | 27 | +d.box(40, 300, 250, 110, "data", "💬", "internal/channels", ["planned · M3", "channels, routing, @ and /"]) |
| 26 | -d.box(330, 300, 250, 110, "agent", "🤖", "internal/agents", ["agent processes: lazy start,", "idle stop, limit, logs"]) | 28 | +d.box(330, 300, 250, 110, "agent", "🤖", "internal/agents", ["lazy start · LRU limit", "idle stop · states · logs"]) |
| 27 | -d.box(620, 300, 250, 110, "agent", "📋", "internal/config", ["load · validate · watch", "save with comments"]) | 29 | +d.box(620, 300, 250, 110, "agent", "📋", "internal/config", ["load · validate · locate", "default file · save · watch"]) |
| 28 | -d.box(910, 300, 250, 110, "agent", "🧰", "internal/workspace", ["files + exec: local,", "container, sbx"]) | 30 | +d.box(910, 300, 250, 110, "data", "🧰", "internal/workspace", ["planned · M4", "files + exec: local, container, sbx"]) |
| 29 | for cx in (165, 455, 745, 1035): | 31 | for cx in (165, 455, 745, 1035): |
| 30 | d.edge([(600, 215), (600, 255), (cx, 255), (cx, 300)]) | 32 | d.edge([(600, 215), (600, 255), (cx, 255), (cx, 300)]) |
| 31 | d.edge([(290, 355), (330, 355)]) | 33 | d.edge([(290, 355), (330, 355)]) |
| 32 | d.edge([(580, 355), (620, 355)]) | 34 | d.edge([(580, 355), (620, 355)]) |
| 33 | 35 | ||
| 34 | -# Row 3: what the domain packages build on. | 36 | +# Row 3: what they build on. |
| 35 | -d.box(40, 480, 250, 105, "agent", "📥", "internal/store", ["Pebble: channels, messages,", "session ids"]) | 37 | +d.box(40, 490, 250, 105, "data", "📥", "internal/store", ["planned · M3", "Pebble: channels, messages"]) |
| 36 | -d.box(330, 480, 250, 105, "agent", "🔧", "internal/acp", ["ACP v1 client wrapper", "SDK types stay inside"]) | 38 | +d.box(330, 490, 250, 105, "agent", "🔧", "internal/acp", ["ACP v1 client over stdio", "SDK types stay inside"]) |
| 37 | -d.box(620, 480, 250, 105, "agent", "🛡️", "schema", ["config JSON Schema", "ValidateConfig()"]) | 39 | +d.box(620, 490, 250, 105, "agent", "🛡️", "schema", ["config JSON Schema", "ValidateConfig()"]) |
| 38 | -d.edge([(165, 410), (165, 480)]) | 40 | +d.box(910, 490, 250, 105, "agent", "📋", "internal/events", ["event names + payloads", "Emitter interface"]) |
| 39 | -d.edge([(455, 410), (455, 480)]) | 41 | +d.edge([(165, 410), (165, 490)]) |
| 40 | -d.edge([(745, 410), (745, 480)]) | 42 | +d.edge([(455, 410), (455, 490)]) |
| 43 | +d.edge([(745, 410), (745, 490)]) | ||
| 44 | +d.edge([(560, 410), (560, 450), (1035, 450), (1035, 490)], "emits", at=(950, 450), lw=60) | ||
| 41 | 45 | ||
| 42 | # Row 4: third-party modules and external processes. | 46 | # Row 4: third-party modules and external processes. |
| 43 | -d.chip(40, 655, 250, 50, "cockroachdb/pebble/v2") | 47 | +d.chip(40, 670, 250, 50, "cockroachdb/pebble/v2") |
| 44 | -d.chip(330, 655, 250, 50, "coder/acp-go-sdk → mm -acp") | 48 | +d.chip(330, 670, 250, 50, "coder/acp-go-sdk → mm -acp") |
| 45 | -d.chip(620, 655, 250, 50, "jsonschema/v6 · yaml/v3") | 49 | +d.chip(620, 670, 250, 50, "jsonschema/v6 · yaml/v3") |
| 46 | -d.chip(910, 655, 250, 50, "creack/pty · docker · sbx") | 50 | +d.chip(910, 670, 250, 50, "fsnotify (config watch)") |
| 47 | -d.edge([(165, 585), (165, 655)]) | 51 | +d.edge([(165, 595), (165, 670)], dashed=True) |
| 48 | -d.edge([(455, 585), (455, 655)], "stdio", at=(500, 620), lw=50) | 52 | +d.edge([(455, 595), (455, 670)], "stdio", at=(500, 632), lw=50) |
| 49 | -d.edge([(745, 585), (745, 655)]) | 53 | +d.edge([(745, 595), (745, 670)]) |
| 50 | -d.edge([(1035, 410), (1035, 655)]) | 54 | +d.text(600, 765, "internal/app also emits through internal/events; internal/config imports schema and fsnotify. Third-party modules in grey chips.", 12.5, italic=True) |
| 51 | -d.text(600, 750, "Third-party modules in grey. Wails v3 is imported by cmd/sidekicks and internal/app only.", 12.5, italic=True) | ||
| 52 | d.write(OUT) | 55 | d.write(OUT) |
added
.github/workflows/ci.yml +53 -0 | new file mode 100644 | ||
| @@ -0,0 +1,53 @@ | ||
| 1 | +# Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE | |
| 2 | +# | |
| 3 | +# Continuous integration: `make check` (lint + every test that needs no real | |
| 4 | +# agent) and a check that the committed TypeScript bindings are up to date. | |
| 5 | +# Rickub runs it as an ordinary GitHub Actions workflow, on every push and | |
| 6 | +# every merge request. No workflow_dispatch: Rickub's dispatch API fires every | |
| 7 | +# dispatchable workflow of a ref (see mini-me's release.yml). | |
| 8 | +name: CI | |
| 9 | + | |
| 10 | +on: | |
| 11 | + push: | |
| 12 | + pull_request: | |
| 13 | + | |
| 14 | +concurrency: | |
| 15 | + group: ci-${{ github.ref }} | |
| 16 | + cancel-in-progress: true | |
| 17 | + | |
| 18 | +jobs: | |
| 19 | + check: | |
| 20 | + runs-on: ubuntu-latest | |
| 21 | + steps: | |
| 22 | + - name: Checkout | |
| 23 | + uses: actions/checkout@v4 | |
| 24 | + | |
| 25 | + - name: Set up Go | |
| 26 | + uses: actions/setup-go@v5 | |
| 27 | + with: | |
| 28 | + go-version-file: go.mod | |
| 29 | + cache: true | |
| 30 | + | |
| 31 | + - name: Set up Node | |
| 32 | + uses: actions/setup-node@v4 | |
| 33 | + with: | |
| 34 | + node-version: "22" | |
| 35 | + | |
| 36 | + - name: Install pnpm (version from frontend/package.json) | |
| 37 | + run: npm install -g "$(node -p "require('./frontend/package.json').packageManager")" | |
| 38 | + | |
| 39 | + - name: Install the Wails build dependencies (GTK 4, WebKitGTK 6) | |
| 40 | + run: | | |
| 41 | + sudo apt-get update -qq | |
| 42 | + sudo apt-get install -y -qq pkg-config libgtk-4-dev libwebkitgtk-6.0-dev | |
| 43 | + | |
| 44 | + - name: Install the Wails CLI | |
| 45 | + run: | | |
| 46 | + go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0 | |
| 47 | + echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | |
| 48 | + | |
| 49 | + - name: Bindings are up to date | |
| 50 | + run: make bindings-check | |
| 51 | + | |
| 52 | + - name: Lint and tests | |
| 53 | + run: make check | |
| new file mode 100644 | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | +# Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE | ||
| 2 | +# | ||
| 3 | +# Continuous integration: `make check` (lint + every test that needs no real | ||
| 4 | +# agent) and a check that the committed TypeScript bindings are up to date. | ||
| 5 | +# Rickub runs it as an ordinary GitHub Actions workflow, on every push and | ||
| 6 | +# every merge request. No workflow_dispatch: Rickub's dispatch API fires every | ||
| 7 | +# dispatchable workflow of a ref (see mini-me's release.yml). | ||
| 8 | +name: CI | ||
| 9 | + | ||
| 10 | +on: | ||
| 11 | + push: | ||
| 12 | + pull_request: | ||
| 13 | + | ||
| 14 | +concurrency: | ||
| 15 | + group: ci-${{ github.ref }} | ||
| 16 | + cancel-in-progress: true | ||
| 17 | + | ||
| 18 | +jobs: | ||
| 19 | + check: | ||
| 20 | + runs-on: ubuntu-latest | ||
| 21 | + steps: | ||
| 22 | + - name: Checkout | ||
| 23 | + uses: actions/checkout@v4 | ||
| 24 | + | ||
| 25 | + - name: Set up Go | ||
| 26 | + uses: actions/setup-go@v5 | ||
| 27 | + with: | ||
| 28 | + go-version-file: go.mod | ||
| 29 | + cache: true | ||
| 30 | + | ||
| 31 | + - name: Set up Node | ||
| 32 | + uses: actions/setup-node@v4 | ||
| 33 | + with: | ||
| 34 | + node-version: "22" | ||
| 35 | + | ||
| 36 | + - name: Install pnpm (version from frontend/package.json) | ||
| 37 | + run: npm install -g "$(node -p "require('./frontend/package.json').packageManager")" | ||
| 38 | + | ||
| 39 | + - name: Install the Wails build dependencies (GTK 4, WebKitGTK 6) | ||
| 40 | + run: | | ||
| 41 | + sudo apt-get update -qq | ||
| 42 | + sudo apt-get install -y -qq pkg-config libgtk-4-dev libwebkitgtk-6.0-dev | ||
| 43 | + | ||
| 44 | + - name: Install the Wails CLI | ||
| 45 | + run: | | ||
| 46 | + go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0 | ||
| 47 | + echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | ||
| 48 | + | ||
| 49 | + - name: Bindings are up to date | ||
| 50 | + run: make bindings-check | ||
| 51 | + | ||
| 52 | + - name: Lint and tests | ||
| 53 | + run: make check | ||
modified
.gitignore +11 -0 | @@ -2,3 +2,14 @@ | ||
| 2 | 2 | .run/ |
| 3 | 3 | # macOS |
| 4 | 4 | .DS_Store |
| 5 | +# Wails / Task | |
| 6 | +.task | |
| 7 | +bin/ | |
| 8 | +frontend/dist | |
| 9 | +frontend/node_modules | |
| 10 | +build/linux/appimage/build | |
| 11 | +build/windows/nsis/MicrosoftEdgeWebview2Setup.exe | |
| 12 | +# pnpm content-addressable store (created next to the repository when it sits on another file system) | |
| 13 | +.pnpm-store/ | |
| 14 | +# Local scratch files (machine-specific configurations…) | |
| 15 | +tmp/ | |
| @@ -2,3 +2,14 @@ | |||
| 2 | .run/ | 2 | .run/ |
| 3 | # macOS | 3 | # macOS |
| 4 | .DS_Store | 4 | .DS_Store |
| 5 | +# Wails / Task | ||
| 6 | +.task | ||
| 7 | +bin/ | ||
| 8 | +frontend/dist | ||
| 9 | +frontend/node_modules | ||
| 10 | +build/linux/appimage/build | ||
| 11 | +build/windows/nsis/MicrosoftEdgeWebview2Setup.exe | ||
| 12 | +# pnpm content-addressable store (created next to the repository when it sits on another file system) | ||
| 13 | +.pnpm-store/ | ||
| 14 | +# Local scratch files (machine-specific configurations…) | ||
| 15 | +tmp/ | ||
added
.golangci.yml +33 -0 | new file mode 100644 | ||
| @@ -0,0 +1,33 @@ | ||
| 1 | +# Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE | |
| 2 | +# | |
| 3 | +# golangci-lint v2, pinned in tools/go.mod and run with `make lint`. | |
| 4 | +version: "2" | |
| 5 | + | |
| 6 | +linters: | |
| 7 | + default: standard # errcheck, govet, ineffassign, staticcheck, unused | |
| 8 | + enable: | |
| 9 | + - errorlint # errors compared with errors.Is / errors.As | |
| 10 | + - gocyclo # functions a person can still follow | |
| 11 | + - misspell | |
| 12 | + - revive # doc comments and naming of exported identifiers | |
| 13 | + - unconvert | |
| 14 | + - unparam | |
| 15 | + settings: | |
| 16 | + gocyclo: | |
| 17 | + min-complexity: 15 | |
| 18 | + misspell: | |
| 19 | + # No locale: British and American spellings are both accepted (the ACP | |
| 20 | + # SDK itself says "Cancelled"); only real misspellings are reported. | |
| 21 | + ignore-rules: | |
| 22 | + # French words of the default configuration file (internal/config/default.go) | |
| 23 | + - assistante | |
| 24 | + - exemple | |
| 25 | + - programme | |
| 26 | + - marrage | |
| 27 | + exclusions: | |
| 28 | + paths: | |
| 29 | + - spikes # throwaway prototypes, separate modules | |
| 30 | + | |
| 31 | +formatters: | |
| 32 | + enable: | |
| 33 | + - gofmt | |
| new file mode 100644 | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | +# Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE | ||
| 2 | +# | ||
| 3 | +# golangci-lint v2, pinned in tools/go.mod and run with `make lint`. | ||
| 4 | +version: "2" | ||
| 5 | + | ||
| 6 | +linters: | ||
| 7 | + default: standard # errcheck, govet, ineffassign, staticcheck, unused | ||
| 8 | + enable: | ||
| 9 | + - errorlint # errors compared with errors.Is / errors.As | ||
| 10 | + - gocyclo # functions a person can still follow | ||
| 11 | + - misspell | ||
| 12 | + - revive # doc comments and naming of exported identifiers | ||
| 13 | + - unconvert | ||
| 14 | + - unparam | ||
| 15 | + settings: | ||
| 16 | + gocyclo: | ||
| 17 | + min-complexity: 15 | ||
| 18 | + misspell: | ||
| 19 | + # No locale: British and American spellings are both accepted (the ACP | ||
| 20 | + # SDK itself says "Cancelled"); only real misspellings are reported. | ||
| 21 | + ignore-rules: | ||
| 22 | + # French words of the default configuration file (internal/config/default.go) | ||
| 23 | + - assistante | ||
| 24 | + - exemple | ||
| 25 | + - programme | ||
| 26 | + - marrage | ||
| 27 | + exclusions: | ||
| 28 | + paths: | ||
| 29 | + - spikes # throwaway prototypes, separate modules | ||
| 30 | + | ||
| 31 | +formatters: | ||
| 32 | + enable: | ||
| 33 | + - gofmt | ||
modified
.memory/handoffs/2026-10-29-milestone-initialize.md +1 -1 | @@ -10,7 +10,7 @@ Initialize is implemented on branch `feature/initialize` (not committed by the a | ||
| 10 | 10 | |
| 11 | 11 | ## Next steps |
| 12 | 12 | |
| 13 | -1. Owner: merge `feature/initialize`, then create the M1 branch. | |
| 13 | +1. Done: `feature/initialize` merged; M1 continues in `handoffs/2026-10-29-milestone-m1.md`. | |
| 14 | 14 | 2. Owner: decide whether to run the qlty gate (needs a sandbox with the dev-toolkit kit) before M1. |
| 15 | 15 | 3. Start M1 with #8 (project from `wails3 init -t svelte`, merged into the existing root `go.mod`; keep the Makefile as entry point; licence headers), then #9 (loader on top of `schema`), #10 (`internal/acp` wrapping coder/acp-go-sdk; `realagents` build tag), #11, #12, #13. |
| 16 | 16 | |
| @@ -10,7 +10,7 @@ Initialize is implemented on branch `feature/initialize` (not committed by the a | |||
| 10 | 10 | ||
| 11 | ## Next steps | 11 | ## Next steps |
| 12 | 12 | ||
| 13 | -1. Owner: merge `feature/initialize`, then create the M1 branch. | 13 | +1. Done: `feature/initialize` merged; M1 continues in `handoffs/2026-10-29-milestone-m1.md`. |
| 14 | 2. Owner: decide whether to run the qlty gate (needs a sandbox with the dev-toolkit kit) before M1. | 14 | 2. Owner: decide whether to run the qlty gate (needs a sandbox with the dev-toolkit kit) before M1. |
| 15 | 3. Start M1 with #8 (project from `wails3 init -t svelte`, merged into the existing root `go.mod`; keep the Makefile as entry point; licence headers), then #9 (loader on top of `schema`), #10 (`internal/acp` wrapping coder/acp-go-sdk; `realagents` build tag), #11, #12, #13. | 15 | 3. Start M1 with #8 (project from `wails3 init -t svelte`, merged into the existing root `go.mod`; keep the Makefile as entry point; licence headers), then #9 (loader on top of `schema`), #10 (`internal/acp` wrapping coder/acp-go-sdk; `realagents` build tag), #11, #12, #13. |
| 16 | 16 | ||
added
.memory/handoffs/2026-10-29-milestone-m1.md +31 -0 | new file mode 100644 | ||
| @@ -0,0 +1,31 @@ | ||
| 1 | +# Handoff — 2026-10-29 — milestone M1 · Fondations | |
| 2 | + | |
| 3 | +## State | |
| 4 | + | |
| 5 | +M1 is done and validated by the owner on macOS; first commit made by the owner on `feature/m1-foundations`. Issues #8–#13 and milestone "M1 · Fondations" closed. | |
| 6 | + | |
| 7 | +## In flight | |
| 8 | + | |
| 9 | +- First push: check that `.github/workflows/ci.yml` runs on rickub (ubuntu-latest must provide `libwebkitgtk-6.0-dev`). | |
| 10 | + | |
| 11 | +## Next steps | |
| 12 | + | |
| 13 | +1. M2 · Conversation avec un agent: #14 (sessions + prompt turn + streaming in `internal/acp`, the `client` handler must route `SessionUpdate`/`RequestPermission` to sessions), #15 (conversation view + composer), #16 (Markdown/Shiki/DOMPurify — reuse `spikes/wails-ui/frontend/src/lib/markdown.ts`), #17 (tool calls + permissions, see ADR 0001 fact 4), #18 (Settings YAML editor, `config.Save`), #19 (open another config file; `config.Locate` already takes `lastOpened`). | |
| 14 | +2. #38: qlty kit. | |
| 15 | + | |
| 16 | +## Open questions / blockers | |
| 17 | + | |
| 18 | +- qlty unavailable (by design of the quality skill: do not install by hand). | |
| 19 | +- `make` targets need `wails3` and `pnpm` on PATH (`$(go env GOPATH)/bin`, `npm i -g pnpm@12.11.2`). | |
| 20 | + | |
| 21 | +## Watch out for | |
| 22 | + | |
| 23 | +- **Never nest heredocs** in a Bash tool call (`<<'EOF'` containing `<<EOF`): the outer one ends at the inner EOF and the rest runs as shell. Use the Write tool for any file containing a heredoc. | |
| 24 | +- `rm` with a glob after `cd` is blocked by a safety check: copy only what is needed instead. | |
| 25 | +- Timestamps in `.tickets/`: use `date -u` (UTC), not the local hour. | |
| 26 | +- `frontend/node_modules` is shared with the Mac: only `pnpm install` (never npm), thanks to `pnpm-workspace.yaml` both platforms' binaries are present. | |
| 27 | +- macOS detection: never rely on `System.IsMac()` alone at startup (Wails environment arrives asynchronously); use `isMac()` from `frontend/src/lib/theme.ts`. | |
| 28 | +- Svelte 5: a module export named `state` conflicts with the `$state` rune — the shared state is `appState`. | |
| 29 | +- `go test ./...` needs `frontend/dist` (embed in main.go): `make test-go` builds it if missing. | |
| 30 | +- Bindings are generated with `-ts -i` (interfaces); `wails3 generate bindings -clean=true -ts -i` is stable (no diff on re-run). | |
| 31 | +- The SDK logs "connection closed" via slog: silenced in `internal/acp`. | |
| new file mode 100644 | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | +# Handoff — 2026-10-29 — milestone M1 · Fondations | ||
| 2 | + | ||
| 3 | +## State | ||
| 4 | + | ||
| 5 | +M1 is done and validated by the owner on macOS; first commit made by the owner on `feature/m1-foundations`. Issues #8–#13 and milestone "M1 · Fondations" closed. | ||
| 6 | + | ||
| 7 | +## In flight | ||
| 8 | + | ||
| 9 | +- First push: check that `.github/workflows/ci.yml` runs on rickub (ubuntu-latest must provide `libwebkitgtk-6.0-dev`). | ||
| 10 | + | ||
| 11 | +## Next steps | ||
| 12 | + | ||
| 13 | +1. M2 · Conversation avec un agent: #14 (sessions + prompt turn + streaming in `internal/acp`, the `client` handler must route `SessionUpdate`/`RequestPermission` to sessions), #15 (conversation view + composer), #16 (Markdown/Shiki/DOMPurify — reuse `spikes/wails-ui/frontend/src/lib/markdown.ts`), #17 (tool calls + permissions, see ADR 0001 fact 4), #18 (Settings YAML editor, `config.Save`), #19 (open another config file; `config.Locate` already takes `lastOpened`). | ||
| 14 | +2. #38: qlty kit. | ||
| 15 | + | ||
| 16 | +## Open questions / blockers | ||
| 17 | + | ||
| 18 | +- qlty unavailable (by design of the quality skill: do not install by hand). | ||
| 19 | +- `make` targets need `wails3` and `pnpm` on PATH (`$(go env GOPATH)/bin`, `npm i -g pnpm@12.11.2`). | ||
| 20 | + | ||
| 21 | +## Watch out for | ||
| 22 | + | ||
| 23 | +- **Never nest heredocs** in a Bash tool call (`<<'EOF'` containing `<<EOF`): the outer one ends at the inner EOF and the rest runs as shell. Use the Write tool for any file containing a heredoc. | ||
| 24 | +- `rm` with a glob after `cd` is blocked by a safety check: copy only what is needed instead. | ||
| 25 | +- Timestamps in `.tickets/`: use `date -u` (UTC), not the local hour. | ||
| 26 | +- `frontend/node_modules` is shared with the Mac: only `pnpm install` (never npm), thanks to `pnpm-workspace.yaml` both platforms' binaries are present. | ||
| 27 | +- macOS detection: never rely on `System.IsMac()` alone at startup (Wails environment arrives asynchronously); use `isMac()` from `frontend/src/lib/theme.ts`. | ||
| 28 | +- Svelte 5: a module export named `state` conflicts with the `$state` rune — the shared state is `appState`. | ||
| 29 | +- `go test ./...` needs `frontend/dist` (embed in main.go): `make test-go` builds it if missing. | ||
| 30 | +- Bindings are generated with `-ts -i` (interfaces); `wails3 generate bindings -clean=true -ts -i` is stable (no diff on re-run). | ||
| 31 | +- The SDK logs "connection closed" via slog: silenced in `internal/acp`. | ||
modified
.memory/history.md +25 -0 | @@ -34,3 +34,28 @@ | ||
| 34 | 34 | |
| 35 | 35 | - **Goal**: after the owner's successful macOS check, close #3 and the milestone. |
| 36 | 36 | - **Changes**: #3 last task closed + result comment, issue closed; milestone `Initialize` → closed; ADR 0002 status "verified on macOS"; prototype README updated; `.memory/` summary and handoff updated. No commit by the agent (the owner commits and merges). |
| 37 | + | |
| 38 | +## 2026-10-29 — Milestone M1 · Fondations (#8–#13) | |
| 39 | + | |
| 40 | +- **Goal**: implement M1 in one go (owner's choice), with CI on rickub Actions, pnpm + supportedArchitectures, golangci-lint as go tool, and a ticket for a qlty kit. | |
| 41 | +- **Changes**: ticket #38 (qlty kit); root Wails v3 project (`main.go`, `Taskfile.yml`, `build/`, `frontend/`); `internal/{events,config,acp,agents,app}`; frontend shell (paneforge, panel registry, Agents/Channels/Conversation/Settings/Journal panels, status bar, theme, macOS inset); `Makefile` rewrite; `tools/go.mod` + `.golangci.yml`; `scripts/check-license-headers.sh` (+tests); `.github/workflows/ci.yml`; README; schema fix (`stopIdleAgentsAfter: 0` as a number); ADR 0003 Amendment 1; package diagram; docs EN/FR (tutorial first launch, how-to develop / run tests / test M1 on macOS, references commands + agents-and-events, updated configuration/architecture/memory); tickets #8–#11, #13 closed, #12 open. | |
| 42 | +- **Decisions**: main at the root instead of `cmd/sidekicks` (Wails Taskfiles build `.`); Wails imported only by main.go (internal/app testable without cgo); LRU eviction of an idle agent when the limit is reached, refuse only if all busy; crash never auto-restarts; config channels exposed read-only until M3; bindings committed + `bindings-check` in CI; go.yaml.in/yaml/v3 instead of gopkg.in/yaml.v3; misspell without locale (SDK uses "Cancelled"), French words ignored by explicit rule. | |
| 43 | +- **Tests**: Go (events, config 20+, acp with a self-exec fake agent, agents with fake clock, app) all pass with `-race`; vitest 8; shell 14 + 5; real Alice handshake (`make test-real`) OK; app run under Xvfb: config load, start Alice from the panel, journal, invalid config + live fix, quit stops agents. | |
| 44 | +- **Quality**: golangci-lint 0 issues, svelte-check 0/0, licence headers ok. qlty not available (see #38). | |
| 45 | +- **Docs**: see Changes; all links checked, no FR→EN link. | |
| 46 | + | |
| 47 | +## 2026-10-29 — macOS feedback on M1: traffic lights over "CHANNELS" again | |
| 48 | + | |
| 49 | +- **Cause**: `System.IsMac()` reads `window._wails.environment`, filled asynchronously by the Wails runtime; at page load it can still be empty, so the `macos` class (and `--titlebar-inset`) was set or not depending on timing. | |
| 50 | +- **Fix**: `isMac(System.IsMac(), navigator.userAgent)` in `frontend/src/lib/theme.ts` (WKWebView's user agent contains "Macintosh"), 3 vitest cases; comment on #12. Not yet re-checked on the Mac. | |
| 51 | +- **Docs**: M1 macOS guide (EN/FR) — Settings shows the full path; `open '~/…'` in quotes does not expand `~`; added `open` and restore commands. | |
| 52 | + | |
| 53 | +## 2026-10-29 — Default configuration with the test agents | |
| 54 | + | |
| 55 | +- **Goal**: make the default configuration work with the test agents (owner's request), and give the owner a ready file in `./tmp`. | |
| 56 | +- **Changes**: `scripts/install-test-config.sh` + `make install-test-config` (writes examples/test-agents.yaml at the default location with absolute repo paths and `MM_BIN`/`PATH` in each agent's env — an app opened from the Finder gets a minimal PATH and finds neither mm nor jq; keeps an existing file as `.bak`); Go test `internal/config/testconfig_test.go`; docs (commands reference, M1 guide, develop guide, EN/FR). `tmp/config.yaml` generated for the Mac (MM_BIN=/usr/local/bin/mm, PATH with /opt/homebrew/bin); `tmp/` git-ignored. | |
| 57 | +- **Tests**: Go test passes; app started without --config and with `env -i PATH=/usr/bin:/bin` → Alice starts. | |
| 58 | + | |
| 59 | +## 2026-10-29 — M1 closed | |
| 60 | + | |
| 61 | +- Owner validated M1 on macOS and committed. Closed #12 (last task + comment) and milestone "M1 · Fondations"; summary and M1 handoff updated. #38 (qlty kit) stays open. | |
| @@ -34,3 +34,28 @@ | |||
| 34 | 34 | ||
| 35 | - **Goal**: after the owner's successful macOS check, close #3 and the milestone. | 35 | - **Goal**: after the owner's successful macOS check, close #3 and the milestone. |
| 36 | - **Changes**: #3 last task closed + result comment, issue closed; milestone `Initialize` → closed; ADR 0002 status "verified on macOS"; prototype README updated; `.memory/` summary and handoff updated. No commit by the agent (the owner commits and merges). | 36 | - **Changes**: #3 last task closed + result comment, issue closed; milestone `Initialize` → closed; ADR 0002 status "verified on macOS"; prototype README updated; `.memory/` summary and handoff updated. No commit by the agent (the owner commits and merges). |
| 37 | + | ||
| 38 | +## 2026-10-29 — Milestone M1 · Fondations (#8–#13) | ||
| 39 | + | ||
| 40 | +- **Goal**: implement M1 in one go (owner's choice), with CI on rickub Actions, pnpm + supportedArchitectures, golangci-lint as go tool, and a ticket for a qlty kit. | ||
| 41 | +- **Changes**: ticket #38 (qlty kit); root Wails v3 project (`main.go`, `Taskfile.yml`, `build/`, `frontend/`); `internal/{events,config,acp,agents,app}`; frontend shell (paneforge, panel registry, Agents/Channels/Conversation/Settings/Journal panels, status bar, theme, macOS inset); `Makefile` rewrite; `tools/go.mod` + `.golangci.yml`; `scripts/check-license-headers.sh` (+tests); `.github/workflows/ci.yml`; README; schema fix (`stopIdleAgentsAfter: 0` as a number); ADR 0003 Amendment 1; package diagram; docs EN/FR (tutorial first launch, how-to develop / run tests / test M1 on macOS, references commands + agents-and-events, updated configuration/architecture/memory); tickets #8–#11, #13 closed, #12 open. | ||
| 42 | +- **Decisions**: main at the root instead of `cmd/sidekicks` (Wails Taskfiles build `.`); Wails imported only by main.go (internal/app testable without cgo); LRU eviction of an idle agent when the limit is reached, refuse only if all busy; crash never auto-restarts; config channels exposed read-only until M3; bindings committed + `bindings-check` in CI; go.yaml.in/yaml/v3 instead of gopkg.in/yaml.v3; misspell without locale (SDK uses "Cancelled"), French words ignored by explicit rule. | ||
| 43 | +- **Tests**: Go (events, config 20+, acp with a self-exec fake agent, agents with fake clock, app) all pass with `-race`; vitest 8; shell 14 + 5; real Alice handshake (`make test-real`) OK; app run under Xvfb: config load, start Alice from the panel, journal, invalid config + live fix, quit stops agents. | ||
| 44 | +- **Quality**: golangci-lint 0 issues, svelte-check 0/0, licence headers ok. qlty not available (see #38). | ||
| 45 | +- **Docs**: see Changes; all links checked, no FR→EN link. | ||
| 46 | + | ||
| 47 | +## 2026-10-29 — macOS feedback on M1: traffic lights over "CHANNELS" again | ||
| 48 | + | ||
| 49 | +- **Cause**: `System.IsMac()` reads `window._wails.environment`, filled asynchronously by the Wails runtime; at page load it can still be empty, so the `macos` class (and `--titlebar-inset`) was set or not depending on timing. | ||
| 50 | +- **Fix**: `isMac(System.IsMac(), navigator.userAgent)` in `frontend/src/lib/theme.ts` (WKWebView's user agent contains "Macintosh"), 3 vitest cases; comment on #12. Not yet re-checked on the Mac. | ||
| 51 | +- **Docs**: M1 macOS guide (EN/FR) — Settings shows the full path; `open '~/…'` in quotes does not expand `~`; added `open` and restore commands. | ||
| 52 | + | ||
| 53 | +## 2026-10-29 — Default configuration with the test agents | ||
| 54 | + | ||
| 55 | +- **Goal**: make the default configuration work with the test agents (owner's request), and give the owner a ready file in `./tmp`. | ||
| 56 | +- **Changes**: `scripts/install-test-config.sh` + `make install-test-config` (writes examples/test-agents.yaml at the default location with absolute repo paths and `MM_BIN`/`PATH` in each agent's env — an app opened from the Finder gets a minimal PATH and finds neither mm nor jq; keeps an existing file as `.bak`); Go test `internal/config/testconfig_test.go`; docs (commands reference, M1 guide, develop guide, EN/FR). `tmp/config.yaml` generated for the Mac (MM_BIN=/usr/local/bin/mm, PATH with /opt/homebrew/bin); `tmp/` git-ignored. | ||
| 57 | +- **Tests**: Go test passes; app started without --config and with `env -i PATH=/usr/bin:/bin` → Alice starts. | ||
| 58 | + | ||
| 59 | +## 2026-10-29 — M1 closed | ||
| 60 | + | ||
| 61 | +- Owner validated M1 on macOS and committed. Closed #12 (last task + comment) and milestone "M1 · Fondations"; summary and M1 handoff updated. #38 (qlty kit) stays open. | ||
modified
.memory/summary.md +19 -15 | @@ -4,23 +4,25 @@ | ||
| 4 | 4 | |
| 5 | 5 | A desktop application (Go + Wails) to talk with AI agents in channels, for non-technical ("citizen") users. Agent-agnostic: every agent is reached over the Agent Client Protocol (ACP, JSON-RPC on stdio). Full brief: `.tickets/issues/0001-draft.yaml`; backlog of 36 issues, 9 epics, 6 milestones in `.tickets/` (IssueSpec format, see `.claude/skills/issuespec`). |
| 6 | 6 | |
| 7 | -## State (2026-10-29) | |
| 7 | +## State (2026-10-29, end of M1) | |
| 8 | 8 | |
| 9 | -Milestone **Initialize** is closed (issues #2–#7 closed; the UI prototype was verified on macOS by the owner). There is **no application code yet**; M1 (issues #8–#13) starts it. | |
| 9 | +Milestones **Initialize** and **M1 · Fondations** are closed (M1 validated by the owner on macOS; issues #8–#13 closed). The application opens, loads/validates/watches its configuration, lists the agents, starts/stops them over ACP (lazy start, LRU limit, idle stop, crash → error), shows states and stderr logs. **No conversation yet**: next is M2 (#14–#19). Open outside milestones: #26 (spike agent→agent), #38 (qlty kit). | |
| 10 | 10 | |
| 11 | 11 | What exists: |
| 12 | 12 | |
| 13 | -- `scripts/agents.sh` — the only way to start test agents: `run <agent>` (stdio pass-through, max 2 simultaneous, unloads the model at exit), `ps`, `unload`, `model`, `list`. | |
| 14 | -- `schema/` — Go package (`git.rickub.com/bots-garden/sidekicks/schema`): configuration JSON Schema + `ValidateConfig`. | |
| 15 | -- `examples/test-agents.yaml` — a valid configuration with the 4 test agents (through `scripts/agents.sh`). | |
| 16 | -- `spikes/acp-trace` (ACP trace client), `spikes/wails-ui` (Wails v3 + Svelte prototype) — throwaway, separate Go modules. | |
| 17 | -- `docs/adr/0001..0003`, `docs/design/` (6 wireframes, draw.io), `docs/diagrams/packages.drawio`, `docs/en|fr/` (Diátaxis). | |
| 13 | +- `main.go` (root, only file importing Wails) · `internal/app` (AgentService, ConfigService, Core) · `internal/agents` (Manager) · `internal/acp` (ACP v1 client) · `internal/config` · `internal/events` · `schema`. | |
| 14 | +- `frontend/`: Svelte 5 + paneforge shell, panel registry (`src/lib/panels/index.ts`), shared state (`src/lib/state.svelte.ts`, `appState`), generated bindings committed in `frontend/bindings`. | |
| 15 | +- Tooling: `Makefile` (entry point), golangci-lint in `tools/go.mod`, `.golangci.yml`, `scripts/check-license-headers.sh`, CI `.github/workflows/ci.yml` (not yet seen running on rickub). | |
| 16 | +- `scripts/agents.sh`, `examples/test-agents.yaml`, `spikes/` (Initialize), docs EN/FR, ADRs, wireframes. | |
| 18 | 17 | |
| 19 | 18 | ## Decisions in force |
| 20 | 19 | |
| 21 | 20 | - ACP **v1**, via `github.com/coder/acp-go-sdk` v0.13.5, wrapped in `internal/acp` (ADR 0001). One ACP session per (channel, agent). |
| 22 | 21 | - **Wails v3.0.0**, Svelte 5 + TS, paneforge, markdown-it + Shiki (JS engine) + DOMPurify, CodeMirror 6, xterm.js + creack/pty (ADR 0002). Markdown rendered at most once per animation frame. macOS hidden-inset title bar: content near the top-left is padded by `--titlebar-inset` (38px under `:root.macos`, = `InvisibleTitleBarHeight`). |
| 23 | -- Packages and data model: ADR 0003. YAML = what exists; Pebble v2 = what happens, one DB per config file; channels live only in Pebble (YAML-declared ones are created once). Messages written at end of turn. | |
| 22 | +- Packages and data model: ADR 0003 + Amendment 1 (main at the root, only main.go imports Wails, `internal/events` with an `Emitter` interface, LRU eviction of idle agents at the limit). | |
| 23 | +- Frontend dependencies with **pnpm 12.11.2** and `frontend/pnpm-workspace.yaml` `supportedArchitectures` (darwin+linux): the repository folder is shared between the Mac and the Linux sandbox. Never use npm in `frontend/`. | |
| 24 | +- Go deps: wails v3.0.0, coder/acp-go-sdk v0.13.5, go.yaml.in/yaml/v3, santhosh-tekuri/jsonschema/v6, fsnotify; go.mod says `go 1.26.0`. | |
| 25 | +- Packages and data model (initial): ADR 0003. YAML = what exists; Pebble v2 = what happens, one DB per config file; channels live only in Pebble (YAML-declared ones are created once). Messages written at end of turn. | |
| 24 | 26 | - Config format v1: `docs/en/reference/configuration.md`; unknown keys are errors; cross-entry rules belong to the loader (#9). |
| 25 | 27 | - Licence: custom source-available (`LICENSE`). Every hand-written source file starts with the one-line header `Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE` (comment syntax of the language); not on generated files nor on the owner's root scripts (`git.sh`, `new.*.sh`, `tag-step.sh`). |
| 26 | 28 | - ADRs and specs in English; docs bilingual EN + FR; tickets in French. |
| @@ -29,12 +31,13 @@ What exists: | ||
| 29 | 31 | |
| 30 | 32 | | | | |
| 31 | 33 | | --- | --- | |
| 32 | -| All tests | `make test` (Go `go test ./...` + `scripts/agents_test.sh`; no network, no real agent) | | |
| 33 | -| Test agents | `scripts/agents.sh run alice` · `ps` · `unload --all` (needs `mm` on PATH or `MM_BIN`, llmman on 127.0.0.1:17434 or host.docker.internal:17434) | | |
| 34 | -| ACP trace | `cd spikes/acp-trace && go run . -agent alice -prompt "…" -out /tmp/t.jsonl` | | |
| 35 | -| UI prototype | `cd spikes/wails-ui && wails3 dev` (macOS) ; Linux build needs `pkg-config libgtk-4-dev libwebkitgtk-6.0-dev` | | |
| 36 | -| Wireframes | `python3 docs/design/wireframes.py` then `rsvg-convert` each SVG | | |
| 37 | -| Package diagram | `python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams` then `rsvg-convert -w 1200 -h 780` | | |
| 34 | +| Everything the CI runs | `make check` (lint + tests; needs `wails3`, `pnpm`, GTK/WebKit dev packages on Linux) | | |
| 35 | +| Tests only | `make test` (Go + vitest + shell) · real agents: `make test-real` | | |
| 36 | +| Run | `SIDEKICKS_CONFIG="$PWD/examples/test-agents.yaml" make dev` · build `make build` · macOS app `make package` | | |
| 37 | +| Bindings | `make bindings` after changing a service/event; CI runs `make bindings-check` | | |
| 38 | +| Test agents | `scripts/agents.sh run alice` · `ps` · `unload --all` (`MM_BIN`, llmman on 127.0.0.1 or host.docker.internal:17434) | | |
| 39 | +| Headless UI check (sandbox) | `Xvfb :97`, `GDK_BACKEND=x11 WEBKIT_DISABLE_DMABUF_RENDERER=1 dbus-launch bin/sidekicks --config …`, `xdotool`, `import -window root` | | |
| 40 | +| Wireframes / package diagram | `python3 docs/design/wireframes.py` · `python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams` + `rsvg-convert -w 1200 -h 800` | | |
| 38 | 41 | |
| 39 | 42 | ## Facts about the test agents (mm v1.0.3) |
| 40 | 43 | |
| @@ -45,5 +48,6 @@ What exists: | ||
| 45 | 48 | ## Not yet established |
| 46 | 49 | |
| 47 | 50 | - How to exec a shell / read files inside an `sbx` sandbox (issue #28). |
| 48 | -- Quality gate: `qlty` was not installed in the 2026-10-29 sandbox, so no qlty measurement exists yet (`.quality/` absent). | |
| 51 | +- Quality gate: `qlty` is not in this sandbox → no qlty measurement yet (issue #38: build a sandbox kit with qlty). golangci-lint (go tool) is the stopgap. | |
| 52 | +- Whether the CI workflow runs as-is on rickub (first push of `feature/m1-foundations`). | |
| 49 | 53 | - Whether `.claude/skills/*` (kit files) should be committed with the project is the owner's call. |
| @@ -4,23 +4,25 @@ | |||
| 4 | 4 | ||
| 5 | A desktop application (Go + Wails) to talk with AI agents in channels, for non-technical ("citizen") users. Agent-agnostic: every agent is reached over the Agent Client Protocol (ACP, JSON-RPC on stdio). Full brief: `.tickets/issues/0001-draft.yaml`; backlog of 36 issues, 9 epics, 6 milestones in `.tickets/` (IssueSpec format, see `.claude/skills/issuespec`). | 5 | A desktop application (Go + Wails) to talk with AI agents in channels, for non-technical ("citizen") users. Agent-agnostic: every agent is reached over the Agent Client Protocol (ACP, JSON-RPC on stdio). Full brief: `.tickets/issues/0001-draft.yaml`; backlog of 36 issues, 9 epics, 6 milestones in `.tickets/` (IssueSpec format, see `.claude/skills/issuespec`). |
| 6 | 6 | ||
| 7 | -## State (2026-10-29) | 7 | +## State (2026-10-29, end of M1) |
| 8 | 8 | ||
| 9 | -Milestone **Initialize** is closed (issues #2–#7 closed; the UI prototype was verified on macOS by the owner). There is **no application code yet**; M1 (issues #8–#13) starts it. | 9 | +Milestones **Initialize** and **M1 · Fondations** are closed (M1 validated by the owner on macOS; issues #8–#13 closed). The application opens, loads/validates/watches its configuration, lists the agents, starts/stops them over ACP (lazy start, LRU limit, idle stop, crash → error), shows states and stderr logs. **No conversation yet**: next is M2 (#14–#19). Open outside milestones: #26 (spike agent→agent), #38 (qlty kit). |
| 10 | 10 | ||
| 11 | What exists: | 11 | What exists: |
| 12 | 12 | ||
| 13 | -- `scripts/agents.sh` — the only way to start test agents: `run <agent>` (stdio pass-through, max 2 simultaneous, unloads the model at exit), `ps`, `unload`, `model`, `list`. | 13 | +- `main.go` (root, only file importing Wails) · `internal/app` (AgentService, ConfigService, Core) · `internal/agents` (Manager) · `internal/acp` (ACP v1 client) · `internal/config` · `internal/events` · `schema`. |
| 14 | -- `schema/` — Go package (`git.rickub.com/bots-garden/sidekicks/schema`): configuration JSON Schema + `ValidateConfig`. | 14 | +- `frontend/`: Svelte 5 + paneforge shell, panel registry (`src/lib/panels/index.ts`), shared state (`src/lib/state.svelte.ts`, `appState`), generated bindings committed in `frontend/bindings`. |
| 15 | -- `examples/test-agents.yaml` — a valid configuration with the 4 test agents (through `scripts/agents.sh`). | 15 | +- Tooling: `Makefile` (entry point), golangci-lint in `tools/go.mod`, `.golangci.yml`, `scripts/check-license-headers.sh`, CI `.github/workflows/ci.yml` (not yet seen running on rickub). |
| 16 | -- `spikes/acp-trace` (ACP trace client), `spikes/wails-ui` (Wails v3 + Svelte prototype) — throwaway, separate Go modules. | 16 | +- `scripts/agents.sh`, `examples/test-agents.yaml`, `spikes/` (Initialize), docs EN/FR, ADRs, wireframes. |
| 17 | -- `docs/adr/0001..0003`, `docs/design/` (6 wireframes, draw.io), `docs/diagrams/packages.drawio`, `docs/en|fr/` (Diátaxis). | ||
| 18 | 17 | ||
| 19 | ## Decisions in force | 18 | ## Decisions in force |
| 20 | 19 | ||
| 21 | - ACP **v1**, via `github.com/coder/acp-go-sdk` v0.13.5, wrapped in `internal/acp` (ADR 0001). One ACP session per (channel, agent). | 20 | - ACP **v1**, via `github.com/coder/acp-go-sdk` v0.13.5, wrapped in `internal/acp` (ADR 0001). One ACP session per (channel, agent). |
| 22 | - **Wails v3.0.0**, Svelte 5 + TS, paneforge, markdown-it + Shiki (JS engine) + DOMPurify, CodeMirror 6, xterm.js + creack/pty (ADR 0002). Markdown rendered at most once per animation frame. macOS hidden-inset title bar: content near the top-left is padded by `--titlebar-inset` (38px under `:root.macos`, = `InvisibleTitleBarHeight`). | 21 | - **Wails v3.0.0**, Svelte 5 + TS, paneforge, markdown-it + Shiki (JS engine) + DOMPurify, CodeMirror 6, xterm.js + creack/pty (ADR 0002). Markdown rendered at most once per animation frame. macOS hidden-inset title bar: content near the top-left is padded by `--titlebar-inset` (38px under `:root.macos`, = `InvisibleTitleBarHeight`). |
| 23 | -- Packages and data model: ADR 0003. YAML = what exists; Pebble v2 = what happens, one DB per config file; channels live only in Pebble (YAML-declared ones are created once). Messages written at end of turn. | 22 | +- Packages and data model: ADR 0003 + Amendment 1 (main at the root, only main.go imports Wails, `internal/events` with an `Emitter` interface, LRU eviction of idle agents at the limit). |
| 23 | +- Frontend dependencies with **pnpm 12.11.2** and `frontend/pnpm-workspace.yaml` `supportedArchitectures` (darwin+linux): the repository folder is shared between the Mac and the Linux sandbox. Never use npm in `frontend/`. | ||
| 24 | +- Go deps: wails v3.0.0, coder/acp-go-sdk v0.13.5, go.yaml.in/yaml/v3, santhosh-tekuri/jsonschema/v6, fsnotify; go.mod says `go 1.26.0`. | ||
| 25 | +- Packages and data model (initial): ADR 0003. YAML = what exists; Pebble v2 = what happens, one DB per config file; channels live only in Pebble (YAML-declared ones are created once). Messages written at end of turn. | ||
| 24 | - Config format v1: `docs/en/reference/configuration.md`; unknown keys are errors; cross-entry rules belong to the loader (#9). | 26 | - Config format v1: `docs/en/reference/configuration.md`; unknown keys are errors; cross-entry rules belong to the loader (#9). |
| 25 | - Licence: custom source-available (`LICENSE`). Every hand-written source file starts with the one-line header `Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE` (comment syntax of the language); not on generated files nor on the owner's root scripts (`git.sh`, `new.*.sh`, `tag-step.sh`). | 27 | - Licence: custom source-available (`LICENSE`). Every hand-written source file starts with the one-line header `Copyright (c) 2026 Philippe Charrière — Sidekicks Source-Available License 1.0, see LICENSE` (comment syntax of the language); not on generated files nor on the owner's root scripts (`git.sh`, `new.*.sh`, `tag-step.sh`). |
| 26 | - ADRs and specs in English; docs bilingual EN + FR; tickets in French. | 28 | - ADRs and specs in English; docs bilingual EN + FR; tickets in French. |
| @@ -29,12 +31,13 @@ What exists: | |||
| 29 | 31 | ||
| 30 | | | | | 32 | | | | |
| 31 | | --- | --- | | 33 | | --- | --- | |
| 32 | -| All tests | `make test` (Go `go test ./...` + `scripts/agents_test.sh`; no network, no real agent) | | 34 | +| Everything the CI runs | `make check` (lint + tests; needs `wails3`, `pnpm`, GTK/WebKit dev packages on Linux) | |
| 33 | -| Test agents | `scripts/agents.sh run alice` · `ps` · `unload --all` (needs `mm` on PATH or `MM_BIN`, llmman on 127.0.0.1:17434 or host.docker.internal:17434) | | 35 | +| Tests only | `make test` (Go + vitest + shell) · real agents: `make test-real` | |
| 34 | -| ACP trace | `cd spikes/acp-trace && go run . -agent alice -prompt "…" -out /tmp/t.jsonl` | | 36 | +| Run | `SIDEKICKS_CONFIG="$PWD/examples/test-agents.yaml" make dev` · build `make build` · macOS app `make package` | |
| 35 | -| UI prototype | `cd spikes/wails-ui && wails3 dev` (macOS) ; Linux build needs `pkg-config libgtk-4-dev libwebkitgtk-6.0-dev` | | 37 | +| Bindings | `make bindings` after changing a service/event; CI runs `make bindings-check` | |
| 36 | -| Wireframes | `python3 docs/design/wireframes.py` then `rsvg-convert` each SVG | | 38 | +| Test agents | `scripts/agents.sh run alice` · `ps` · `unload --all` (`MM_BIN`, llmman on 127.0.0.1 or host.docker.internal:17434) | |
| 37 | -| Package diagram | `python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams` then `rsvg-convert -w 1200 -h 780` | | 39 | +| Headless UI check (sandbox) | `Xvfb :97`, `GDK_BACKEND=x11 WEBKIT_DISABLE_DMABUF_RENDERER=1 dbus-launch bin/sidekicks --config …`, `xdotool`, `import -window root` | |
| 40 | +| Wireframes / package diagram | `python3 docs/design/wireframes.py` · `python3 .claude/skills/drawio-fancy-diagram/generator/examples/sidekicks_packages.py docs/diagrams` + `rsvg-convert -w 1200 -h 800` | | ||
| 38 | 41 | ||
| 39 | ## Facts about the test agents (mm v1.0.3) | 42 | ## Facts about the test agents (mm v1.0.3) |
| 40 | 43 | ||
| @@ -45,5 +48,6 @@ What exists: | |||
| 45 | ## Not yet established | 48 | ## Not yet established |
| 46 | 49 | ||
| 47 | - How to exec a shell / read files inside an `sbx` sandbox (issue #28). | 50 | - How to exec a shell / read files inside an `sbx` sandbox (issue #28). |
| 48 | -- Quality gate: `qlty` was not installed in the 2026-10-29 sandbox, so no qlty measurement exists yet (`.quality/` absent). | 51 | +- Quality gate: `qlty` is not in this sandbox → no qlty measurement yet (issue #38: build a sandbox kit with qlty). golangci-lint (go tool) is the stopgap. |
| 52 | +- Whether the CI workflow runs as-is on rickub (first push of `feature/m1-foundations`). | ||
| 49 | - Whether `.claude/skills/*` (kit files) should be committed with the project is the owner's call. | 53 | - Whether `.claude/skills/*` (kit files) should be committed with the project is the owner's call. |
modified
.tickets/issues/0008-initialiser-le-projet-go-wails.yaml +40 -10 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 8 |
| 3 | 3 | title: "Initialiser le projet Go + Wails" |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-29T07:20:06.000Z |
| 9 | -updatedAt: 2026-10-29T08:51:00.000Z | |
| 9 | +updatedAt: 2026-10-29T10:19:30.000Z | |
| 10 | 10 | labels: |
| 11 | 11 | - "kind::chore" |
| 12 | 12 | - "area::infra" |
| @@ -38,68 +38,84 @@ body: | | ||
| 38 | 38 | tasks: |
| 39 | 39 | - id: 1 |
| 40 | 40 | title: "Générer le projet Wails avec le template choisi" |
| 41 | - state: open | |
| 41 | + state: closed | |
| 42 | 42 | priority: high |
| 43 | 43 | author: |
| 44 | 44 | name: k33g |
| 45 | 45 | email: ph.charriere@gmail.com |
| 46 | 46 | createdAt: 2026-10-29T07:20:06.000Z |
| 47 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 48 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 47 | 49 | - id: 2 |
| 48 | 50 | title: "Arborescence cmd/ internal/ frontend/" |
| 49 | - state: open | |
| 51 | + state: closed | |
| 50 | 52 | priority: medium |
| 51 | 53 | author: |
| 52 | 54 | name: k33g |
| 53 | 55 | email: ph.charriere@gmail.com |
| 54 | 56 | createdAt: 2026-10-29T07:20:06.000Z |
| 57 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 58 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 55 | 59 | - id: 3 |
| 56 | 60 | title: "Taskfile : dev, build, test, lint" |
| 57 | - state: open | |
| 61 | + state: closed | |
| 58 | 62 | priority: medium |
| 59 | 63 | author: |
| 60 | 64 | name: k33g |
| 61 | 65 | email: ph.charriere@gmail.com |
| 62 | 66 | createdAt: 2026-10-29T07:20:06.000Z |
| 67 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 68 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 63 | 69 | - id: 4 |
| 64 | 70 | title: "Lint Go et frontend" |
| 65 | - state: open | |
| 71 | + state: closed | |
| 66 | 72 | priority: medium |
| 67 | 73 | author: |
| 68 | 74 | name: k33g |
| 69 | 75 | email: ph.charriere@gmail.com |
| 70 | 76 | createdAt: 2026-10-29T07:20:06.000Z |
| 77 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 78 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 71 | 79 | - id: 5 |
| 72 | 80 | title: "CI ou hook pre-push" |
| 73 | - state: open | |
| 81 | + state: closed | |
| 74 | 82 | priority: medium |
| 75 | 83 | author: |
| 76 | 84 | name: k33g |
| 77 | 85 | email: ph.charriere@gmail.com |
| 78 | 86 | createdAt: 2026-10-29T07:20:06.000Z |
| 87 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 88 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 79 | 89 | - id: 6 |
| 80 | 90 | title: "README développeur" |
| 81 | - state: open | |
| 91 | + state: closed | |
| 82 | 92 | priority: medium |
| 83 | 93 | author: |
| 84 | 94 | name: k33g |
| 85 | 95 | email: ph.charriere@gmail.com |
| 86 | 96 | createdAt: 2026-10-29T07:20:06.000Z |
| 97 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 98 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 87 | 99 | - id: 7 |
| 88 | 100 | title: "Ajouter l'en-tête de licence aux fichiers sources et aux templates" |
| 89 | - state: open | |
| 101 | + state: closed | |
| 90 | 102 | priority: high |
| 91 | 103 | author: |
| 92 | 104 | name: k33g |
| 93 | 105 | email: ph.charriere@gmail.com |
| 94 | 106 | createdAt: 2026-10-29T08:00:00.000Z |
| 107 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 108 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 95 | 109 | - id: 8 |
| 96 | 110 | title: "Vérifier la présence de l'en-tête dans task lint" |
| 97 | - state: open | |
| 111 | + state: closed | |
| 98 | 112 | priority: medium |
| 99 | 113 | author: |
| 100 | 114 | name: k33g |
| 101 | 115 | email: ph.charriere@gmail.com |
| 102 | 116 | createdAt: 2026-10-29T08:00:00.000Z |
| 117 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 118 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 103 | 119 | comments: |
| 104 | 120 | - id: 1 |
| 105 | 121 | author: |
| @@ -138,3 +154,17 @@ comments: | ||
| 138 | 154 | - `go.mod` existe déjà à la racine (`git.rickub.com/bots-garden/sidekicks`, go 1.26) avec le package `schema`. `wails3 init` génère son propre go.mod : partir du template Svelte dans un dossier temporaire et reporter `main.go`, `frontend/`, `build/`, `Taskfile.yml` à la racine. |
| 139 | 155 | - Le `Makefile` est le point d'entrée unique (`make test`) ; ses cibles délèguent à la Taskfile de Wails (ADR 0002). |
| 140 | 156 | - Build Linux : `pkg-config`, `libgtk-4-dev`, `libwebkitgtk-6.0-dev`. Le prototype [spikes/wails-ui](spikes/wails-ui/README.md) sert de modèle. |
| 157 | + - id: 3 | |
| 158 | + author: | |
| 159 | + name: k33g | |
| 160 | + email: ph.charriere@gmail.com | |
| 161 | + createdAt: 2026-10-29T10:19:30.000Z | |
| 162 | + body: | | |
| 163 | + ## Résultat — milestone M1 | |
| 164 | + | |
| 165 | + - Projet Wails v3 (template Svelte) à la racine : `main.go`, `Taskfile.yml` et `build/` générés par Wails, `frontend/` en Svelte 5 + TypeScript. **Écart à l'ADR 0003** : le `main` est à la racine et non dans `cmd/sidekicks`, parce que les Taskfiles générées compilent `.` sur toutes les plateformes (voir l'amendement 1 de [l'ADR 0003](docs/adr/0003-architecture.md)). | |
| 166 | + - **Taskfile** : le `Makefile` reste le point d'entrée unique (`install`, `bindings`, `frontend`, `dev`, `build`, `package`, `check`, `test*`, `lint*`, `bindings-check`) et délègue la construction à la Taskfile de Wails via `wails3`. | |
| 167 | + - **Lint** : golangci-lint v2.14.0 épinglé dans `tools/go.mod` (`go tool`), configuré dans `.golangci.yml` ; `svelte-check` ; `scripts/check-license-headers.sh` (avec tests). qlty viendra avec #38. | |
| 168 | + - **CI** : `.github/workflows/ci.yml` (format GitHub Actions, comme mini-me) : `make bindings-check` puis `make check` à chaque push et MR. **À confirmer côté forge** : premier passage sur rickub. | |
| 169 | + - **pnpm 12.11.2** avec `frontend/pnpm-workspace.yaml` (`supportedArchitectures`) : un seul `node_modules` pour macOS et Linux. | |
| 170 | + - README développeur à la racine ; guides EN/FR « Développer l'application » et référence « Commandes ». | |
| @@ -1,12 +1,12 @@ | |||
| 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 8 | 2 | id: 8 |
| 3 | title: "Initialiser le projet Go + Wails" | 3 | title: "Initialiser le projet Go + Wails" |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-10-29T07:20:06.000Z | 8 | createdAt: 2026-10-29T07:20:06.000Z |
| 9 | -updatedAt: 2026-10-29T08:51:00.000Z | 9 | +updatedAt: 2026-10-29T10:19:30.000Z |
| 10 | labels: | 10 | labels: |
| 11 | - "kind::chore" | 11 | - "kind::chore" |
| 12 | - "area::infra" | 12 | - "area::infra" |
| @@ -38,68 +38,84 @@ body: | | |||
| 38 | tasks: | 38 | tasks: |
| 39 | - id: 1 | 39 | - id: 1 |
| 40 | title: "Générer le projet Wails avec le template choisi" | 40 | title: "Générer le projet Wails avec le template choisi" |
| 41 | - state: open | 41 | + state: closed |
| 42 | priority: high | 42 | priority: high |
| 43 | author: | 43 | author: |
| 44 | name: k33g | 44 | name: k33g |
| 45 | email: ph.charriere@gmail.com | 45 | email: ph.charriere@gmail.com |
| 46 | createdAt: 2026-10-29T07:20:06.000Z | 46 | createdAt: 2026-10-29T07:20:06.000Z |
| 47 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 48 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 47 | - id: 2 | 49 | - id: 2 |
| 48 | title: "Arborescence cmd/ internal/ frontend/" | 50 | title: "Arborescence cmd/ internal/ frontend/" |
| 49 | - state: open | 51 | + state: closed |
| 50 | priority: medium | 52 | priority: medium |
| 51 | author: | 53 | author: |
| 52 | name: k33g | 54 | name: k33g |
| 53 | email: ph.charriere@gmail.com | 55 | email: ph.charriere@gmail.com |
| 54 | createdAt: 2026-10-29T07:20:06.000Z | 56 | createdAt: 2026-10-29T07:20:06.000Z |
| 57 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 58 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 55 | - id: 3 | 59 | - id: 3 |
| 56 | title: "Taskfile : dev, build, test, lint" | 60 | title: "Taskfile : dev, build, test, lint" |
| 57 | - state: open | 61 | + state: closed |
| 58 | priority: medium | 62 | priority: medium |
| 59 | author: | 63 | author: |
| 60 | name: k33g | 64 | name: k33g |
| 61 | email: ph.charriere@gmail.com | 65 | email: ph.charriere@gmail.com |
| 62 | createdAt: 2026-10-29T07:20:06.000Z | 66 | createdAt: 2026-10-29T07:20:06.000Z |
| 67 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 68 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 63 | - id: 4 | 69 | - id: 4 |
| 64 | title: "Lint Go et frontend" | 70 | title: "Lint Go et frontend" |
| 65 | - state: open | 71 | + state: closed |
| 66 | priority: medium | 72 | priority: medium |
| 67 | author: | 73 | author: |
| 68 | name: k33g | 74 | name: k33g |
| 69 | email: ph.charriere@gmail.com | 75 | email: ph.charriere@gmail.com |
| 70 | createdAt: 2026-10-29T07:20:06.000Z | 76 | createdAt: 2026-10-29T07:20:06.000Z |
| 77 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 78 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 71 | - id: 5 | 79 | - id: 5 |
| 72 | title: "CI ou hook pre-push" | 80 | title: "CI ou hook pre-push" |
| 73 | - state: open | 81 | + state: closed |
| 74 | priority: medium | 82 | priority: medium |
| 75 | author: | 83 | author: |
| 76 | name: k33g | 84 | name: k33g |
| 77 | email: ph.charriere@gmail.com | 85 | email: ph.charriere@gmail.com |
| 78 | createdAt: 2026-10-29T07:20:06.000Z | 86 | createdAt: 2026-10-29T07:20:06.000Z |
| 87 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 88 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 79 | - id: 6 | 89 | - id: 6 |
| 80 | title: "README développeur" | 90 | title: "README développeur" |
| 81 | - state: open | 91 | + state: closed |
| 82 | priority: medium | 92 | priority: medium |
| 83 | author: | 93 | author: |
| 84 | name: k33g | 94 | name: k33g |
| 85 | email: ph.charriere@gmail.com | 95 | email: ph.charriere@gmail.com |
| 86 | createdAt: 2026-10-29T07:20:06.000Z | 96 | createdAt: 2026-10-29T07:20:06.000Z |
| 97 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 98 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 87 | - id: 7 | 99 | - id: 7 |
| 88 | title: "Ajouter l'en-tête de licence aux fichiers sources et aux templates" | 100 | title: "Ajouter l'en-tête de licence aux fichiers sources et aux templates" |
| 89 | - state: open | 101 | + state: closed |
| 90 | priority: high | 102 | priority: high |
| 91 | author: | 103 | author: |
| 92 | name: k33g | 104 | name: k33g |
| 93 | email: ph.charriere@gmail.com | 105 | email: ph.charriere@gmail.com |
| 94 | createdAt: 2026-10-29T08:00:00.000Z | 106 | createdAt: 2026-10-29T08:00:00.000Z |
| 107 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 108 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 95 | - id: 8 | 109 | - id: 8 |
| 96 | title: "Vérifier la présence de l'en-tête dans task lint" | 110 | title: "Vérifier la présence de l'en-tête dans task lint" |
| 97 | - state: open | 111 | + state: closed |
| 98 | priority: medium | 112 | priority: medium |
| 99 | author: | 113 | author: |
| 100 | name: k33g | 114 | name: k33g |
| 101 | email: ph.charriere@gmail.com | 115 | email: ph.charriere@gmail.com |
| 102 | createdAt: 2026-10-29T08:00:00.000Z | 116 | createdAt: 2026-10-29T08:00:00.000Z |
| 117 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 118 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 103 | comments: | 119 | comments: |
| 104 | - id: 1 | 120 | - id: 1 |
| 105 | author: | 121 | author: |
| @@ -138,3 +154,17 @@ comments: | |||
| 138 | - `go.mod` existe déjà à la racine (`git.rickub.com/bots-garden/sidekicks`, go 1.26) avec le package `schema`. `wails3 init` génère son propre go.mod : partir du template Svelte dans un dossier temporaire et reporter `main.go`, `frontend/`, `build/`, `Taskfile.yml` à la racine. | 154 | - `go.mod` existe déjà à la racine (`git.rickub.com/bots-garden/sidekicks`, go 1.26) avec le package `schema`. `wails3 init` génère son propre go.mod : partir du template Svelte dans un dossier temporaire et reporter `main.go`, `frontend/`, `build/`, `Taskfile.yml` à la racine. |
| 139 | - Le `Makefile` est le point d'entrée unique (`make test`) ; ses cibles délèguent à la Taskfile de Wails (ADR 0002). | 155 | - Le `Makefile` est le point d'entrée unique (`make test`) ; ses cibles délèguent à la Taskfile de Wails (ADR 0002). |
| 140 | - Build Linux : `pkg-config`, `libgtk-4-dev`, `libwebkitgtk-6.0-dev`. Le prototype [spikes/wails-ui](spikes/wails-ui/README.md) sert de modèle. | 156 | - Build Linux : `pkg-config`, `libgtk-4-dev`, `libwebkitgtk-6.0-dev`. Le prototype [spikes/wails-ui](spikes/wails-ui/README.md) sert de modèle. |
| 157 | + - id: 3 | ||
| 158 | + author: | ||
| 159 | + name: k33g | ||
| 160 | + email: ph.charriere@gmail.com | ||
| 161 | + createdAt: 2026-10-29T10:19:30.000Z | ||
| 162 | + body: | | ||
| 163 | + ## Résultat — milestone M1 | ||
| 164 | + | ||
| 165 | + - Projet Wails v3 (template Svelte) à la racine : `main.go`, `Taskfile.yml` et `build/` générés par Wails, `frontend/` en Svelte 5 + TypeScript. **Écart à l'ADR 0003** : le `main` est à la racine et non dans `cmd/sidekicks`, parce que les Taskfiles générées compilent `.` sur toutes les plateformes (voir l'amendement 1 de [l'ADR 0003](docs/adr/0003-architecture.md)). | ||
| 166 | + - **Taskfile** : le `Makefile` reste le point d'entrée unique (`install`, `bindings`, `frontend`, `dev`, `build`, `package`, `check`, `test*`, `lint*`, `bindings-check`) et délègue la construction à la Taskfile de Wails via `wails3`. | ||
| 167 | + - **Lint** : golangci-lint v2.14.0 épinglé dans `tools/go.mod` (`go tool`), configuré dans `.golangci.yml` ; `svelte-check` ; `scripts/check-license-headers.sh` (avec tests). qlty viendra avec #38. | ||
| 168 | + - **CI** : `.github/workflows/ci.yml` (format GitHub Actions, comme mini-me) : `make bindings-check` puis `make check` à chaque push et MR. **À confirmer côté forge** : premier passage sur rickub. | ||
| 169 | + - **pnpm 12.11.2** avec `frontend/pnpm-workspace.yaml` (`supportedArchitectures`) : un seul `node_modules` pour macOS et Linux. | ||
| 170 | + - README développeur à la racine ; guides EN/FR « Développer l'application » et référence « Commandes ». | ||
modified
.tickets/issues/0009-charger-valider-et-sauvegarder-la-configuration.yaml +38 -9 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 9 |
| 3 | 3 | title: "Charger, valider et sauvegarder la configuration YAML" |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-29T07:20:07.000Z |
| 9 | -updatedAt: 2026-10-29T08:51:00.000Z | |
| 9 | +updatedAt: 2026-10-29T10:19:30.000Z | |
| 10 | 10 | labels: |
| 11 | 11 | - "kind::feature" |
| 12 | 12 | - "area::config" |
| @@ -35,60 +35,74 @@ body: | | ||
| 35 | 35 | tasks: |
| 36 | 36 | - id: 1 |
| 37 | 37 | title: "Structs Go et parsing (gopkg.in/yaml.v3)" |
| 38 | - state: open | |
| 38 | + state: closed | |
| 39 | 39 | priority: high |
| 40 | 40 | author: |
| 41 | 41 | name: k33g |
| 42 | 42 | email: ph.charriere@gmail.com |
| 43 | 43 | createdAt: 2026-10-29T07:20:07.000Z |
| 44 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 45 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 44 | 46 | - id: 2 |
| 45 | 47 | title: "Validation avec messages lisibles et numéros de ligne" |
| 46 | - state: open | |
| 48 | + state: closed | |
| 47 | 49 | priority: high |
| 48 | 50 | author: |
| 49 | 51 | name: k33g |
| 50 | 52 | email: ph.charriere@gmail.com |
| 51 | 53 | createdAt: 2026-10-29T07:20:07.000Z |
| 54 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 55 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 52 | 56 | - id: 3 |
| 53 | 57 | title: "Création d'un fichier par défaut commenté" |
| 54 | - state: open | |
| 58 | + state: closed | |
| 55 | 59 | priority: medium |
| 56 | 60 | author: |
| 57 | 61 | name: k33g |
| 58 | 62 | email: ph.charriere@gmail.com |
| 59 | 63 | createdAt: 2026-10-29T07:20:07.000Z |
| 64 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 65 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 60 | 66 | - id: 4 |
| 61 | 67 | title: "Résolution de l'emplacement (défaut, flag, env)" |
| 62 | - state: open | |
| 68 | + state: closed | |
| 63 | 69 | priority: medium |
| 64 | 70 | author: |
| 65 | 71 | name: k33g |
| 66 | 72 | email: ph.charriere@gmail.com |
| 67 | 73 | createdAt: 2026-10-29T07:20:07.000Z |
| 74 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 75 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 68 | 76 | - id: 5 |
| 69 | 77 | title: "Watch du fichier et événement de rechargement" |
| 70 | - state: open | |
| 78 | + state: closed | |
| 71 | 79 | priority: medium |
| 72 | 80 | author: |
| 73 | 81 | name: k33g |
| 74 | 82 | email: ph.charriere@gmail.com |
| 75 | 83 | createdAt: 2026-10-29T07:20:07.000Z |
| 84 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 85 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 76 | 86 | - id: 6 |
| 77 | 87 | title: "Sauvegarde préservant les commentaires" |
| 78 | - state: open | |
| 88 | + state: closed | |
| 79 | 89 | priority: medium |
| 80 | 90 | author: |
| 81 | 91 | name: k33g |
| 82 | 92 | email: ph.charriere@gmail.com |
| 83 | 93 | createdAt: 2026-10-29T07:20:07.000Z |
| 94 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 95 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 84 | 96 | - id: 7 |
| 85 | 97 | title: "Tests unitaires" |
| 86 | - state: open | |
| 98 | + state: closed | |
| 87 | 99 | priority: medium |
| 88 | 100 | author: |
| 89 | 101 | name: k33g |
| 90 | 102 | email: ph.charriere@gmail.com |
| 91 | 103 | createdAt: 2026-10-29T07:20:07.000Z |
| 104 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 105 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 92 | 106 | comments: |
| 93 | 107 | - id: 1 |
| 94 | 108 | author: |
| @@ -97,3 +111,18 @@ comments: | ||
| 97 | 111 | createdAt: 2026-10-29T08:51:00.000Z |
| 98 | 112 | body: | |
| 99 | 113 | Le package `schema` (#4) existe : `schema.ValidateConfig(yaml)` valide la forme du fichier. Il reste au chargeur : les règles inter-entrées (noms uniques, membres de channel existants, `command` trouvable), la traduction des `*jsonschema.ValidationError` en messages humains avec numéro de ligne (exemples dans la référence de configuration), et la résolution des chemins. Bibliothèques déjà choisies : `go.yaml.in/yaml/v3` (préserve les commentaires via l'API Node) et `santhosh-tekuri/jsonschema/v6`. |
| 114 | + - id: 2 | |
| 115 | + author: | |
| 116 | + name: k33g | |
| 117 | + email: ph.charriere@gmail.com | |
| 118 | + createdAt: 2026-10-29T10:19:30.000Z | |
| 119 | + body: | | |
| 120 | + ## Résultat | |
| 121 | + | |
| 122 | + Package `internal/config` : `Load`/`Parse` (valeurs par défaut, chemins résolus par rapport au fichier, `~`), `Locate` (flag → `SIDEKICKS_CONFIG` → dernier ouvert → défaut), `EnsureDefault` (fichier commenté pour le citizen user), `Save` (valide puis écrit atomiquement), `AppendAgent` (préserve les commentaires via l'API Node), `Watch` (fsnotify sur le dossier, regroupe les rafales). | |
| 123 | + | |
| 124 | + - Problèmes localisés et expliqués, en FR ou EN selon `ui.language` : « ligne 4 — agents[0].comand : clé inconnue « comand » ; vouliez-vous dire « command » ? ». | |
| 125 | + - Règles inter-entrées : noms d'agents et de channels uniques, membres existants ; commande introuvable = simple avertissement. | |
| 126 | + - YAML : `go.yaml.in/yaml/v3` (successeur maintenu de `gopkg.in/yaml.v3`). | |
| 127 | + - **Bug trouvé** dans le schéma d'Initialize : `stopIdleAgentsAfter: 0` (nombre) était refusé alors que la référence l'autorise — corrigé, avec un cas de test. | |
| 128 | + - 20+ tests, dont le rechargement après un enregistrement atomique. | |
| @@ -1,12 +1,12 @@ | |||
| 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 9 | 2 | id: 9 |
| 3 | title: "Charger, valider et sauvegarder la configuration YAML" | 3 | title: "Charger, valider et sauvegarder la configuration YAML" |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-10-29T07:20:07.000Z | 8 | createdAt: 2026-10-29T07:20:07.000Z |
| 9 | -updatedAt: 2026-10-29T08:51:00.000Z | 9 | +updatedAt: 2026-10-29T10:19:30.000Z |
| 10 | labels: | 10 | labels: |
| 11 | - "kind::feature" | 11 | - "kind::feature" |
| 12 | - "area::config" | 12 | - "area::config" |
| @@ -35,60 +35,74 @@ body: | | |||
| 35 | tasks: | 35 | tasks: |
| 36 | - id: 1 | 36 | - id: 1 |
| 37 | title: "Structs Go et parsing (gopkg.in/yaml.v3)" | 37 | title: "Structs Go et parsing (gopkg.in/yaml.v3)" |
| 38 | - state: open | 38 | + state: closed |
| 39 | priority: high | 39 | priority: high |
| 40 | author: | 40 | author: |
| 41 | name: k33g | 41 | name: k33g |
| 42 | email: ph.charriere@gmail.com | 42 | email: ph.charriere@gmail.com |
| 43 | createdAt: 2026-10-29T07:20:07.000Z | 43 | createdAt: 2026-10-29T07:20:07.000Z |
| 44 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 45 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 44 | - id: 2 | 46 | - id: 2 |
| 45 | title: "Validation avec messages lisibles et numéros de ligne" | 47 | title: "Validation avec messages lisibles et numéros de ligne" |
| 46 | - state: open | 48 | + state: closed |
| 47 | priority: high | 49 | priority: high |
| 48 | author: | 50 | author: |
| 49 | name: k33g | 51 | name: k33g |
| 50 | email: ph.charriere@gmail.com | 52 | email: ph.charriere@gmail.com |
| 51 | createdAt: 2026-10-29T07:20:07.000Z | 53 | createdAt: 2026-10-29T07:20:07.000Z |
| 54 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 55 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 52 | - id: 3 | 56 | - id: 3 |
| 53 | title: "Création d'un fichier par défaut commenté" | 57 | title: "Création d'un fichier par défaut commenté" |
| 54 | - state: open | 58 | + state: closed |
| 55 | priority: medium | 59 | priority: medium |
| 56 | author: | 60 | author: |
| 57 | name: k33g | 61 | name: k33g |
| 58 | email: ph.charriere@gmail.com | 62 | email: ph.charriere@gmail.com |
| 59 | createdAt: 2026-10-29T07:20:07.000Z | 63 | createdAt: 2026-10-29T07:20:07.000Z |
| 64 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 65 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 60 | - id: 4 | 66 | - id: 4 |
| 61 | title: "Résolution de l'emplacement (défaut, flag, env)" | 67 | title: "Résolution de l'emplacement (défaut, flag, env)" |
| 62 | - state: open | 68 | + state: closed |
| 63 | priority: medium | 69 | priority: medium |
| 64 | author: | 70 | author: |
| 65 | name: k33g | 71 | name: k33g |
| 66 | email: ph.charriere@gmail.com | 72 | email: ph.charriere@gmail.com |
| 67 | createdAt: 2026-10-29T07:20:07.000Z | 73 | createdAt: 2026-10-29T07:20:07.000Z |
| 74 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 75 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 68 | - id: 5 | 76 | - id: 5 |
| 69 | title: "Watch du fichier et événement de rechargement" | 77 | title: "Watch du fichier et événement de rechargement" |
| 70 | - state: open | 78 | + state: closed |
| 71 | priority: medium | 79 | priority: medium |
| 72 | author: | 80 | author: |
| 73 | name: k33g | 81 | name: k33g |
| 74 | email: ph.charriere@gmail.com | 82 | email: ph.charriere@gmail.com |
| 75 | createdAt: 2026-10-29T07:20:07.000Z | 83 | createdAt: 2026-10-29T07:20:07.000Z |
| 84 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 85 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 76 | - id: 6 | 86 | - id: 6 |
| 77 | title: "Sauvegarde préservant les commentaires" | 87 | title: "Sauvegarde préservant les commentaires" |
| 78 | - state: open | 88 | + state: closed |
| 79 | priority: medium | 89 | priority: medium |
| 80 | author: | 90 | author: |
| 81 | name: k33g | 91 | name: k33g |
| 82 | email: ph.charriere@gmail.com | 92 | email: ph.charriere@gmail.com |
| 83 | createdAt: 2026-10-29T07:20:07.000Z | 93 | createdAt: 2026-10-29T07:20:07.000Z |
| 94 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 95 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 84 | - id: 7 | 96 | - id: 7 |
| 85 | title: "Tests unitaires" | 97 | title: "Tests unitaires" |
| 86 | - state: open | 98 | + state: closed |
| 87 | priority: medium | 99 | priority: medium |
| 88 | author: | 100 | author: |
| 89 | name: k33g | 101 | name: k33g |
| 90 | email: ph.charriere@gmail.com | 102 | email: ph.charriere@gmail.com |
| 91 | createdAt: 2026-10-29T07:20:07.000Z | 103 | createdAt: 2026-10-29T07:20:07.000Z |
| 104 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 105 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 92 | comments: | 106 | comments: |
| 93 | - id: 1 | 107 | - id: 1 |
| 94 | author: | 108 | author: |
| @@ -97,3 +111,18 @@ comments: | |||
| 97 | createdAt: 2026-10-29T08:51:00.000Z | 111 | createdAt: 2026-10-29T08:51:00.000Z |
| 98 | body: | | 112 | body: | |
| 99 | Le package `schema` (#4) existe : `schema.ValidateConfig(yaml)` valide la forme du fichier. Il reste au chargeur : les règles inter-entrées (noms uniques, membres de channel existants, `command` trouvable), la traduction des `*jsonschema.ValidationError` en messages humains avec numéro de ligne (exemples dans la référence de configuration), et la résolution des chemins. Bibliothèques déjà choisies : `go.yaml.in/yaml/v3` (préserve les commentaires via l'API Node) et `santhosh-tekuri/jsonschema/v6`. | 113 | Le package `schema` (#4) existe : `schema.ValidateConfig(yaml)` valide la forme du fichier. Il reste au chargeur : les règles inter-entrées (noms uniques, membres de channel existants, `command` trouvable), la traduction des `*jsonschema.ValidationError` en messages humains avec numéro de ligne (exemples dans la référence de configuration), et la résolution des chemins. Bibliothèques déjà choisies : `go.yaml.in/yaml/v3` (préserve les commentaires via l'API Node) et `santhosh-tekuri/jsonschema/v6`. |
| 114 | + - id: 2 | ||
| 115 | + author: | ||
| 116 | + name: k33g | ||
| 117 | + email: ph.charriere@gmail.com | ||
| 118 | + createdAt: 2026-10-29T10:19:30.000Z | ||
| 119 | + body: | | ||
| 120 | + ## Résultat | ||
| 121 | + | ||
| 122 | + Package `internal/config` : `Load`/`Parse` (valeurs par défaut, chemins résolus par rapport au fichier, `~`), `Locate` (flag → `SIDEKICKS_CONFIG` → dernier ouvert → défaut), `EnsureDefault` (fichier commenté pour le citizen user), `Save` (valide puis écrit atomiquement), `AppendAgent` (préserve les commentaires via l'API Node), `Watch` (fsnotify sur le dossier, regroupe les rafales). | ||
| 123 | + | ||
| 124 | + - Problèmes localisés et expliqués, en FR ou EN selon `ui.language` : « ligne 4 — agents[0].comand : clé inconnue « comand » ; vouliez-vous dire « command » ? ». | ||
| 125 | + - Règles inter-entrées : noms d'agents et de channels uniques, membres existants ; commande introuvable = simple avertissement. | ||
| 126 | + - YAML : `go.yaml.in/yaml/v3` (successeur maintenu de `gopkg.in/yaml.v3`). | ||
| 127 | + - **Bug trouvé** dans le schéma d'Initialize : `stopIdleAgentsAfter: 0` (nombre) était refusé alors que la référence l'autorise — corrigé, avec un cas de test. | ||
| 128 | + - 20+ tests, dont le rechargement après un enregistrement atomique. | ||
modified
.tickets/issues/0010-client-acp-transport-stdio-et-handshake-initiali.yaml +37 -10 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 10 |
| 3 | 3 | title: "Client ACP : transport stdio et handshake initialize" |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-29T07:20:08.000Z |
| 9 | -updatedAt: 2026-10-29T08:51:00.000Z | |
| 9 | +updatedAt: 2026-10-29T10:19:30.000Z | |
| 10 | 10 | labels: |
| 11 | 11 | - "kind::feature" |
| 12 | 12 | - "area::acp" |
| @@ -40,68 +40,84 @@ body: | | ||
| 40 | 40 | tasks: |
| 41 | 41 | - id: 1 |
| 42 | 42 | title: "Spawn du processus et pipes stdio" |
| 43 | - state: open | |
| 43 | + state: closed | |
| 44 | 44 | priority: high |
| 45 | 45 | author: |
| 46 | 46 | name: k33g |
| 47 | 47 | email: ph.charriere@gmail.com |
| 48 | 48 | createdAt: 2026-10-29T07:20:08.000Z |
| 49 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 50 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 49 | 51 | - id: 2 |
| 50 | 52 | title: "Codec JSON-RPC (corrélation des ids, notifications, requêtes entrantes)" |
| 51 | - state: open | |
| 53 | + state: closed | |
| 52 | 54 | priority: high |
| 53 | 55 | author: |
| 54 | 56 | name: k33g |
| 55 | 57 | email: ph.charriere@gmail.com |
| 56 | 58 | createdAt: 2026-10-29T07:20:08.000Z |
| 59 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 60 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 57 | 61 | - id: 3 |
| 58 | 62 | title: "Méthode initialize et stockage des capacités" |
| 59 | - state: open | |
| 63 | + state: closed | |
| 60 | 64 | priority: high |
| 61 | 65 | author: |
| 62 | 66 | name: k33g |
| 63 | 67 | email: ph.charriere@gmail.com |
| 64 | 68 | createdAt: 2026-10-29T07:20:08.000Z |
| 69 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 70 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 65 | 71 | - id: 4 |
| 66 | 72 | title: "Capture de stderr dans un log par agent" |
| 67 | - state: open | |
| 73 | + state: closed | |
| 68 | 74 | priority: medium |
| 69 | 75 | author: |
| 70 | 76 | name: k33g |
| 71 | 77 | email: ph.charriere@gmail.com |
| 72 | 78 | createdAt: 2026-10-29T07:20:08.000Z |
| 79 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 80 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 73 | 81 | - id: 5 |
| 74 | 82 | title: "Arrêt propre et gestion des crashs" |
| 75 | - state: open | |
| 83 | + state: closed | |
| 76 | 84 | priority: medium |
| 77 | 85 | author: |
| 78 | 86 | name: k33g |
| 79 | 87 | email: ph.charriere@gmail.com |
| 80 | 88 | createdAt: 2026-10-29T07:20:08.000Z |
| 89 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 90 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 81 | 91 | - id: 6 |
| 82 | 92 | title: "Faux agent pour les tests unitaires" |
| 83 | - state: open | |
| 93 | + state: closed | |
| 84 | 94 | priority: medium |
| 85 | 95 | author: |
| 86 | 96 | name: k33g |
| 87 | 97 | email: ph.charriere@gmail.com |
| 88 | 98 | createdAt: 2026-10-29T07:20:08.000Z |
| 99 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 100 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 89 | 101 | - id: 7 |
| 90 | 102 | title: "Test d'intégration avec Alice" |
| 91 | - state: open | |
| 103 | + state: closed | |
| 92 | 104 | priority: medium |
| 93 | 105 | author: |
| 94 | 106 | name: k33g |
| 95 | 107 | email: ph.charriere@gmail.com |
| 96 | 108 | createdAt: 2026-10-29T07:20:08.000Z |
| 109 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 110 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 97 | 111 | - id: 8 |
| 98 | 112 | title: "Build tag realagents pour les tests d'intégration (repris de #7)" |
| 99 | - state: open | |
| 113 | + state: closed | |
| 100 | 114 | priority: high |
| 101 | 115 | author: |
| 102 | 116 | name: k33g |
| 103 | 117 | email: ph.charriere@gmail.com |
| 104 | 118 | createdAt: 2026-10-29T08:51:00.000Z |
| 119 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 120 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 105 | 121 | comments: |
| 106 | 122 | - id: 1 |
| 107 | 123 | author: |
| @@ -110,3 +126,14 @@ comments: | ||
| 110 | 126 | createdAt: 2026-10-29T08:51:00.000Z |
| 111 | 127 | body: | |
| 112 | 128 | Repris de #7 : les tests d'intégration avec de vrais agents utilisent le build tag `realagents` et lancent les agents via `scripts/agents.sh run <agent>` (limite + déchargement). Le SDK retenu est `github.com/coder/acp-go-sdk` v0.13.5 ([ADR 0001](docs/adr/0001-acp.md)) ; [spikes/acp-trace](spikes/acp-trace/main.go) montre son usage côté client. |
| 129 | + - id: 2 | |
| 130 | + author: | |
| 131 | + name: k33g | |
| 132 | + email: ph.charriere@gmail.com | |
| 133 | + createdAt: 2026-10-29T10:19:30.000Z | |
| 134 | + body: | | |
| 135 | + ## Résultat | |
| 136 | + | |
| 137 | + Package `internal/acp` : `Start(ctx, Spec, Options)` lance l'agent dans son propre groupe de processus, fait `initialize` (ACP v1, refuse une autre version), capture stderr (callback + 20 dernières lignes, ajoutées au message d'erreur d'un démarrage raté), `Close` ferme stdin puis tue le groupe après 5 s, `Done`/`Err` signalent un crash. Les types du SDK `coder/acp-go-sdk` restent dans le package. | |
| 138 | + | |
| 139 | + Tests : un faux agent (le binaire de test relancé en mode agent) couvre handshake, fermeture, agent récalcitrant, crash, mauvaise version, sortie prématurée, commande absente, délai d'initialize — tous avec `-race`. Test réel `realagents` avec Alice via `scripts/agents.sh` : OK (`make test-real`). | |
| @@ -1,12 +1,12 @@ | |||
| 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 10 | 2 | id: 10 |
| 3 | title: "Client ACP : transport stdio et handshake initialize" | 3 | title: "Client ACP : transport stdio et handshake initialize" |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-10-29T07:20:08.000Z | 8 | createdAt: 2026-10-29T07:20:08.000Z |
| 9 | -updatedAt: 2026-10-29T08:51:00.000Z | 9 | +updatedAt: 2026-10-29T10:19:30.000Z |
| 10 | labels: | 10 | labels: |
| 11 | - "kind::feature" | 11 | - "kind::feature" |
| 12 | - "area::acp" | 12 | - "area::acp" |
| @@ -40,68 +40,84 @@ body: | | |||
| 40 | tasks: | 40 | tasks: |
| 41 | - id: 1 | 41 | - id: 1 |
| 42 | title: "Spawn du processus et pipes stdio" | 42 | title: "Spawn du processus et pipes stdio" |
| 43 | - state: open | 43 | + state: closed |
| 44 | priority: high | 44 | priority: high |
| 45 | author: | 45 | author: |
| 46 | name: k33g | 46 | name: k33g |
| 47 | email: ph.charriere@gmail.com | 47 | email: ph.charriere@gmail.com |
| 48 | createdAt: 2026-10-29T07:20:08.000Z | 48 | createdAt: 2026-10-29T07:20:08.000Z |
| 49 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 50 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 49 | - id: 2 | 51 | - id: 2 |
| 50 | title: "Codec JSON-RPC (corrélation des ids, notifications, requêtes entrantes)" | 52 | title: "Codec JSON-RPC (corrélation des ids, notifications, requêtes entrantes)" |
| 51 | - state: open | 53 | + state: closed |
| 52 | priority: high | 54 | priority: high |
| 53 | author: | 55 | author: |
| 54 | name: k33g | 56 | name: k33g |
| 55 | email: ph.charriere@gmail.com | 57 | email: ph.charriere@gmail.com |
| 56 | createdAt: 2026-10-29T07:20:08.000Z | 58 | createdAt: 2026-10-29T07:20:08.000Z |
| 59 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 60 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 57 | - id: 3 | 61 | - id: 3 |
| 58 | title: "Méthode initialize et stockage des capacités" | 62 | title: "Méthode initialize et stockage des capacités" |
| 59 | - state: open | 63 | + state: closed |
| 60 | priority: high | 64 | priority: high |
| 61 | author: | 65 | author: |
| 62 | name: k33g | 66 | name: k33g |
| 63 | email: ph.charriere@gmail.com | 67 | email: ph.charriere@gmail.com |
| 64 | createdAt: 2026-10-29T07:20:08.000Z | 68 | createdAt: 2026-10-29T07:20:08.000Z |
| 69 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 70 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 65 | - id: 4 | 71 | - id: 4 |
| 66 | title: "Capture de stderr dans un log par agent" | 72 | title: "Capture de stderr dans un log par agent" |
| 67 | - state: open | 73 | + state: closed |
| 68 | priority: medium | 74 | priority: medium |
| 69 | author: | 75 | author: |
| 70 | name: k33g | 76 | name: k33g |
| 71 | email: ph.charriere@gmail.com | 77 | email: ph.charriere@gmail.com |
| 72 | createdAt: 2026-10-29T07:20:08.000Z | 78 | createdAt: 2026-10-29T07:20:08.000Z |
| 79 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 80 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 73 | - id: 5 | 81 | - id: 5 |
| 74 | title: "Arrêt propre et gestion des crashs" | 82 | title: "Arrêt propre et gestion des crashs" |
| 75 | - state: open | 83 | + state: closed |
| 76 | priority: medium | 84 | priority: medium |
| 77 | author: | 85 | author: |
| 78 | name: k33g | 86 | name: k33g |
| 79 | email: ph.charriere@gmail.com | 87 | email: ph.charriere@gmail.com |
| 80 | createdAt: 2026-10-29T07:20:08.000Z | 88 | createdAt: 2026-10-29T07:20:08.000Z |
| 89 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 90 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 81 | - id: 6 | 91 | - id: 6 |
| 82 | title: "Faux agent pour les tests unitaires" | 92 | title: "Faux agent pour les tests unitaires" |
| 83 | - state: open | 93 | + state: closed |
| 84 | priority: medium | 94 | priority: medium |
| 85 | author: | 95 | author: |
| 86 | name: k33g | 96 | name: k33g |
| 87 | email: ph.charriere@gmail.com | 97 | email: ph.charriere@gmail.com |
| 88 | createdAt: 2026-10-29T07:20:08.000Z | 98 | createdAt: 2026-10-29T07:20:08.000Z |
| 99 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 100 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 89 | - id: 7 | 101 | - id: 7 |
| 90 | title: "Test d'intégration avec Alice" | 102 | title: "Test d'intégration avec Alice" |
| 91 | - state: open | 103 | + state: closed |
| 92 | priority: medium | 104 | priority: medium |
| 93 | author: | 105 | author: |
| 94 | name: k33g | 106 | name: k33g |
| 95 | email: ph.charriere@gmail.com | 107 | email: ph.charriere@gmail.com |
| 96 | createdAt: 2026-10-29T07:20:08.000Z | 108 | createdAt: 2026-10-29T07:20:08.000Z |
| 109 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 110 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 97 | - id: 8 | 111 | - id: 8 |
| 98 | title: "Build tag realagents pour les tests d'intégration (repris de #7)" | 112 | title: "Build tag realagents pour les tests d'intégration (repris de #7)" |
| 99 | - state: open | 113 | + state: closed |
| 100 | priority: high | 114 | priority: high |
| 101 | author: | 115 | author: |
| 102 | name: k33g | 116 | name: k33g |
| 103 | email: ph.charriere@gmail.com | 117 | email: ph.charriere@gmail.com |
| 104 | createdAt: 2026-10-29T08:51:00.000Z | 118 | createdAt: 2026-10-29T08:51:00.000Z |
| 119 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 120 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 105 | comments: | 121 | comments: |
| 106 | - id: 1 | 122 | - id: 1 |
| 107 | author: | 123 | author: |
| @@ -110,3 +126,14 @@ comments: | |||
| 110 | createdAt: 2026-10-29T08:51:00.000Z | 126 | createdAt: 2026-10-29T08:51:00.000Z |
| 111 | body: | | 127 | body: | |
| 112 | Repris de #7 : les tests d'intégration avec de vrais agents utilisent le build tag `realagents` et lancent les agents via `scripts/agents.sh run <agent>` (limite + déchargement). Le SDK retenu est `github.com/coder/acp-go-sdk` v0.13.5 ([ADR 0001](docs/adr/0001-acp.md)) ; [spikes/acp-trace](spikes/acp-trace/main.go) montre son usage côté client. | 128 | Repris de #7 : les tests d'intégration avec de vrais agents utilisent le build tag `realagents` et lancent les agents via `scripts/agents.sh run <agent>` (limite + déchargement). Le SDK retenu est `github.com/coder/acp-go-sdk` v0.13.5 ([ADR 0001](docs/adr/0001-acp.md)) ; [spikes/acp-trace](spikes/acp-trace/main.go) montre son usage côté client. |
| 129 | + - id: 2 | ||
| 130 | + author: | ||
| 131 | + name: k33g | ||
| 132 | + email: ph.charriere@gmail.com | ||
| 133 | + createdAt: 2026-10-29T10:19:30.000Z | ||
| 134 | + body: | | ||
| 135 | + ## Résultat | ||
| 136 | + | ||
| 137 | + Package `internal/acp` : `Start(ctx, Spec, Options)` lance l'agent dans son propre groupe de processus, fait `initialize` (ACP v1, refuse une autre version), capture stderr (callback + 20 dernières lignes, ajoutées au message d'erreur d'un démarrage raté), `Close` ferme stdin puis tue le groupe après 5 s, `Done`/`Err` signalent un crash. Les types du SDK `coder/acp-go-sdk` restent dans le package. | ||
| 138 | + | ||
| 139 | + Tests : un faux agent (le binaire de test relancé en mode agent) couvre handshake, fermeture, agent récalcitrant, crash, mauvaise version, sortie prématurée, commande absente, délai d'initialize — tous avec `-race`. Test réel `realagents` avec Alice via `scripts/agents.sh` : OK (`make test-real`). | ||
modified
.tickets/issues/0011-gerer-le-cycle-de-vie-des-processus-agents.yaml +32 -9 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 11 |
| 3 | 3 | title: "Gérer le cycle de vie des processus agents" |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-29T07:20:09.000Z |
| 9 | -updatedAt: 2026-10-29T07:20:09.000Z | |
| 9 | +updatedAt: 2026-10-29T10:19:30.000Z | |
| 10 | 10 | labels: |
| 11 | 11 | - "kind::feature" |
| 12 | 12 | - "area::acp" |
| @@ -33,50 +33,73 @@ body: | | ||
| 33 | 33 | tasks: |
| 34 | 34 | - id: 1 |
| 35 | 35 | title: "AgentManager : démarrage paresseux" |
| 36 | - state: open | |
| 36 | + state: closed | |
| 37 | 37 | priority: high |
| 38 | 38 | author: |
| 39 | 39 | name: k33g |
| 40 | 40 | email: ph.charriere@gmail.com |
| 41 | 41 | createdAt: 2026-10-29T07:20:09.000Z |
| 42 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 43 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 42 | 44 | - id: 2 |
| 43 | 45 | title: "Arrêt après inactivité" |
| 44 | - state: open | |
| 46 | + state: closed | |
| 45 | 47 | priority: medium |
| 46 | 48 | author: |
| 47 | 49 | name: k33g |
| 48 | 50 | email: ph.charriere@gmail.com |
| 49 | 51 | createdAt: 2026-10-29T07:20:09.000Z |
| 52 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 53 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 50 | 54 | - id: 3 |
| 51 | 55 | title: "Limite d'agents simultanés" |
| 52 | - state: open | |
| 56 | + state: closed | |
| 53 | 57 | priority: high |
| 54 | 58 | author: |
| 55 | 59 | name: k33g |
| 56 | 60 | email: ph.charriere@gmail.com |
| 57 | 61 | createdAt: 2026-10-29T07:20:09.000Z |
| 62 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 63 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 58 | 64 | - id: 4 |
| 59 | 65 | title: "Machine à états et événements" |
| 60 | - state: open | |
| 66 | + state: closed | |
| 61 | 67 | priority: medium |
| 62 | 68 | author: |
| 63 | 69 | name: k33g |
| 64 | 70 | email: ph.charriere@gmail.com |
| 65 | 71 | createdAt: 2026-10-29T07:20:09.000Z |
| 72 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 73 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 66 | 74 | - id: 5 |
| 67 | 75 | title: "Gestion du crash et proposition de redémarrage" |
| 68 | - state: open | |
| 76 | + state: closed | |
| 69 | 77 | priority: medium |
| 70 | 78 | author: |
| 71 | 79 | name: k33g |
| 72 | 80 | email: ph.charriere@gmail.com |
| 73 | 81 | createdAt: 2026-10-29T07:20:09.000Z |
| 82 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 83 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 74 | 84 | - id: 6 |
| 75 | 85 | title: "Tests" |
| 76 | - state: open | |
| 86 | + state: closed | |
| 77 | 87 | priority: medium |
| 78 | 88 | author: |
| 79 | 89 | name: k33g |
| 80 | 90 | email: ph.charriere@gmail.com |
| 81 | 91 | createdAt: 2026-10-29T07:20:09.000Z |
| 82 | -comments: [] | |
| 92 | + updatedAt: 2026-10-29T10:19:30.000Z | |
| 93 | + closedAt: 2026-10-29T10:19:30.000Z | |
| 94 | +comments: | |
| 95 | + - id: 1 | |
| 96 | + author: | |
| 97 | + name: k33g | |
| 98 | + email: ph.charriere@gmail.com | |
| 99 | + createdAt: 2026-10-29T10:19:30.000Z | |
| 100 | + body: | | |
| 101 | + ## Résultat | |
| 102 | + | |
| 103 | + Package `internal/agents` : `Manager` avec démarrage paresseux (un seul démarrage pour plusieurs demandes simultanées), `Acquire`/release (états busy/ready), limite `maxRunningAgents` — **l'agent inoccupé utilisé le moins récemment est arrêté pour faire de la place** ; si tous sont occupés, le démarrage est refusé —, arrêt après inactivité (`StopIdle`, balayage toutes les 30 s), crash → état `error` avec la raison, jamais de redémarrage automatique (`Restart` le propose), `Reconfigure` (agents ajoutés/retirés, `outdated` si la définition change), journal de 200 lignes et événements `agent:state`/`agent:log`. 13 tests avec horloge simulée, `-race`. | |
| 104 | + | |
| 105 | + Vérifié dans l'application (Linux) : ▶ sur Alice démarre le vrai mm via `agents.sh`, fermer Sidekicks arrête les agents et décharge les modèles. | |
| @@ -1,12 +1,12 @@ | |||
| 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 11 | 2 | id: 11 |
| 3 | title: "Gérer le cycle de vie des processus agents" | 3 | title: "Gérer le cycle de vie des processus agents" |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-10-29T07:20:09.000Z | 8 | createdAt: 2026-10-29T07:20:09.000Z |
| 9 | -updatedAt: 2026-10-29T07:20:09.000Z | 9 | +updatedAt: 2026-10-29T10:19:30.000Z |
| 10 | labels: | 10 | labels: |
| 11 | - "kind::feature" | 11 | - "kind::feature" |
| 12 | - "area::acp" | 12 | - "area::acp" |
| @@ -33,50 +33,73 @@ body: | | |||
| 33 | tasks: | 33 | tasks: |
| 34 | - id: 1 | 34 | - id: 1 |
| 35 | title: "AgentManager : démarrage paresseux" | 35 | title: "AgentManager : démarrage paresseux" |
| 36 | - state: open | 36 | + state: closed |
| 37 | priority: high | 37 | priority: high |
| 38 | author: | 38 | author: |
| 39 | name: k33g | 39 | name: k33g |
| 40 | email: ph.charriere@gmail.com | 40 | email: ph.charriere@gmail.com |
| 41 | createdAt: 2026-10-29T07:20:09.000Z | 41 | createdAt: 2026-10-29T07:20:09.000Z |
| 42 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 43 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 42 | - id: 2 | 44 | - id: 2 |
| 43 | title: "Arrêt après inactivité" | 45 | title: "Arrêt après inactivité" |
| 44 | - state: open | 46 | + state: closed |
| 45 | priority: medium | 47 | priority: medium |
| 46 | author: | 48 | author: |
| 47 | name: k33g | 49 | name: k33g |
| 48 | email: ph.charriere@gmail.com | 50 | email: ph.charriere@gmail.com |
| 49 | createdAt: 2026-10-29T07:20:09.000Z | 51 | createdAt: 2026-10-29T07:20:09.000Z |
| 52 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 53 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 50 | - id: 3 | 54 | - id: 3 |
| 51 | title: "Limite d'agents simultanés" | 55 | title: "Limite d'agents simultanés" |
| 52 | - state: open | 56 | + state: closed |
| 53 | priority: high | 57 | priority: high |
| 54 | author: | 58 | author: |
| 55 | name: k33g | 59 | name: k33g |
| 56 | email: ph.charriere@gmail.com | 60 | email: ph.charriere@gmail.com |
| 57 | createdAt: 2026-10-29T07:20:09.000Z | 61 | createdAt: 2026-10-29T07:20:09.000Z |
| 62 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 63 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 58 | - id: 4 | 64 | - id: 4 |
| 59 | title: "Machine à états et événements" | 65 | title: "Machine à états et événements" |
| 60 | - state: open | 66 | + state: closed |
| 61 | priority: medium | 67 | priority: medium |
| 62 | author: | 68 | author: |
| 63 | name: k33g | 69 | name: k33g |
| 64 | email: ph.charriere@gmail.com | 70 | email: ph.charriere@gmail.com |
| 65 | createdAt: 2026-10-29T07:20:09.000Z | 71 | createdAt: 2026-10-29T07:20:09.000Z |
| 72 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 73 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 66 | - id: 5 | 74 | - id: 5 |
| 67 | title: "Gestion du crash et proposition de redémarrage" | 75 | title: "Gestion du crash et proposition de redémarrage" |
| 68 | - state: open | 76 | + state: closed |
| 69 | priority: medium | 77 | priority: medium |
| 70 | author: | 78 | author: |
| 71 | name: k33g | 79 | name: k33g |
| 72 | email: ph.charriere@gmail.com | 80 | email: ph.charriere@gmail.com |
| 73 | createdAt: 2026-10-29T07:20:09.000Z | 81 | createdAt: 2026-10-29T07:20:09.000Z |
| 82 | + updatedAt: 2026-10-29T10:19:30.000Z | ||
| 83 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 74 | - id: 6 | 84 | - id: 6 |
| 75 | title: "Tests" | 85 | title: "Tests" |
| 76 | - state: open | 86 | + state: closed |
| 77 | priority: medium | 87 | priority: medium |
| 78 | author: | 88 | author: |
| 79 | name: k33g | 89 | name: k33g |
| 80 | email: ph.charriere@gmail.com | 90 | email: ph.charriere@gmail.com |
| 81 | createdAt: 2026-10-29T07:20:09.000Z | 91 | createdAt: 2026-10-29T07:20:09.000Z |
| 82 | -comments: [] | 92 | + updatedAt: 2026-10-29T10:19:30.000Z |
| 93 | + closedAt: 2026-10-29T10:19:30.000Z | ||
| 94 | +comments: | ||
| 95 | + - id: 1 | ||
| 96 | + author: | ||
| 97 | + name: k33g | ||
| 98 | + email: ph.charriere@gmail.com | ||
| 99 | + createdAt: 2026-10-29T10:19:30.000Z | ||
| 100 | + body: | | ||
| 101 | + ## Résultat | ||
| 102 | + | ||
| 103 | + Package `internal/agents` : `Manager` avec démarrage paresseux (un seul démarrage pour plusieurs demandes simultanées), `Acquire`/release (états busy/ready), limite `maxRunningAgents` — **l'agent inoccupé utilisé le moins récemment est arrêté pour faire de la place** ; si tous sont occupés, le démarrage est refusé —, arrêt après inactivité (`StopIdle`, balayage toutes les 30 s), crash → état `error` avec la raison, jamais de redémarrage automatique (`Restart` le propose), `Reconfigure` (agents ajoutés/retirés, `outdated` si la définition change), journal de 200 lignes et événements `agent:state`/`agent:log`. 13 tests avec horloge simulée, `-race`. | ||
| 104 | + | ||
| 105 | + Vérifié dans l'application (Linux) : ▶ sur Alice démarre le vrai mm via `agents.sh`, fermer Sidekicks arrête les agents et décharge les modèles. | ||
modified
.tickets/issues/0012-shell-ui-a-panels-inspire-de-zed.yaml +69 -8 Large diff collapsed to keep the page fast — load it when you need it.
modified
.tickets/issues/0013-pont-d-evenements-entre-go-et-le-frontend.yaml +27 -7 Large diff collapsed to keep the page fast — load it when you need it.
added
.tickets/issues/0038-creer-un-kit-de-sandbox-avec-qlty-pour-le-contro.yaml +70 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
.tickets/milestones.yaml +1 -1 | @@ -5,7 +5,7 @@ milestones: | ||
| 5 | 5 | description: Specification of the project, settings, definition of tools |
| 6 | 6 | dueOn: 2026-10-30 |
| 7 | 7 | - title: "M1 · Fondations" |
| 8 | - state: open | |
| 8 | + state: closed | |
| 9 | 9 | description: "Squelette Go + Wails, chargement de la config YAML, client ACP capable de démarrer un agent et de faire le handshake, shell UI à panels vide." |
| 10 | 10 | dueOn: 2026-11-13 |
| 11 | 11 | - title: "M2 · Conversation avec un agent" |
| @@ -5,7 +5,7 @@ milestones: | |||
| 5 | description: Specification of the project, settings, definition of tools | 5 | description: Specification of the project, settings, definition of tools |
| 6 | dueOn: 2026-10-30 | 6 | dueOn: 2026-10-30 |
| 7 | - title: "M1 · Fondations" | 7 | - title: "M1 · Fondations" |
| 8 | - state: open | 8 | + state: closed |
| 9 | description: "Squelette Go + Wails, chargement de la config YAML, client ACP capable de démarrer un agent et de faire le handshake, shell UI à panels vide." | 9 | description: "Squelette Go + Wails, chargement de la config YAML, client ACP capable de démarrer un agent et de faire le handshake, shell UI à panels vide." |
| 10 | dueOn: 2026-11-13 | 10 | dueOn: 2026-11-13 |
| 11 | - title: "M2 · Conversation avec un agent" | 11 | - title: "M2 · Conversation avec un agent" |
modified
Makefile +65 -5 Large diff collapsed to keep the page fast — load it when you need it.
added
README.md +49 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
Taskfile.yml +68 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/Taskfile.yml +398 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/appicon.icon/Assets/wails_icon_vector.svg +9 -0 | new file mode 100644 | ||
| @@ -0,0 +1,9 @@ | ||
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 | +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |
| 3 | +<svg width="100%" height="100%" viewBox="0 0 583 533" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> | |
| 4 | + <g transform="matrix(1,0,0,1,-246,-251)"> | |
| 5 | + <g id="Ebene1"> | |
| 6 | + <path d="M246,251L265,784L401,784L506,450L507,450L505,784L641,784L829,251L682,251L596,567L595,567L596,251L478,251L378,568L391,251L246,251Z"/> | |
| 7 | + </g> | |
| 8 | + </g> | |
| 9 | +</svg> | |
| new file mode 100644 | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| 3 | +<svg width="100%" height="100%" viewBox="0 0 583 533" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> | ||
| 4 | + <g transform="matrix(1,0,0,1,-246,-251)"> | ||
| 5 | + <g id="Ebene1"> | ||
| 6 | + <path d="M246,251L265,784L401,784L506,450L507,450L505,784L641,784L829,251L682,251L596,567L595,567L596,251L478,251L378,568L391,251L246,251Z"/> | ||
| 7 | + </g> | ||
| 8 | + </g> | ||
| 9 | +</svg> | ||
added
build/appicon.icon/icon.json +51 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/appicon.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/build/appicon.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/build/appicon.png differ | Binary files /dev/null and b/build/appicon.png differ | ||
added
build/config.yml +87 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/Assets.car +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/Info.dev.plist +34 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/Info.plist +29 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/Taskfile.yml +230 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/dmg-background.png +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/dmg-file-icon.icns +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/dmg-file-icon.png +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/darwin/icons.icns +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/docker/Dockerfile.cross +225 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/docker/Dockerfile.server +67 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/Taskfile.yml +220 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/appimage/build.sh +35 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/desktop +13 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/nfpm/nfpm.yaml +80 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/nfpm/scripts/postinstall.sh +21 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/nfpm/scripts/postremove.sh +1 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/nfpm/scripts/preinstall.sh +1 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/linux/nfpm/scripts/preremove.sh +1 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/Taskfile.yml +195 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/icon.ico +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/info.json +15 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/msix/app_manifest.xml +55 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/msix/template.xml +54 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/nsis/project.nsi +119 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/nsis/wails_tools.nsh +261 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
build/windows/wails.exe.manifest +22 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/adr/0003-architecture.md +14 -5 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/diagrams/packages.drawio +27 -25 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/diagrams/packages.png +0 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/diagrams/packages.svg +63 -56 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/en/README.md +4 -4 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/en/explanation/architecture.md +5 -1 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/en/explanation/memory-and-local-models.md +2 -2 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/en/how-to/develop-the-application.md +49 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/en/how-to/run-the-tests.md +26 -13 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/en/how-to/test-milestone-m1-on-macos.md +112 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/en/reference/agents-and-events.md +51 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/en/reference/commands.md +51 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/en/reference/configuration.md +5 -5 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/en/tutorials/first-launch.md +95 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/fr/README.md +4 -4 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/fr/explanation/architecture.md +5 -1 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/fr/explanation/memoire-et-modeles-locaux.md +2 -2 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/fr/how-to/developper-l-application.md +49 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/fr/how-to/lancer-les-tests.md +26 -13 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/fr/how-to/tester-la-milestone-m1-sous-macos.md +112 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/fr/reference/agents-et-evenements.md +51 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/fr/reference/commandes.md +51 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/fr/reference/configuration.md +5 -5 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/fr/tutorials/premier-lancement.md +95 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/events/index.ts +25 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/agents/index.ts +10 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/agents/models.ts +42 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/app/agentservice.ts +51 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/app/configservice.ts +23 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/app/index.ts +14 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/app/models.ts +39 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/events/index.ts +8 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/git.rickub.com/bots-garden/sidekicks/internal/events/models.ts +49 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.ts +9 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +20 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/index.html +13 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/package.json +29 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/pnpm-lock.yaml +1108 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/pnpm-workspace.yaml +9 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/App.svelte +10 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/events.test.ts +57 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/events.ts +47 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/layout/Dock.svelte +30 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/layout/Shell.svelte +71 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/layout/StatusBar.svelte +35 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/AgentsPanel.svelte +58 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/ChannelsPanel.svelte +29 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/ConversationPanel.svelte +30 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/LogsPanel.svelte +28 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/SettingsPanel.svelte +53 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/index.ts +19 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/registry.test.ts +26 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/panels/registry.ts +46 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/state.svelte.ts +77 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/theme.test.ts +58 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/lib/theme.ts +42 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/main.ts +11 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/style.css +94 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/src/vite-env.d.ts +2 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/svelte.config.js +7 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/tsconfig.json +19 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
frontend/vite.config.ts +13 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
go.mod +14 -2 Large diff collapsed to keep the page fast — load it when you need it.
modified
go.sum +40 -4 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/acp/client.go +52 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/acp/conn.go +331 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/acp/conn_realagents_test.go +42 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/acp/conn_test.go +245 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/acp/process_other.go +14 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/acp/process_unix.go +20 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agents/manager.go +496 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agents/manager_test.go +431 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/app/app.go +121 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/app/app_test.go +141 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/app/services.go +90 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/config.go +303 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/config_test.go +322 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/default.go +63 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/locate.go +65 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/problems.go +450 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/save.go +86 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/testconfig_test.go +66 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/config/watch.go +65 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/events/events.go +110 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/events/events_test.go +57 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
main.go +87 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
schema/config.schema.json +8 -3 Large diff collapsed to keep the page fast — load it when you need it.
added
schema/testdata/invalid/idle-number-not-zero.yaml +4 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
schema/testdata/valid/idle-zero-number.yaml +4 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
scripts/check-license-headers.sh +61 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
scripts/check-license-headers_test.sh +64 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
scripts/install-test-config.sh +66 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
tools/go.mod +219 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
tools/go.sum +926 -0 Large diff collapsed to keep the page fast — load it when you need it.