aboutsummaryrefslogtreecommitdiff
path: root/docs/CANONICAL.md
blob: 84c8f7e1cc8397096fdc682a7d1ca991a3597cb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# Canonical ShiftPlanner — measurement record

Date: 2026-11-09
Scope: five divergent copies of the same application found under `spaces/`.
No source file was edited, moved, or deleted. All copies were read only, then
copied into this product tree.

## 1. Measured feature table

Produced by one pass over each file with `wc`, `md5sum` and `grep -o | wc -l`.
Pasted verbatim:

```text
FILE                                            LINES    BYTES                                MD5 OLLAMA AIWIRE  DND EXPORT   CDN  VERSION
spaces/mindtech/shiftplanner.html                2163   110972   5dc466b446ae3c19fffd9cd80f91461a      0      0    0      4     0      2.1
spaces/mindtech/downloads/shiftplanner-v12-ai.html   2789   136212   37207b2227899603f90c42e59ff1875a      4    126    0      4     0      2.1
spaces/mindtech/downloads/shiftplanner.html      1910    98435   a59dedc7608243985aad1d59b880bddd      0      0    0      4     0      2.0
spaces/mindtech/shiftplanner_v1.3.html           1434    70415   daa2a71c94c2d0e5cb585857be5e4721     23     26    4      2     0      1.2
spaces/agando/shiftplanner_v1.3.html             1627    81158   710875062b293ed78698d774696058ec     45     27    4      2     0      1.3
```

Column definitions (all counts are occurrences of the regex, not lines):

| Column | Meaning |
|---|---|
| `LINES` / `BYTES` | `wc -l` / `wc -c` |
| `MD5` | `md5sum` of the source file |
| `OLLAMA` | `grep -o -i 'ollama'` — case-insensitive occurrences |
| `AIWIRE` | `grep -o -i -E '\bai\b\|assistant'` — AI/assistant wiring tokens |
| `DND` | `grep -o -i -E 'draggable\|dragstart'` — real drag-and-drop handlers |
| `EXPORT` | `grep -o -E 'exportCSV\|toBlob\|download'` — export code paths |
| `CDN` | `grep -o -E 'src="http'` — external `<script src="http…>` dependencies |
| `VERSION` | the version literal the file itself declares (`version:'x.y'` in its save/export payload, or `version:'2.x'` in state) |

Notes on measurement honesty:

- `DND` deliberately excludes the bare word `drop`, because `drop` also matches
  `dropdown` and `backdrop-filter`. Under the looser
  `draggable|dragstart|drop` regex the three v2.x files score 1–2, but those
  hits are CSS/UI strings only: `dragstart` is 0 and `draggable` is 0 in all
  three v2.x files, so they have **no** drag-and-drop.
- `CDN` is 0 for every file. A wider sweep for `src="http`, `href="http`,
  `@import` and `fonts.googleapis` also returned nothing, so all five copies
  are self-contained single files with no network dependency at load time.
- `AIWIRE` 126 vs. the "~96" figure in the task context: 96 is reproducible as
  the count of *lines* containing an AI token. The table reports occurrence
  count, which is the more meaningful measure of wiring density.

### Reconciling the "ollama" numbers

The task context states the canonical copy has 0 `ollama` refs and the two
v1.3 copies have 12 and 21. Measured result:

| File | `grep -o 'ollama'` (case-sensitive occurrences) | `grep -c 'ollama'` (matching lines) | `grep -o -i 'ollama'` (any case) |
|---|---|---|---|
| canonical (v12-ai) | **0** | 0 | 4 |
| mindtech v1.3 | 13 | **12** | 23 |
| agando v1.3 | 25 | **21** | 45 |

So the context figures are case-sensitive *line* counts. They are correct as
stated, but they understate the canonical file's Ollama usage: the canonical
contains four capitalised `Ollama` strings and calls the Ollama HTTP API
directly. The claim "the canonical has no Ollama path" would be false. What is
true is that the canonical's AI path is **Ollama-native and endpoint-driven**,
while the v1.3 copies carry a **multi-provider** abstraction (Ollama + OpenAI +
Anthropic) — a different architecture, not a strictly larger one. See §4.

## 2. Decision

**Canonical: `spaces/mindtech/downloads/shiftplanner-v12-ai.html`**
→ published here as `src/index.html` (md5 `37207b2227899603f90c42e59ff1875a`,
136,212 bytes, 2,789 lines).

One-line reason: it is a strict functional superset — it contains every
function present in both other v2.x copies (verified by set difference of
`function` names: **zero** functions unique to either sibling) and adds the
entire AI advisor panel on top, while remaining a single self-contained file
with no CDN dependency.

Evidence for the superset claim — the function-name set of each sibling minus
the canonical's set is empty:

```text
=== spaces/mindtech/shiftplanner.html  (functions NOT in canonical):

=== spaces/mindtech/downloads/shiftplanner.html  (functions NOT in canonical):

```

The two v1.3 copies, by contrast, are a **different, older codebase**
(1,434 / 1,627 lines vs 2,789) with roughly 50 functions absent from the
canonical. They have **no** shift templates (`saveTemplate`/`applyTemplate`
count 0; their only "template" matches are `grid-template-columns` CSS), **no**
day notes (`dayNote` count 0) and **no** CSV export (`exportCSV` count 0).
They do keep automatic generation (`autoGeneratePlan`), fairness options
(`Wochenende fair verteilen` / "distribute weekends fairly") and conflict
handling (`detectAllConflicts`, `clearAllConflicts`), under a different
codebase and with a **German-language UI**. They also add real drag-and-drop
and a multi-provider AI chat. They are therefore not candidates for canonical,
but they are worth archiving as feature donors.

## 3. Archived copies

| Archive file | Origin | Verdict |
|---|---|---|
| `archive/mindtech__shiftplanner.html` | `spaces/mindtech/shiftplanner.html` | **nothing found** — identical feature set to the canonical minus the AI panel; 0 functions and 0 features unique to it. |
| `archive/mindtech__downloads__shiftplanner.html` | `spaces/mindtech/downloads/shiftplanner.html` | **nothing found** — the v2.0 predecessor; a strict subset of the canonical in both functions and UI strings. |
| `archive/mindtech__shiftplanner_v1.3.html` | `spaces/mindtech/shiftplanner_v1.3.html` | **adds real drag-and-drop** and a 3-provider AI layer (see below). |
| `archive/agando__shiftplanner_v1.3.html` | `spaces/agando/shiftplanner_v1.3.html` | **adds real drag-and-drop** plus the most complete Ollama integration of the five (proxy path, model refresh, timeouts, connection test). |

What the two v1.3 copies have that the canonical does not, verified by grep:

- **Drag-and-drop scheduling** — `draggable="true"`, `ondragstart`,
  `ondragover`, `ondrop`, and handlers `onDragStart` / `onDrop` /
  `onDragOver` / `onDragLeave` / `onDragEnd`. The canonical has **0** of these
  (`draggable` 0, `dragstart` 0); it assigns workers via modals instead.
- **Multi-provider AI** — both define `callLLM`, `sendChat`, `processChatMessage`,
  `applyChatAction`, `chatAction`, `mockAgent`, `onProviderChange`; the
  canonical's AI is single-provider (Ollama) and conversational only.
  Endpoints observed:
  - `http://localhost:11434` (Ollama)
  - `https://api.openai.com/v1/chat/completions` + `https://api.openai.com/v1/models`
  - `https://api.anthropic.com/v1/messages` (with `anthropic-version` and
    `anthropic-dangerous-direct-browser-access` headers in the agando copy)
- **Different localStorage schema** — key `schichtplan_v12` with
  `loadState` / `saveState`, versus the canonical's key `shiftplanner_v2` with
  `loadFromStorage` / `saveToStorage`. Any migration between the two needs an
  explicit field mapping: the v1.3 payloads carry
  `employees` / `plan` / `vacations` / `absences` / `customShifts` / `settings`,
  the canonical carries `workers` / `shifts` / `assignments` / `customShifts` /
  `templates` / `settings`.
- **Extra functions unique to the agando copy** — `refreshOllamaModels`,
  `testConnection`, `withTimeout`, `callProvider`, `providerName`,
  `dateKeyOf`, `esc`.
- **Export formats differ in the other direction** — both v1.3 copies export
  **JSON only** (`exportCSV` count 0); the canonical exports **both JSON and
  CSV**. This is a genuine canonical advantage.

## 4. What the canonical's AI path actually calls

The AI panel in `src/index.html` is wired to a locally running Ollama server.
Exact strings, from grep:

```text
921:    let aiEndpoint = 'http://localhost:11434';
922:    let aiModel = localStorage.getItem('sp_ai_model') || 'llama3.2';
2478:        fetch(aiEndpoint + '/api/tags', {
2479:            method: 'GET',
2556:        fetch(aiEndpoint + '/api/generate', {
2486 (testAIConnection)  models = data.models || []
869:  <input ... id="aiEndpointInput" value="http://localhost:11434" placeholder="http://localhost:11434">
870:  <div class="help-text">Ollama server URL. Leave default for local Ollama.</div>
```

- **Base URL:** `http://localhost:11434` (editable in Settings, persisted to
  `localStorage['sp_ai_endpoint']`).
- **Endpoints called:**
  - `GET  {endpoint}/api/tags` — connectivity check / model discovery.
  - `POST {endpoint}/api/generate` — chat completion, body:
    `{ model, prompt, stream: false, options: { temperature: 0.4, num_predict: 1024 } }`,
    reply read from `data.response`.
- **Model identifiers offered in the UI select:** `llama3.2` (default),
  `mistral`, `llama3.1`, `phi3`, `gemma2`, `minimax-m3:cloud`.
  The model choice persists to `localStorage['sp_ai_model']`.
- **No cloud inference endpoint is contacted.** There is no `api.openai.com`,
  `api.anthropic.com` or `generativelanguage` reference anywhere in the
  canonical; the only network calls are to the user-configured Ollama base URL.
- **Graceful degradation:** on failure the panel reports
  `Not connected (start Ollama)` and the rest of the app is unaffected, so the
  scheduler works fully with no server running.

## 5. Provenance

`src/index.html` is a byte-for-byte copy of the canonical source:

```text
37207b2227899603f90c42e59ff1875a  products/shiftplanner/src/index.html
37207b2227899603f90c42e59ff1875a  spaces/mindtech/downloads/shiftplanner-v12-ai.html
```

All four archived files were verified md5-identical to their sources after
copying. The originals under `spaces/` are unchanged.