devcontour-harness 0.1.0-alpha.11 → 0.1.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -5
- package/docs/architecture.md +6 -5
- package/docs/quickstart.md +1 -1
- package/docs/release-notes/0.1.0-alpha.12.md +66 -0
- package/docs/standalone.md +25 -4
- package/docs/upgrade.md +14 -14
- package/package.json +1 -1
- package/skills/harness/SKILL.md +17 -15
- package/skills/harness-setup/SKILL.md +356 -0
package/README.md
CHANGED
|
@@ -5,16 +5,17 @@ Headless-движок исполнения инженерных поручени
|
|
|
5
5
|
интеграция с принятой веткой через compare-and-swap и машинный результат с SHA
|
|
6
6
|
и доказательствами.
|
|
7
7
|
|
|
8
|
-
> Статус: `0.1.0-alpha.
|
|
8
|
+
> Статус: `0.1.0-alpha.12` — предварительный выпуск (alpha). Договоры
|
|
9
9
|
> `v1alpha1` могут измениться между alpha-версиями; закрепляйте точную версию.
|
|
10
10
|
> Файл → ревью плана → кандидат → интеграция → принятие → результат JSON, с
|
|
11
11
|
> ограниченным восстановлением, повторным использованием кандидата, бюджетами,
|
|
12
12
|
> потребителями, свойствами и корпусом, совместной проверкой репозиториев и
|
|
13
13
|
> явным режимом одного вендора.
|
|
14
14
|
|
|
15
|
-
Пакет включает встроенные профили стеков (`profiles/`),
|
|
16
|
-
`skills/harness/SKILL.md`
|
|
17
|
-
|
|
15
|
+
Пакет включает встроенные профили стеков (`profiles/`), skills
|
|
16
|
+
`skills/harness/SKILL.md` (работа с поручениями) и
|
|
17
|
+
`skills/harness-setup/SKILL.md` (установка, первая настройка и обновление
|
|
18
|
+
версии), шаблоны политики, графа и инструкции агентам (`templates/`).
|
|
18
19
|
|
|
19
20
|
## Требования
|
|
20
21
|
|
|
@@ -27,7 +28,7 @@ Headless-движок исполнения инженерных поручени
|
|
|
27
28
|
Из npm — точная версия (воспроизводимо) или последняя alpha по тегу:
|
|
28
29
|
|
|
29
30
|
```sh
|
|
30
|
-
npm install --save-exact devcontour-harness@0.1.0-alpha.
|
|
31
|
+
npm install --save-exact devcontour-harness@0.1.0-alpha.12 # точная версия
|
|
31
32
|
# или: npm install --save-exact devcontour-harness@alpha # текущая alpha
|
|
32
33
|
npx harness --version
|
|
33
34
|
```
|
|
@@ -35,6 +36,11 @@ npx harness --version
|
|
|
35
36
|
Выпуски публикуются под тегом `alpha`; ставьте точную версию или `@alpha`,
|
|
36
37
|
а не версию по умолчанию без тега.
|
|
37
38
|
|
|
39
|
+
Чтобы не менять зависимости и lockfile существующего проекта, пакет ставят в
|
|
40
|
+
отдельный каталог инструментов — снаружи репозитория или в `.harness-tools/`
|
|
41
|
+
внутри него ([standalone](docs/standalone.md#установка), skill
|
|
42
|
+
[harness-setup](skills/harness-setup/SKILL.md)).
|
|
43
|
+
|
|
38
44
|
Из локального архива `devcontour-harness-<version>.tgz` (поддерживаемый
|
|
39
45
|
способ без registry):
|
|
40
46
|
|
|
@@ -117,6 +123,18 @@ PASS» нет. Адаптеры хоста реализуют порты `Execut
|
|
|
117
123
|
`devcontour-harness/schemas/<имя>.schema.json`. Декларации используют типы
|
|
118
124
|
Node.js: TypeScript-потребителю нужен `@types/node` (или `skipLibCheck`).
|
|
119
125
|
|
|
126
|
+
## Выпуск 0.1.0-alpha.12
|
|
127
|
+
|
|
128
|
+
Skill установки и обновления. Подробно —
|
|
129
|
+
[заметки выпуска](docs/release-notes/0.1.0-alpha.12.md).
|
|
130
|
+
|
|
131
|
+
- `skills/harness-setup/SKILL.md` — агент один раз спрашивает решения первой
|
|
132
|
+
настройки (новый или существующий проект, ветка, каталог установки —
|
|
133
|
+
`.harness-tools/` в проекте или снаружи, источник пакета, writer и reviewer
|
|
134
|
+
с моделями, согласование, источник задач: файлы или Relay), ставит точную
|
|
135
|
+
версию, выполняет `init` и обновляет версию с копией state и проверкой
|
|
136
|
+
совместимости. Движок, договоры и формат состояния не менялись.
|
|
137
|
+
|
|
120
138
|
## Выпуск 0.1.0-alpha.11
|
|
121
139
|
|
|
122
140
|
Профили в форме хоста. Подробно —
|
|
@@ -226,6 +244,7 @@ alpha.5 не читает; прежний DevContour его открывает
|
|
|
226
244
|
## Документация
|
|
227
245
|
|
|
228
246
|
- [Быстрый старт по шагам](docs/quickstart.md)
|
|
247
|
+
- [Установка, первая настройка и обновление версии — skill harness-setup](skills/harness-setup/SKILL.md)
|
|
229
248
|
- [Самостоятельный проект: init, планирование (plan-request, plan-check), explain, capabilities, проекции](docs/standalone.md)
|
|
230
249
|
- [Архитектура и границы доверия](docs/architecture.md)
|
|
231
250
|
- [Договоры: входы, выходы, порты, ошибки, CLI](docs/contracts.md)
|
package/docs/architecture.md
CHANGED
|
@@ -74,8 +74,8 @@ RunResult (SHA, evidence, ограничения) -> ResultSink
|
|
|
74
74
|
Таблица перечисляет каталоги `src/`. Git-операции — worktrees, snapshots,
|
|
75
75
|
проверка области, candidate/integration, CAS и recovery — отдельного каталога
|
|
76
76
|
не образуют: они в `engine` (`runner.ts`, `joint-runner.ts`), `control`
|
|
77
|
-
(`base-move.ts`) и `verification`.
|
|
78
|
-
|
|
77
|
+
(`base-move.ts`) и `verification`. Поставляемые skills лежат в корневом
|
|
78
|
+
каталоге пакета `skills/`, шаблоны — в `templates/`; исполняемые гарантии
|
|
79
79
|
остаются в движке.
|
|
80
80
|
|
|
81
81
|
Модули `setup`, `planning`, `explain`, `projections`, `catalog` и разрешение
|
|
@@ -413,9 +413,10 @@ runtime-граф пакета.
|
|
|
413
413
|
|
|
414
414
|
## Профили, skills и шаблоны
|
|
415
415
|
|
|
416
|
-
Встроенные профили (`profiles/`),
|
|
417
|
-
|
|
418
|
-
|
|
416
|
+
Встроенные профили (`profiles/`), skills (`skills/harness/SKILL.md` — работа
|
|
417
|
+
с поручениями, `skills/harness-setup/SKILL.md` — установка, первая настройка
|
|
418
|
+
и обновление версии) и шаблоны (`templates/`: политика, граф, инструкция
|
|
419
|
+
агентам репозитория) входят в пакет. Skills и шаблоны только объясняют использование: движок, runner и проверки их
|
|
419
420
|
не читают, и удаление каталога skills не отключает ни gates, ни ревью, ни
|
|
420
421
|
область записи, ни fencing — это проверяет smoke установленного архива.
|
|
421
422
|
Профиль — вход для сборки политики, а не исполняемый объект: разрешение не
|
package/docs/quickstart.md
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# devcontour-harness 0.1.0-alpha.12
|
|
2
|
+
|
|
3
|
+
Skill установки, первой настройки и обновления версии. Движок, CLI, договоры
|
|
4
|
+
`v1alpha1`, политика, профили и формат состояния не менялись; gates,
|
|
5
|
+
`maxAttempts`, бюджеты попыток и повторов, правила находок, изоляция и
|
|
6
|
+
принятие target ref — прежние.
|
|
7
|
+
|
|
8
|
+
## Что нового
|
|
9
|
+
|
|
10
|
+
- **`skills/harness-setup/SKILL.md`** — маршрут для агента пользователя:
|
|
11
|
+
- один раунд вопросов: существующий или новый проект, ветка подготовки,
|
|
12
|
+
каталог установки (`.harness-tools/` внутри проекта или каталог
|
|
13
|
+
снаружи), источник пакета (npm `@alpha`, сведённый к точной версии,
|
|
14
|
+
точная версия или архив с sha256), writer и reviewer, модели и effort,
|
|
15
|
+
ревью тем же вендором (только явным «да»), режим согласования плана,
|
|
16
|
+
источник задач (файлы графа, Relay v1, Relay-2), коммит подготовки;
|
|
17
|
+
- новый проект: Git, `package.json` со scripts `check` и `test` (JUnit в
|
|
18
|
+
`.reports/junit.xml`) и lockfile — только с согласия пользователя;
|
|
19
|
+
- установка в проект: версию закрепляют `.harness-tools/package.json` и
|
|
20
|
+
`package-lock.json`, `node_modules/` не коммитится, каталог добавляется в
|
|
21
|
+
`protectedPaths` политики; из архива — каталог целиком в
|
|
22
|
+
`.git/info/exclude`;
|
|
23
|
+
- `init` и правки политики по ответам: `model`, `effort` (только для
|
|
24
|
+
codex), reviewer того же вендора для ревью кода и контракта
|
|
25
|
+
(`same-vendor-allowed`), `approvalMode`; проверка `doctor --policy`
|
|
26
|
+
(схема, runtime, toolchain), `init --plan` без конфликтов и `validate`
|
|
27
|
+
первого графа (перекрёстные проверки политики);
|
|
28
|
+
- `connector.json` для Relay и проверки без записи в Relay
|
|
29
|
+
(`source-check`, `source-snapshot`);
|
|
30
|
+
- обновление: остановка writers, копия state, проверка копии новой
|
|
31
|
+
версией, установка, `doctor --state`, `init --plan` (изменённый профиль,
|
|
32
|
+
перенос репозитория или версия API — решение человека; manifest
|
|
33
|
+
пересоздаётся с прежним state, политика не перегенерируется), `validate`
|
|
34
|
+
графов, `resume`; откат по [upgrade](../upgrade.md);
|
|
35
|
+
- восстановление закреплённой версии в новом клоне — `npm ci --prefix
|
|
36
|
+
.harness-tools`.
|
|
37
|
+
- `skills/harness/SKILL.md` по-прежнему ведёт работу с поручениями; новый
|
|
38
|
+
skill передаёт ему управление после подготовки. В нём уточнены каталог
|
|
39
|
+
установки (снаружи или `.harness-tools/`) и причины `content-differs` на
|
|
40
|
+
`project.json` после обновления или переноса.
|
|
41
|
+
|
|
42
|
+
## Документация
|
|
43
|
+
|
|
44
|
+
- [standalone](../standalone.md): установка вне проекта или в
|
|
45
|
+
`.harness-tools/`, закрепление версии файлом, обновление.
|
|
46
|
+
- [architecture](../architecture.md): состав поставляемых skills.
|
|
47
|
+
- [upgrade](../upgrade.md): столбец alpha.12 в матрице форматов.
|
|
48
|
+
|
|
49
|
+
## Совместимость
|
|
50
|
+
|
|
51
|
+
Формат состояния не менялся: alpha.12 читает всё, что читает alpha.11, а
|
|
52
|
+
alpha.11 — всё, что пишет alpha.12. Обновление и откат — по
|
|
53
|
+
[upgrade](../upgrade.md).
|
|
54
|
+
|
|
55
|
+
## Проверка выпуска
|
|
56
|
+
|
|
57
|
+
`npm run check` (lint, typecheck, schemas, build, весь набор тестов, package
|
|
58
|
+
smoke из установленного архива) на macOS arm64, Node.js 24.3. Тест skill
|
|
59
|
+
сверяет с договором CLI каждую команду маршрута: команду, флаги и
|
|
60
|
+
обязательные аргументы полных вызовов; smoke установленного архива требует
|
|
61
|
+
оба skill. Маршрут установки в `.harness-tools/` пройден вручную на свежем
|
|
62
|
+
npm-репозитории с опубликованной alpha.11: `init --plan`, `init`, правки
|
|
63
|
+
политики, `doctor --policy`, отказ `validate` для `effort` не у codex,
|
|
64
|
+
пересоздание manifest с прежним state. Живые модели не вызывались;
|
|
65
|
+
проверка DevContour для alpha.12 не повторялась (движок не менялся,
|
|
66
|
+
[проверенные версии](../compatibility-versions.md) относятся к alpha.11).
|
package/docs/standalone.md
CHANGED
|
@@ -4,20 +4,41 @@
|
|
|
4
4
|
без внешнего хоста: пользователь называет репозиторий, цель и ограничения,
|
|
5
5
|
остальное агент получает от `harness init`, а план составляет сам через
|
|
6
6
|
`harness plan-request` и `harness plan-check`. Пошаговый маршрут для агента —
|
|
7
|
-
skill [`skills/harness/SKILL.md`](../skills/harness/SKILL.md)
|
|
7
|
+
skill [`skills/harness/SKILL.md`](../skills/harness/SKILL.md); установку,
|
|
8
|
+
первую настройку и обновление версии ведёт skill
|
|
9
|
+
[`skills/harness-setup/SKILL.md`](../skills/harness-setup/SKILL.md).
|
|
8
10
|
|
|
9
|
-
## Установка
|
|
11
|
+
## Установка
|
|
10
12
|
|
|
11
13
|
Пакет ставится в отдельный каталог инструментов, а не в зависимости проекта:
|
|
12
|
-
`package.json` и lockfile проекта не меняются.
|
|
14
|
+
`package.json` и lockfile проекта не меняются. Каталог — снаружи
|
|
15
|
+
репозитория или внутри него, в `.harness-tools/`.
|
|
13
16
|
|
|
14
17
|
```sh
|
|
15
|
-
npm install --prefix <tooldir> --omit=dev --ignore-scripts
|
|
18
|
+
npm install --prefix <tooldir> --save-exact --omit=dev --ignore-scripts devcontour-harness@<version>
|
|
19
|
+
# или из архива: npm install --prefix <tooldir> --omit=dev --ignore-scripts ./devcontour-harness-<version>.tgz
|
|
16
20
|
H=<tooldir>/node_modules/.bin/harness
|
|
17
21
|
$H --version
|
|
18
22
|
$H doctor
|
|
19
23
|
```
|
|
20
24
|
|
|
25
|
+
Внутри проекта (`<tooldir>` = `<repo>/.harness-tools`) версию закрепляют
|
|
26
|
+
`.harness-tools/package.json` и `package-lock.json`: их коммитят вместе с
|
|
27
|
+
`.harness/`, а `node_modules/` исключает `.harness-tools/.gitignore`. Чтобы
|
|
28
|
+
поручение не могло изменить инструмент, которым его проверяют, каталог
|
|
29
|
+
добавляют в `protectedPaths` политики. Установка из архива записывает в
|
|
30
|
+
`package.json` локальный путь `file:` — такой каталог целиком исключают через
|
|
31
|
+
`.git/info/exclude`. Worktrees попыток создаются из Git, поэтому
|
|
32
|
+
неотслеживаемый каталог инструментов в них не попадает. Состояние исполнения
|
|
33
|
+
в любом случае остаётся вне репозитория.
|
|
34
|
+
|
|
35
|
+
Обновление — смена закреплённой версии в том же каталоге по процедуре
|
|
36
|
+
[upgrade](upgrade.md): остановка writers, копия state, проверка копии новой
|
|
37
|
+
версией, установка, `doctor --state`, `init --plan`, `validate` графов,
|
|
38
|
+
`resume`. Новая версия не перегенерирует политику: если изменился встроенный
|
|
39
|
+
профиль, `init --plan` сообщает `content-differs` на `project.json`, и решение
|
|
40
|
+
принимает человек.
|
|
41
|
+
|
|
21
42
|
## `harness init`
|
|
22
43
|
|
|
23
44
|
```sh
|
package/docs/upgrade.md
CHANGED
|
@@ -21,20 +21,20 @@
|
|
|
21
21
|
|
|
22
22
|
## Матрица форматов
|
|
23
23
|
|
|
24
|
-
| Состояние, записанное… | Читает 0.1.0-alpha.1 | Читает 0.1.0-alpha.2 | Читает 0.1.0-alpha.6 | Читает 0.1.0-alpha.7 | Читает 0.1.0-alpha.8 | Читает 0.1.0-alpha.9 | Читает 0.1.0-alpha.10 | Читает 0.1.0-alpha.11 | Пишет поверх | Примечание |
|
|
25
|
-
| ------------------------------------------------------------------------------ | ------------------------ | ------------------------ | ----------------------- | -------------------- | -------------------- | -------------------- | --------------------- | --------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
26
|
-
| standalone `stateVersion: 1` версией alpha.1 | да | да | да | да | да | да | да | да | да | одна база SQLite: документ, события, локальные записи |
|
|
27
|
-
| хост, центральная база | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | данные не переносятся; новые поля необязательны |
|
|
28
|
-
| хост, базы компонентов | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | нужна копия всех баз при остановленных writers |
|
|
29
|
-
| alpha.2 после штатной остановки controller | да | да | да | да | да | да | да | да | да | роль controller снята — нового поля в состоянии нет |
|
|
30
|
-
| alpha.2 с живой или брошенной ролью controller | **нет**, отказ до записи | да | да | да | да | да | да | да | — | роль хранит `engineVersion`; строгая схема alpha.1 его не знает → откат через копию |
|
|
31
|
-
| alpha.4 с совместной проверкой | **нет**, отказ до записи | **нет**, отказ до записи | да | да | да | да | да | да | — | проверка хранит `engineVersion`; прежние версии его не знают → откат через копию |
|
|
32
|
-
| alpha.6 standalone с записями ревью нового протокола или доставкой `uncertain` | **нет**, отказ до записи | **нет**, отказ до записи | да | да | да | да | да | да | — | `reviewRound`, `findings[].id/status`, статус доставки `uncertain`; alpha.4/alpha.5 отказывают `STATE_VERSION_UNSUPPORTED` до записи → откат через копию |
|
|
33
|
-
| alpha.6, хост DevContour (адаптер alpha.4) | — | — | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | адаптер DevContour alpha.4 открывает такое состояние без отказа и пишет роль controller и события; новые поля сохраняются → для отката всё равно копия |
|
|
34
|
-
| alpha.7 с новым `inspection` ревью кода | не проверялось | не проверялось | **нет** (строгая схема) | да | да | да | да | да | — | новые значения `source`, `exitCode: null`, `origins`/`context`/`excluded`; строгая схема alpha.6 их не принимает, поведение прежних версий при открытии не проверялось → откат через копию |
|
|
35
|
-
| неизвестная `stateVersion` | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет | `STATE_VERSION_UNSUPPORTED`, exit 4 |
|
|
36
|
-
|
|
37
|
-
Столбец alpha.2 относится и к alpha.3; alpha.4 и alpha.5 читают все строки, кроме неизвестной `stateVersion` и строк alpha.6 с новыми полями (standalone — отказ до записи) и строки alpha.7. alpha.8, alpha.9, alpha.10 и alpha.
|
|
24
|
+
| Состояние, записанное… | Читает 0.1.0-alpha.1 | Читает 0.1.0-alpha.2 | Читает 0.1.0-alpha.6 | Читает 0.1.0-alpha.7 | Читает 0.1.0-alpha.8 | Читает 0.1.0-alpha.9 | Читает 0.1.0-alpha.10 | Читает 0.1.0-alpha.11 | Читает 0.1.0-alpha.12 | Пишет поверх | Примечание |
|
|
25
|
+
| ------------------------------------------------------------------------------ | ------------------------ | ------------------------ | ----------------------- | -------------------- | -------------------- | -------------------- | --------------------- | --------------------- | --------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
26
|
+
| standalone `stateVersion: 1` версией alpha.1 | да | да | да | да | да | да | да | да | да | да | одна база SQLite: документ, события, локальные записи |
|
|
27
|
+
| хост, центральная база | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | данные не переносятся; новые поля необязательны |
|
|
28
|
+
| хост, базы компонентов | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | нужна копия всех баз при остановленных writers |
|
|
29
|
+
| alpha.2 после штатной остановки controller | да | да | да | да | да | да | да | да | да | да | роль controller снята — нового поля в состоянии нет |
|
|
30
|
+
| alpha.2 с живой или брошенной ролью controller | **нет**, отказ до записи | да | да | да | да | да | да | да | да | — | роль хранит `engineVersion`; строгая схема alpha.1 его не знает → откат через копию |
|
|
31
|
+
| alpha.4 с совместной проверкой | **нет**, отказ до записи | **нет**, отказ до записи | да | да | да | да | да | да | да | — | проверка хранит `engineVersion`; прежние версии его не знают → откат через копию |
|
|
32
|
+
| alpha.6 standalone с записями ревью нового протокола или доставкой `uncertain` | **нет**, отказ до записи | **нет**, отказ до записи | да | да | да | да | да | да | да | — | `reviewRound`, `findings[].id/status`, статус доставки `uncertain`; alpha.4/alpha.5 отказывают `STATE_VERSION_UNSUPPORTED` до записи → откат через копию |
|
|
33
|
+
| alpha.6, хост DevContour (адаптер alpha.4) | — | — | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | адаптер DevContour alpha.4 открывает такое состояние без отказа и пишет роль controller и события; новые поля сохраняются → для отката всё равно копия |
|
|
34
|
+
| alpha.7 с новым `inspection` ревью кода | не проверялось | не проверялось | **нет** (строгая схема) | да | да | да | да | да | да | — | новые значения `source`, `exitCode: null`, `origins`/`context`/`excluded`; строгая схема alpha.6 их не принимает, поведение прежних версий при открытии не проверялось → откат через копию |
|
|
35
|
+
| неизвестная `stateVersion` | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет | `STATE_VERSION_UNSUPPORTED`, exit 4 |
|
|
36
|
+
|
|
37
|
+
Столбец alpha.2 относится и к alpha.3; alpha.4 и alpha.5 читают все строки, кроме неизвестной `stateVersion` и строк alpha.6 с новыми полями (standalone — отказ до записи) и строки alpha.7. alpha.8, alpha.9, alpha.10, alpha.11 и alpha.12 формат состояния не меняют и читают всё, что читает alpha.7. Каждая следующая версия добавляет сюда свой столбец. Отказ неизвестного
|
|
38
38
|
формата до записи проверяют тесты совместимости пакета
|
|
39
39
|
<!-- repo-only -->(`tests/compatibility.test.ts`)<!-- /repo-only -->.
|
|
40
40
|
|
package/package.json
CHANGED
package/skills/harness/SKILL.md
CHANGED
|
@@ -39,8 +39,10 @@ shasum -a 256 <file.tgz>
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Use the exact tarball (or exact registry version) you were given and record
|
|
42
|
-
its sha256. Do not install it into the project: the project
|
|
43
|
-
and lockfile stay untouched.
|
|
42
|
+
its sha256. Do not install it into the project's dependencies: the project
|
|
43
|
+
`package.json` and lockfile stay untouched. `<tooldir>` is outside the
|
|
44
|
+
repository or `<repo>/.harness-tools`; the `harness-setup` skill of the
|
|
45
|
+
package covers both, the version pin and upgrades.
|
|
44
46
|
|
|
45
47
|
### 2. Check the machine
|
|
46
48
|
|
|
@@ -65,19 +67,19 @@ Schema of input and response, and the byte limits. Read only.
|
|
|
65
67
|
interruption it resumes from the saved manifest decisions and writes only
|
|
66
68
|
what is missing.
|
|
67
69
|
|
|
68
|
-
| Conflict or refusal | Meaning
|
|
69
|
-
| --------------------------------------------------- |
|
|
70
|
-
| `symlink` | the path or an ancestor (`conflictPath`) is a symlink
|
|
71
|
-
| `ancestor-not-directory` | an ancestor of the path is a file
|
|
72
|
-
| `not-regular-file` | the destination exists and is not a regular file
|
|
73
|
-
| `outside-root` | the destination resolves outside the repository
|
|
74
|
-
| `content-differs` on `.harness/project.json` | an explicit `--writer` or `--profile` differs from the saved manifest
|
|
75
|
-
| `content-differs` on `.harness/policy.json` | the saved policy's writer differs from the manifest or explicit `--writer`
|
|
76
|
-
| `INVALID_INPUT` with a path | not a Git root, invalid manifest or policy (also a truncated write), `--state` inside the repository
|
|
77
|
-
| `NOT_READY` `no-commits` | the repository has no commits
|
|
78
|
-
| `NOT_READY` `stack-ambiguous` / `stack-unsupported` | both lockfiles, or none
|
|
79
|
-
| `NOT_READY` toolchain problems | missing scripts, wrong tool versions
|
|
80
|
-
| `CONTROLLER_BUSY` | the repository is already owned by another controller
|
|
70
|
+
| Conflict or refusal | Meaning | Action |
|
|
71
|
+
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| `symlink` | the path or an ancestor (`conflictPath`) is a symlink | never write through it; the user replaces the link |
|
|
73
|
+
| `ancestor-not-directory` | an ancestor of the path is a file | ask the user; never delete their files |
|
|
74
|
+
| `not-regular-file` | the destination exists and is not a regular file | ask the user |
|
|
75
|
+
| `outside-root` | the destination resolves outside the repository | ask the user |
|
|
76
|
+
| `content-differs` on `.harness/project.json` | an explicit `--writer` or `--profile` differs from the saved manifest; after an upgrade or a move, also a changed built-in profile, root or API version | keep the saved decision, or the user confirms the change explicitly |
|
|
77
|
+
| `content-differs` on `.harness/policy.json` | the saved policy's writer differs from the manifest or explicit `--writer` | keep the saved decision, or the user confirms the change explicitly |
|
|
78
|
+
| `INVALID_INPUT` with a path | not a Git root, invalid manifest or policy (also a truncated write), `--state` inside the repository | read the issue path; a broken file is removed by a human, not overwritten |
|
|
79
|
+
| `NOT_READY` `no-commits` | the repository has no commits | the user commits first |
|
|
80
|
+
| `NOT_READY` `stack-ambiguous` / `stack-unsupported` | both lockfiles, or none | pass `--profile`; when profile gates do not fit, write `.harness/profile.json` and pass `--profile ./.harness/profile.json` |
|
|
81
|
+
| `NOT_READY` toolchain problems | missing scripts, wrong tool versions | fix the project or hand it to the user; never weaken the policy |
|
|
82
|
+
| `CONTROLLER_BUSY` | the repository is already owned by another controller | stop: a second controller and state are not created |
|
|
81
83
|
|
|
82
84
|
### 4. Plan the graph
|
|
83
85
|
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: harness-setup
|
|
3
|
+
description: Install, configure or upgrade devcontour-harness for a new or existing npm/pnpm Git repository — ask the setup questions once (project, branch, install location, package source, writer and reviewer models, approval, task source such as files or Relay), install the exact version inside the project (`.harness-tools/`) or outside it, run `harness init`, record the decisions and hand over to the `harness` skill; upgrade an installed version with a state copy and a compatibility check.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Harness setup
|
|
7
|
+
|
|
8
|
+
This skill installs and upgrades the `devcontour-harness` package for one
|
|
9
|
+
repository and leaves it ready for work. Running work orders (plan, run,
|
|
10
|
+
explain, result) is the job of the `harness` skill shipped inside the package
|
|
11
|
+
(`<tooldir>/node_modules/devcontour-harness/skills/harness/SKILL.md`); read it
|
|
12
|
+
once the package is installed.
|
|
13
|
+
|
|
14
|
+
This skill only explains the route. Gates, review, write scope, budgets and
|
|
15
|
+
the reviewer vendor rule are enforced by the harness itself; nothing here
|
|
16
|
+
replaces or relaxes them.
|
|
17
|
+
|
|
18
|
+
Every `harness` command prints one JSON envelope on stdout (`ok` with `data`,
|
|
19
|
+
or `error`); exit codes: 0 success, 2 invalid input, 3 refusal or block,
|
|
20
|
+
4 infrastructure. Below `$H` is the installed CLI:
|
|
21
|
+
`H=<tooldir>/node_modules/.bin/harness`.
|
|
22
|
+
|
|
23
|
+
Modes: **install** (first setup), **upgrade** (change the installed version),
|
|
24
|
+
**check** (report what is installed; read only). Pick the mode from the
|
|
25
|
+
request; when the repository already has `.harness/` and a pinned or
|
|
26
|
+
installed `$H`, it is upgrade or check, not install.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
### 0. Ask once
|
|
31
|
+
|
|
32
|
+
Ask everything in one round (a multiple-choice question per item where the
|
|
33
|
+
host supports it); offer the default first. Do not ask what the repository
|
|
34
|
+
already answers: detect the lockfile, `packageManager`, an existing
|
|
35
|
+
`.harness/`, the current branch and which of `claude` / `codex` are installed
|
|
36
|
+
first. Whether a runtime is signed in is not detectable without a model call:
|
|
37
|
+
the user confirms it.
|
|
38
|
+
|
|
39
|
+
| # | Question | Options (default first) | Becomes |
|
|
40
|
+
| --- | ------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
41
|
+
| 1 | Repository | existing path / new project at a path | step 2 |
|
|
42
|
+
| 2 | Branch for the setup | new branch `harness-setup` / current branch | step 3; never the name `harness` (it clashes with `harness/accepted`) |
|
|
43
|
+
| 3 | Install location | inside the project `.harness-tools/` / outside, in a tool directory | `<tooldir>` of step 4 |
|
|
44
|
+
| 4 | Package source | npm `@alpha` resolved to an exact version / npm exact version / local `.tgz` with its sha256 | step 4 |
|
|
45
|
+
| 5 | Writer runtime | `claude` / `codex` | `init --writer`; the reviewer is the other vendor |
|
|
46
|
+
| 6 | Models and effort | runtime defaults / explicit `model` (and `effort` for codex) for writer and reviewer | step 6 |
|
|
47
|
+
| 7 | Reviewer of the writer's vendor | no (`different-vendor`) / yes for code and contract review, stated explicitly | step 6 |
|
|
48
|
+
| 8 | Plan approval | `agent` (the reviewer approves) / `operator` (a human runs `approve`) | step 6 |
|
|
49
|
+
| 9 | Task source | graph files in `.harness/work/` / Relay v1 (HTTP) / Relay-2 (CLI) | step 7 |
|
|
50
|
+
| 10 | Commit the setup | commit on the setup branch / leave uncommitted | step 8 |
|
|
51
|
+
|
|
52
|
+
For Relay also ask: the v1 endpoint, or the absolute Relay-2 binary, the
|
|
53
|
+
absolute `relay.config.json` / `relay.workspace.json` and the workspace
|
|
54
|
+
project; `projectId`; `actor` (default `harness-controller`); the task refs
|
|
55
|
+
and, per task, its write scope when it is narrower than the whole
|
|
56
|
+
repository; the columns a task may start from; `completion.mode`
|
|
57
|
+
(`review-only` for the first run, or `complete`).
|
|
58
|
+
|
|
59
|
+
The answers are the user's decisions. Do not change them later without
|
|
60
|
+
asking.
|
|
61
|
+
|
|
62
|
+
### 1. Preconditions
|
|
63
|
+
|
|
64
|
+
Node.js ≥ 24.3, `git`, `npm` (or `pnpm` for a pnpm project) and the runtime
|
|
65
|
+
CLIs the answers name (`claude --version`, `codex --version`). A missing or
|
|
66
|
+
signed-out runtime is the user's to fix; a live run is impossible without it.
|
|
67
|
+
|
|
68
|
+
The package manager version is checked exactly: the built-in profiles pin
|
|
69
|
+
one (`npm-ci` pins npm `11.4.2`), and `package.json#packageManager`
|
|
70
|
+
(`npm@<version>` / `pnpm@<version>`) overrides that pin. Another version is
|
|
71
|
+
`NOT_READY` (`TOOL_VERSION`) at `init`; adding `packageManager` to an existing
|
|
72
|
+
project is the user's decision.
|
|
73
|
+
|
|
74
|
+
### 2. Repository
|
|
75
|
+
|
|
76
|
+
**Existing.** It must be the top level of a Git repository with at least one
|
|
77
|
+
commit and exactly one lockfile: `package-lock.json` (profile `npm-ci`) or
|
|
78
|
+
`pnpm-lock.yaml` (profile `pnpm-frozen`). Both or none is decided by the user
|
|
79
|
+
(`--profile`, or a local `.harness/profile.json` passed as
|
|
80
|
+
`--profile ./.harness/profile.json`).
|
|
81
|
+
|
|
82
|
+
**New.** Create it only with the user's consent, at the path they gave:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
git init <repo> && cd <repo>
|
|
86
|
+
npm init -y && npm install # writes package-lock.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The built-in `npm-ci` profile needs two scripts: `check` and `test`, where
|
|
90
|
+
`test` writes JUnit to `.reports/junit.xml`. A minimal set for Node's test
|
|
91
|
+
runner, with the installed npm version pinned:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
"packageManager": "npm@<npm --version>",
|
|
95
|
+
"scripts": {
|
|
96
|
+
"check": "node --check index.js",
|
|
97
|
+
"test": "mkdir -p .reports && node --test --test-reporter=spec --test-reporter-destination=stdout --test-reporter=junit --test-reporter-destination=.reports/junit.xml"
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Add `.reports/` and `node_modules/` to `.gitignore`, a first source file and
|
|
102
|
+
a passing test, then commit. The first commit must pass its own gates: a
|
|
103
|
+
project failing on its base is a separate first task, not a reason to relax
|
|
104
|
+
a gate.
|
|
105
|
+
|
|
106
|
+
### 3. Branch
|
|
107
|
+
|
|
108
|
+
`git status` must be clean (ask the user about local changes; never stash or
|
|
109
|
+
discard them yourself). Then `git switch -c <branch>`.
|
|
110
|
+
|
|
111
|
+
`run` creates `refs/heads/harness/accepted` from the `HEAD` of the main
|
|
112
|
+
checkout when that ref does not exist yet. Keep the setup branch checked out,
|
|
113
|
+
with the setup committed (step 8), until the first `run`: otherwise
|
|
114
|
+
`harness/accepted` starts from a commit without it. When `harness/accepted`
|
|
115
|
+
already exists, report its SHA and leave it alone. Accepted work lands in
|
|
116
|
+
`harness/accepted`, not in the setup branch; merging it anywhere is the
|
|
117
|
+
user's decision.
|
|
118
|
+
|
|
119
|
+
### 4. Install the exact version
|
|
120
|
+
|
|
121
|
+
Resolve `@alpha` to the exact version first and install that:
|
|
122
|
+
`npm view devcontour-harness@alpha version`. For a tarball, compare
|
|
123
|
+
`shasum -a 256 <file.tgz>` with the sha256 the user gave and stop on a
|
|
124
|
+
mismatch.
|
|
125
|
+
|
|
126
|
+
**Inside the project** — `<tooldir>` = `<repo>/.harness-tools`:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
T=<repo>/.harness-tools
|
|
130
|
+
mkdir -p "$T"
|
|
131
|
+
npm install --prefix "$T" --save-exact --omit=dev --ignore-scripts devcontour-harness@<version>
|
|
132
|
+
printf 'node_modules/\n' > "$T/.gitignore"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The version is pinned by `.harness-tools/package.json` and its
|
|
136
|
+
`package-lock.json`, not by a directory name; both are committed with the
|
|
137
|
+
setup, `node_modules/` is not. The project's own `package.json` and lockfile
|
|
138
|
+
do not change. When the project declares npm `workspaces` or a
|
|
139
|
+
`pnpm-workspace.yaml` whose globs match `.harness-tools`, or lint/type/test
|
|
140
|
+
globs that would read it, tell the user before going on.
|
|
141
|
+
|
|
142
|
+
In a fresh clone, or after `node_modules/` was removed, restore the pinned
|
|
143
|
+
version without changing the pin:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
npm ci --prefix <repo>/.harness-tools --omit=dev --ignore-scripts
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
A tarball source records a local `file:` path in `.harness-tools/package.json`
|
|
150
|
+
that does not exist on other machines: install it the same way, but keep the
|
|
151
|
+
whole directory out of Git with `.git/info/exclude` instead of committing it:
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
npm install --prefix "$T" --omit=dev --ignore-scripts <file.tgz>
|
|
155
|
+
grep -qxF '.harness-tools/' <repo>/.git/info/exclude || echo '.harness-tools/' >> <repo>/.git/info/exclude
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Outside the project** — any directory the user names, the same commands
|
|
159
|
+
with `--prefix <tooldir>`; nothing is written into the repository.
|
|
160
|
+
|
|
161
|
+
Then:
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
H=<tooldir>/node_modules/.bin/harness
|
|
165
|
+
$H --version
|
|
166
|
+
$H doctor
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Never install the package into the project's own dependencies as part of this
|
|
170
|
+
route, and never put the execution state inside the repository.
|
|
171
|
+
|
|
172
|
+
### 5. `harness init`
|
|
173
|
+
|
|
174
|
+
```sh
|
|
175
|
+
$H init --repository <repo> --writer <claude|codex> --plan
|
|
176
|
+
$H init --repository <repo> --writer <claude|codex>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The first call writes nothing: read `data.files`, `data.conflicts`,
|
|
180
|
+
`data.toolchain.problems`, `data.facts` and `data.manifest.paths.state`, and
|
|
181
|
+
resolve every conflict or problem with the table of the `harness` skill
|
|
182
|
+
(step 3) before the second call. `init` is create-only: `.harness/.gitignore`,
|
|
183
|
+
`.harness/README.md`, `.harness/project.json` (local, not under Git) and
|
|
184
|
+
`.harness/policy.json`. The state lives outside the repository
|
|
185
|
+
(`HARNESS_STATE_HOME`, `XDG_STATE_HOME` or `~/.local/state/devcontour-harness`).
|
|
186
|
+
|
|
187
|
+
### 6. Runtimes and approval
|
|
188
|
+
|
|
189
|
+
Edit `.harness/policy.json` only as the answers require:
|
|
190
|
+
|
|
191
|
+
- models: `model` on `roles.<role>.writer` and on `review.code.reviewer`,
|
|
192
|
+
`review.plan.reviewer`, `review.contract.reviewer`;
|
|
193
|
+
- effort: `effort` (`low`, `medium`, `high`, `xhigh`) only on bindings whose
|
|
194
|
+
`runtime` is `codex`; on any other runtime it is refused;
|
|
195
|
+
- a reviewer of the writer's vendor (an explicit yes only): on
|
|
196
|
+
`review.code` and/or `review.contract`, set `reviewer.runtime` to the
|
|
197
|
+
writer's runtime and add `"vendor": "same-vendor-allowed"`. Leave
|
|
198
|
+
`review.plan` with the other vendor: `init` reads the saved writer from the
|
|
199
|
+
plan reviewer, so changing it makes every later `init --plan` report
|
|
200
|
+
`content-differs` on `policy.json`. When the user wants it anyway, say so
|
|
201
|
+
and let them decide;
|
|
202
|
+
- operator approval: top-level `"approvalMode": "operator"`;
|
|
203
|
+
- with the version pin committed inside the project: add `.harness-tools/` to
|
|
204
|
+
`repositories[0].protectedPaths`, so no work order can change the tool it
|
|
205
|
+
is checked by.
|
|
206
|
+
|
|
207
|
+
Never remove or weaken anything `init` wrote. Keep the writer runtime as
|
|
208
|
+
`init` wrote it: a different writer vendor is a new `init --writer` decision.
|
|
209
|
+
|
|
210
|
+
Check after editing:
|
|
211
|
+
|
|
212
|
+
```sh
|
|
213
|
+
$H doctor --policy <repo>/.harness/policy.json
|
|
214
|
+
$H init --repository <repo> --plan
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`doctor` checks the policy schema, runtimes and toolchain only; `init --plan`
|
|
218
|
+
must show `data.conflicts` = 0. The cross-checks of the policy (effort on a
|
|
219
|
+
non-codex runtime, the reviewer vendor rule, unknown gates) run in
|
|
220
|
+
`$H validate --graph <graph> --policy <repo>/.harness/policy.json`: run it
|
|
221
|
+
for the first graph before any review or run, and fix the policy, not the
|
|
222
|
+
check, when it fails.
|
|
223
|
+
|
|
224
|
+
### 7. Task source
|
|
225
|
+
|
|
226
|
+
**Graph files.** Nothing more to configure; the `harness` skill plans the
|
|
227
|
+
first graph.
|
|
228
|
+
|
|
229
|
+
**Relay.** Write `.harness/connector.json` from `docs/connectors.md` of the
|
|
230
|
+
installed package ("Конфигурация"):
|
|
231
|
+
|
|
232
|
+
- `"version": 1` and `"provider": "relay-v1-http"` or `"relay-v2-cli"`,
|
|
233
|
+
always explicit — never guessed from a binary named `relay`;
|
|
234
|
+
- `projectId` and `actor` at the top level; `repository.id` is the policy
|
|
235
|
+
repository id (`app` after `init`);
|
|
236
|
+
- adapter settings nested under `relay`: v1 `relay.endpoint`; Relay-2
|
|
237
|
+
absolute `relay.binary` and `relay.config`, `relay.project` for a workspace,
|
|
238
|
+
`relay.env` that may set `RELAY_HOME` (and on macOS `DYLD_LIBRARY_PATH` to
|
|
239
|
+
SQLite ≥ 3.44) but never `RELAY_CONFIG` or `RELAY_ACTOR`;
|
|
240
|
+
- `tasks[]`: `ref`; `role` and `gates` only from `data.facts` of `init`;
|
|
241
|
+
`writeScope` (required) = the role's `writePaths` from the facts, or, when
|
|
242
|
+
the role has none, `["."]` (the whole repository) or the narrower paths the
|
|
243
|
+
user named; `criteria` mapped to a gate and a JUnit `testId`;
|
|
244
|
+
- `completion: { "mode": "review-only" }` (or `"complete"`) and
|
|
245
|
+
`eligibility.columns` from the answers;
|
|
246
|
+
- no `stateDir` (pass `--state <manifest.paths.state>`), no secret values.
|
|
247
|
+
|
|
248
|
+
Checks that do not write to Relay:
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
$H source-check --source <repo>/.harness/connector.json --policy <repo>/.harness/policy.json --state <state>
|
|
252
|
+
$H source-snapshot --source <repo>/.harness/connector.json --policy <repo>/.harness/policy.json --state <state> --out <dir outside the repo>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`source-check` is read only. `source-snapshot` reads Relay but records the
|
|
256
|
+
snapshot in the connector state under `--state` and writes `graph.json`,
|
|
257
|
+
`context.json` and `manifest.json` to `--out`. `run --source`,
|
|
258
|
+
`source-deliver` and `source-reconcile` write to Relay: run them only after
|
|
259
|
+
the user says so.
|
|
260
|
+
|
|
261
|
+
### 8. Commit
|
|
262
|
+
|
|
263
|
+
With the user's yes: commit on the setup branch `.harness/.gitignore`,
|
|
264
|
+
`.harness/README.md`, `.harness/policy.json`, `.harness/connector.json` (when
|
|
265
|
+
present) and, for an npm source inside the project,
|
|
266
|
+
`.harness-tools/.gitignore`, `.harness-tools/package.json`,
|
|
267
|
+
`.harness-tools/package-lock.json`. Never `project.json`, `node_modules/` or
|
|
268
|
+
the state. Do not push or merge.
|
|
269
|
+
|
|
270
|
+
### 9. Report and hand over
|
|
271
|
+
|
|
272
|
+
Report: installed version (and the tarball sha256), `doctor`, the decisions
|
|
273
|
+
of the manifest (profile, writer, reviewer, state path), the policy edits,
|
|
274
|
+
the connector check, the commit SHA. Then continue with the `harness` skill:
|
|
275
|
+
brief → `plan-request` → draft → `plan-check` → `validate` → `run`. A live
|
|
276
|
+
`run` or `review-plan` calls paid models: start it when the user asks.
|
|
277
|
+
|
|
278
|
+
## Upgrade
|
|
279
|
+
|
|
280
|
+
An upgrade changes only the package. Policy, profiles, graphs, accepted
|
|
281
|
+
results and `.harness/project.json` stay as they are unless the user decides
|
|
282
|
+
otherwise in step 7.
|
|
283
|
+
|
|
284
|
+
1. **Current and target.** `$H --version`; target from the user, or
|
|
285
|
+
`npm view devcontour-harness dist-tags`. Install the target into a scratch
|
|
286
|
+
directory outside the repository (`N=<scratch>/node_modules/.bin/harness`)
|
|
287
|
+
and read its `docs/release-notes/<version>.md` and the format matrix of
|
|
288
|
+
`docs/upgrade.md` for every version in between.
|
|
289
|
+
2. **Stop the writers.** `$H status --state <state>`; `$H pause --state <state>`;
|
|
290
|
+
wait for active attempts to finish or ask the user to stop them; stop every
|
|
291
|
+
`run` process on this state. A paused queue alone is not enough.
|
|
292
|
+
3. **Record.** `git rev-parse refs/heads/harness/accepted` and
|
|
293
|
+
`$H result --state <state> --work <id>` for the accepted orders.
|
|
294
|
+
4. **Copy the state** while nothing writes: `cp -Rp <state> <state>.bak-<old version>`.
|
|
295
|
+
5. **Check on a second copy** with the target version: `$N doctor --state <copy>`
|
|
296
|
+
and `$N status --state <copy>`. Hash the copy's files before and after;
|
|
297
|
+
they must not change. Stop and report when `doctor` shows
|
|
298
|
+
`data.state.compatible: false` or `status` fails with
|
|
299
|
+
`STATE_VERSION_UNSUPPORTED`.
|
|
300
|
+
6. **Install** into the same `<tooldir>`:
|
|
301
|
+
`npm install --prefix <tooldir> --save-exact --omit=dev --ignore-scripts devcontour-harness@<new>`
|
|
302
|
+
(or the new `.tgz` after its sha256 check).
|
|
303
|
+
7. **Verify.**
|
|
304
|
+
- `$H --version`; `$H doctor --state <state> --policy <repo>/.harness/policy.json`.
|
|
305
|
+
- `$H init --repository <repo> --plan` must show `data.conflicts` = 0.
|
|
306
|
+
`content-differs` on `.harness/project.json` means a saved decision no
|
|
307
|
+
longer matches: the built-in profile digest changed (compare
|
|
308
|
+
`$H profile --profile <id>` with the pin in `project.json`), the
|
|
309
|
+
repository moved (`root`, `projectId`), or the API version changed.
|
|
310
|
+
Show the difference to the user. With their yes, move the manifest out
|
|
311
|
+
of the repository, next to the state copy of step 4
|
|
312
|
+
(`mv <repo>/.harness/project.json <state>.bak-<old version>/project.json`),
|
|
313
|
+
and run
|
|
314
|
+
`$H init --repository <repo> --profile <saved profile.ref> --writer <saved runtimes.writer> --state <saved paths.state>`
|
|
315
|
+
with the values of the moved manifest, so the profile choice and the state
|
|
316
|
+
path are kept; never edit the manifest by hand.
|
|
317
|
+
- The policy is not regenerated. List gates or defaults of the new profile
|
|
318
|
+
that the policy lacks and add them only with the user's yes; never weaken
|
|
319
|
+
the existing ones. A changed policy changes the facts of planning, so
|
|
320
|
+
graphs may need plan review or approval again (`explain` names it).
|
|
321
|
+
- `$H validate --graph <graph> --policy <repo>/.harness/policy.json` for
|
|
322
|
+
every `.harness/work/*.json` graph.
|
|
323
|
+
8. **Resume.** `$H resume --state <state>`, then `run` as before. Attempts that
|
|
324
|
+
were active at the stop are not continued with old tokens; recovery either
|
|
325
|
+
accepts a saved integration SHA or ends the attempt.
|
|
326
|
+
9. **Commit** the changed `.harness-tools/package.json` and
|
|
327
|
+
`package-lock.json` on a branch, with the user's yes.
|
|
328
|
+
|
|
329
|
+
Rollback: stop the writers again; reinstall the old exact version; when the
|
|
330
|
+
new version already wrote state the old one cannot read, restore the copy of
|
|
331
|
+
step 4 and reconcile `harness/accepted` with the recorded SHAs
|
|
332
|
+
(`docs/upgrade.md`, "Откат"). Never `git reset --hard` the user's repository.
|
|
333
|
+
|
|
334
|
+
## Check
|
|
335
|
+
|
|
336
|
+
Read only: `$H --version`, `$H doctor`, `$H init --repository <repo> --plan`,
|
|
337
|
+
`$H status --state <paths.state>`, and the pin in
|
|
338
|
+
`.harness-tools/package.json` when present. Report a mismatch between the pin
|
|
339
|
+
and `$H --version`, or a missing `node_modules/` (restore with `npm ci`, step
|
|
340
|
+
4); do not fix it unasked.
|
|
341
|
+
|
|
342
|
+
## Don'ts
|
|
343
|
+
|
|
344
|
+
- Do not choose for the user: location, source, runtimes, models, the vendor
|
|
345
|
+
rule, approval mode, task source and commits are their answers.
|
|
346
|
+
- Do not install into the project's dependencies, edit its `package.json` or
|
|
347
|
+
lockfile (except when bootstrapping a new project with consent), or put the
|
|
348
|
+
state inside the repository.
|
|
349
|
+
- Do not weaken gates, budgets, isolation or the reviewer rule, and do not set
|
|
350
|
+
`same-vendor-allowed` without an explicit yes.
|
|
351
|
+
- Do not overwrite `.harness/project.json` or `.harness/policy.json` on a
|
|
352
|
+
`content-differs`; that is a decision to show to the user.
|
|
353
|
+
- Do not write to Relay, call live models, push, tag or publish without being
|
|
354
|
+
asked.
|
|
355
|
+
- Do not upgrade while a controller writes the state, and do not skip the
|
|
356
|
+
state copy.
|