@agentshouse/kit 0.1.0-alpha.3 → 0.1.0-alpha.31
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 +722 -263
- package/bin/connect-linux.sh +200 -25
- package/bin/kit.js +179 -157
- package/bootstrap.json +17 -0
- package/package.json +7 -2
- package/src/adapter-mcp.js +76 -12
- package/src/agents.js +63 -8
- package/src/binding.js +52 -0
- package/src/blocks.js +2 -26
- package/src/bridge.js +28 -14
- package/src/bytes.js +19 -8
- package/src/configuration.js +13 -209
- package/src/connector-login.js +3 -84
- package/src/contract.js +36 -11
- package/src/delivery.js +4 -7
- package/src/directory.js +6 -26
- package/src/draft.js +4 -82
- package/src/git-main.js +138 -0
- package/src/git.js +62 -0
- package/src/google/calendar.js +39 -45
- package/src/google/drive.js +61 -186
- package/src/google/entries.js +346 -0
- package/src/google/gateway.js +3 -6
- package/src/google/gmail.js +33 -23
- package/src/google/oauth.js +106 -66
- package/src/google/source.js +21 -23
- package/src/host.js +6 -2
- package/src/house-main.js +65 -8
- package/src/house.js +446 -127
- package/src/how-we-work.md +25 -0
- package/src/inbound.js +2 -18
- package/src/kit-work-stream.js +118 -0
- package/src/launcher.js +46 -10
- package/src/local-files.js +3 -11
- package/src/login.js +23 -11
- package/src/mcp.js +18 -0
- package/src/mount.js +13 -21
- package/src/original.js +4 -4
- package/src/pacing.js +41 -0
- package/src/plan.js +37 -45
- package/src/repository.js +3 -61
- package/src/session-bin/git +2 -0
- package/src/setup.js +14 -15
- package/src/skill-set/ask-matt/PHASE-BOUNDARIES.md +55 -0
- package/src/skill-set/ask-matt/SKILL.md +91 -0
- package/src/skill-set/ask-matt/agents/openai.yaml +4 -0
- package/src/skill-set/code-review/LICENSE +21 -0
- package/src/skill-set/code-review/SKILL.md +89 -0
- package/src/skill-set/code-review/agents/openai.yaml +3 -0
- package/src/skill-set/codebase-design/DEEPENING.md +37 -0
- package/src/skill-set/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/src/skill-set/codebase-design/LICENSE +21 -0
- package/src/skill-set/codebase-design/SKILL.md +116 -0
- package/src/skill-set/codebase-design/agents/openai.yaml +3 -0
- package/src/skill-set/diagnosing-bugs/LICENSE +21 -0
- package/src/skill-set/diagnosing-bugs/SKILL.md +140 -0
- package/src/skill-set/diagnosing-bugs/agents/openai.yaml +3 -0
- package/src/skill-set/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
- package/src/skill-set/domain-modeling/ADR-FORMAT.md +47 -0
- package/src/skill-set/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/src/skill-set/domain-modeling/LICENSE +21 -0
- package/src/skill-set/domain-modeling/SKILL.md +76 -0
- package/src/skill-set/domain-modeling/agents/openai.yaml +3 -0
- package/src/skill-set/grill-me/LICENSE +21 -0
- package/src/skill-set/grill-me/SKILL.md +8 -0
- package/src/skill-set/grill-me/agents/openai.yaml +4 -0
- package/src/skill-set/grill-with-docs/LICENSE +21 -0
- package/src/skill-set/grill-with-docs/SKILL.md +8 -0
- package/src/skill-set/grill-with-docs/agents/openai.yaml +4 -0
- package/src/skill-set/grilling/LICENSE +21 -0
- package/src/{starter-set → skill-set}/grilling/SKILL.md +1 -1
- package/src/skill-set/handoff/LICENSE +21 -0
- package/src/skill-set/handoff/SKILL.md +17 -0
- package/src/skill-set/handoff/agents/openai.yaml +4 -0
- package/src/skill-set/implement/LICENSE +21 -0
- package/src/skill-set/implement/SKILL.md +16 -0
- package/src/skill-set/implement/agents/openai.yaml +4 -0
- package/src/skill-set/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/src/skill-set/improve-codebase-architecture/LICENSE +21 -0
- package/src/skill-set/improve-codebase-architecture/SKILL.md +72 -0
- package/src/skill-set/improve-codebase-architecture/agents/openai.yaml +4 -0
- package/src/skill-set/prototype/LICENSE +21 -0
- package/src/skill-set/prototype/LOGIC.md +67 -0
- package/src/skill-set/prototype/SKILL.md +28 -0
- package/src/skill-set/prototype/UI.md +112 -0
- package/src/skill-set/prototype/agents/openai.yaml +3 -0
- package/src/skill-set/research/LICENSE +21 -0
- package/src/skill-set/research/SKILL.md +14 -0
- package/src/skill-set/research/agents/openai.yaml +3 -0
- package/src/skill-set/resolving-merge-conflicts/LICENSE +21 -0
- package/src/skill-set/resolving-merge-conflicts/SKILL.md +16 -0
- package/src/skill-set/resolving-merge-conflicts/agents/openai.yaml +3 -0
- package/src/skill-set/tdd/LICENSE +21 -0
- package/src/skill-set/tdd/SKILL.md +40 -0
- package/src/skill-set/tdd/agents/openai.yaml +3 -0
- package/src/skill-set/tdd/mocking.md +59 -0
- package/src/skill-set/tdd/tests.md +77 -0
- package/src/skill-set/teach/GLOSSARY-FORMAT.md +35 -0
- package/src/skill-set/teach/LEARNING-RECORD-FORMAT.md +46 -0
- package/src/skill-set/teach/LICENSE +21 -0
- package/src/skill-set/teach/MISSION-FORMAT.md +31 -0
- package/src/skill-set/teach/RESOURCES-FORMAT.md +32 -0
- package/src/skill-set/teach/SKILL.md +141 -0
- package/src/skill-set/teach/agents/openai.yaml +4 -0
- package/src/skill-set/to-questionnaire/LICENSE +21 -0
- package/src/skill-set/to-questionnaire/SKILL.md +55 -0
- package/src/skill-set/to-questionnaire/agents/openai.yaml +4 -0
- package/src/skill-set/to-spec/LICENSE +21 -0
- package/src/skill-set/to-spec/SKILL.md +76 -0
- package/src/skill-set/to-spec/agents/openai.yaml +4 -0
- package/src/skill-set/to-tickets/LICENSE +21 -0
- package/src/skill-set/to-tickets/SKILL.md +106 -0
- package/src/skill-set/to-tickets/agents/openai.yaml +4 -0
- package/src/skill-set/wait-what/LICENSE +21 -0
- package/src/skill-set/wait-what/SKILL.md +8 -0
- package/src/skill-set/wait-what/agents/openai.yaml +4 -0
- package/src/skill-set/wayfinder/LICENSE +21 -0
- package/src/skill-set/wayfinder/SKILL.md +129 -0
- package/src/skill-set/wayfinder/agents/openai.yaml +4 -0
- package/src/skill-set/writing-for-agents/LICENSE +21 -0
- package/src/skill-set/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/src/skill-set/writing-for-agents/SKILL.md +83 -0
- package/src/skill-set/writing-for-agents/agents/openai.yaml +3 -0
- package/src/skill-set.js +85 -0
- package/src/source.js +93 -54
- package/src/state.js +19 -1
- package/src/sync-library.js +7 -11
- package/src/sync-state.js +16 -3
- package/src/sync.js +129 -41
- package/src/tasks.js +75 -0
- package/src/telegram-view.js +214 -0
- package/src/telegram.js +161 -66
- package/src/turn-frames.js +69 -0
- package/src/worker.js +685 -184
- package/src/working-copy.js +1221 -0
- package/src/workspace.js +40 -32
- package/src/google/declared.js +0 -146
- package/src/google/id.js +0 -1
- package/src/instance/google.js +0 -1
- package/src/starter-set.js +0 -17
- /package/src/{starter-set/grilling → skill-set/ask-matt}/LICENSE +0 -0
- /package/src/{starter-set → skill-set}/grilling/agents/openai.yaml +0 -0
package/README.md
CHANGED
|
@@ -4,61 +4,184 @@ House Kit is a public package repository. Product development is planned and
|
|
|
4
4
|
coordinated in the [Agents House repository](https://github.com/trof3039/agents.house);
|
|
5
5
|
this repository contains only the package source and its operator documentation.
|
|
6
6
|
|
|
7
|
+
The Skill set Kit installs is Matt Pocock's
|
|
8
|
+
[`mattpocock/skills`](https://github.com/mattpocock/skills); thank you, Matt.
|
|
9
|
+
|
|
7
10
|
## Connect a Linux computer
|
|
8
11
|
|
|
9
|
-
On Linux `amd64` or `arm64
|
|
10
|
-
versioned bootstrap once:
|
|
12
|
+
On Linux `amd64` or `arm64`, run the published, versioned bootstrap once:
|
|
11
13
|
|
|
12
14
|
```sh
|
|
13
|
-
bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.
|
|
15
|
+
bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.31/connect-linux.sh)
|
|
14
16
|
```
|
|
15
17
|
|
|
18
|
+
The bootstrap first establishes Docker Engine from what it observes on the
|
|
19
|
+
computer. A Docker Engine that already answers is used as it is, on any
|
|
20
|
+
distribution. On Ubuntu 22.04, 24.04 or 26.04 LTS it follows Docker's
|
|
21
|
+
[apt repository recipe](https://docs.docker.com/engine/install/ubuntu/) for
|
|
22
|
+
whatever is missing: it installs `docker-ce`, `docker-ce-cli`,
|
|
23
|
+
`containerd.io`, `docker-buildx-plugin` and `docker-compose-plugin` from
|
|
24
|
+
`download.docker.com`, starts the `docker` service when it is stopped and adds
|
|
25
|
+
the account to the `docker` group. Every such step runs through `sudo`, which
|
|
26
|
+
asks for the password as it ordinarily does. A new group membership applies
|
|
27
|
+
from the account's next sign-in, so the invocation that grants it reaches
|
|
28
|
+
Docker Engine through `sudo` for the rest of its own run; a later invocation
|
|
29
|
+
from a session older than the membership is refused until the account signs
|
|
30
|
+
out and back in. The bootstrap refuses an Ubuntu computer whose installed
|
|
31
|
+
`docker.io`, `docker-compose`, `docker-compose-v2`, `docker-doc`,
|
|
32
|
+
`docker-buildx`, `podman-docker`, `containerd` or `runc` package conflicts with
|
|
33
|
+
that recipe rather than removing it. Any other distribution needs a working
|
|
34
|
+
Docker Engine supplied by its owner, and without one the bootstrap stops with
|
|
35
|
+
that missing prerequisite. A step that fails names its cause and changes
|
|
36
|
+
nothing further; running the same bootstrap again continues from the state it
|
|
37
|
+
left, including after a restart.
|
|
38
|
+
|
|
16
39
|
The release asset pins one immutable multi-architecture image digest. It creates
|
|
17
40
|
owner-protected `~/.house-kit` and `~/AgentsHouse`, mounts those as the complete
|
|
18
41
|
Kit home and `/agents/house`, enrolls through House Login in the host browser,
|
|
19
42
|
and starts the container with Docker's `unless-stopped` lifecycle. Pass
|
|
20
43
|
`--workspace /absolute/path` for one other workspace root or `--manual` for
|
|
21
44
|
the existing URL and one-time-code login route. `--house <origin>` selects
|
|
22
|
-
another House and is retained in Kit home. A
|
|
23
|
-
|
|
24
|
-
|
|
45
|
+
another House and is retained in Kit home. A local loopback House,
|
|
46
|
+
`http://127.0.0.1:<port>` or `http://localhost:<port>`, runs the resident
|
|
47
|
+
container on the host network, as the one-shot login, credential check and
|
|
48
|
+
apply containers always run, so the resident reaches the House the host serves;
|
|
49
|
+
an HTTPS House leaves it on Docker's own network. A repeated invocation reuses the
|
|
50
|
+
same container, credential and Environment. Every invocation that is not a
|
|
51
|
+
forwarded command also sets `skills` in Kit's configuration: `--no-skills`
|
|
52
|
+
declines [the Skill set](#the-skill-set) and an invocation without it accepts
|
|
53
|
+
the set again.
|
|
54
|
+
|
|
55
|
+
Running a newer release's bootstrap the same way is the only update. When the
|
|
56
|
+
installed container runs another image, the bootstrap pulls this release's
|
|
57
|
+
image and asks the running resident Kit to drain with `kit resident drain`. The
|
|
58
|
+
resident stops acquiring Runs, resumptions, setup, agent CLI work, Google
|
|
59
|
+
sign-ins and scheduled Google captures, while the Sessions it supervises keep
|
|
60
|
+
their renewal, owner stops, answers and reports and a capture already running
|
|
61
|
+
finishes.
|
|
62
|
+
While any Agent Session is still running or unreported, including one whose Run
|
|
63
|
+
was being acquired when the drain began, the bootstrap names it and leaves the
|
|
64
|
+
container as it is; rerun it once they end. Once nothing remains,
|
|
65
|
+
the resident stops renewing, releases its exact lease and stays quiescent, and
|
|
66
|
+
the bootstrap replaces the container with one on this release's image over the
|
|
67
|
+
same Kit home and workspace. The credential, Environment, Kit-home state and
|
|
68
|
+
everything under the workspace are kept; anything installed elsewhere in the old
|
|
69
|
+
container is not. A stopped container is replaced without a drain.
|
|
70
|
+
|
|
71
|
+
If House refuses the installed Kit with `kit_upgrade_required`, including in
|
|
72
|
+
its answer to a command the resident serves, the resident calls House no more,
|
|
73
|
+
neither to release nor to report. It keeps supervising
|
|
74
|
+
every running Session locally and never stops one to make progress. A Session
|
|
75
|
+
that ends keeps its exact binding, stop observation and outcome in Kit home,
|
|
76
|
+
and the drain answers ready once no supervised process runs. The updated Kit
|
|
77
|
+
waits for the old lease to expire, acquires the next one and reports each held
|
|
78
|
+
Session before it acquires any work, restoring no process and inventing no
|
|
79
|
+
outcome.
|
|
80
|
+
|
|
81
|
+
The versioned `bootstrap.json` is the machine-readable command source for this
|
|
82
|
+
release. It is exported from the npm package as `@agentshouse/kit/bootstrap`
|
|
83
|
+
(JSON import) and published byte-for-byte beside `connect-linux.sh` in the
|
|
84
|
+
GitHub release. Its schema version is `1`, its `version` is the Kit package
|
|
85
|
+
version, and `hosts` contains only bootstrap scripts published in that release.
|
|
86
|
+
The package exports only the `./bootstrap` subpath; `./package.json` and source
|
|
87
|
+
subpaths are not exported. For this release, only `hosts.linux` exists. In this
|
|
88
|
+
schema example, `<version>` stands for the package's version:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"schemaVersion": 1,
|
|
93
|
+
"version": "<version>",
|
|
94
|
+
"hosts": {
|
|
95
|
+
"linux": {
|
|
96
|
+
"command": "bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v<version>/connect-linux.sh)",
|
|
97
|
+
"asset": {
|
|
98
|
+
"name": "connect-linux.sh",
|
|
99
|
+
"url": "https://github.com/agentshouse/kit/releases/download/v<version>/connect-linux.sh"
|
|
100
|
+
},
|
|
101
|
+
"workspace": { "argument": "--workspace", "quoting": "posix" }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`command` is complete for the default workspace. To show a selected absolute
|
|
108
|
+
workspace, append the declared `workspace.argument` and the path as one POSIX
|
|
109
|
+
shell-quoted argument. For example, `/home/user/My Agents' House` becomes
|
|
110
|
+
`--workspace '/home/user/My Agents'\'' House'`. Quote the entire path before
|
|
111
|
+
adding it to a copyable shell command; never interpolate it as shell syntax.
|
|
112
|
+
The bootstrap validates an absolute workspace root and encodes it as one Docker
|
|
113
|
+
`--mount` CSV source field, including commas and double quotes in the name.
|
|
114
|
+
The package manifest contains no image digest: the release workflow
|
|
115
|
+
fills the immutable image digest into the published script after the package
|
|
116
|
+
has been built.
|
|
25
117
|
|
|
26
118
|
The bootstrap does not install native Kit on an ordinary computer. The native
|
|
27
119
|
package remains for managed Nodes and an explicitly selected eligible Kit host.
|
|
28
120
|
|
|
121
|
+
The same bootstrap is the host's entry point for the existing `kit` commands:
|
|
122
|
+
append `kit` and the command to the connect command above, as in
|
|
123
|
+
`bash <(curl -fsSL …/connect-linux.sh) kit apply` or
|
|
124
|
+
`bash <(curl -fsSL …/connect-linux.sh) kit telegram connect`. It forwards the
|
|
125
|
+
command and its arguments unchanged into the installed container through the
|
|
126
|
+
host's Docker client and ends with the command's own output and exit status.
|
|
127
|
+
Standard input stays attached and a terminal stays a terminal, so a hidden
|
|
128
|
+
prompt such as the Telegram bot token is read inside the container and never
|
|
129
|
+
becomes an argument or printed output. With the output redirected, the
|
|
130
|
+
command's output and errors stay separate and the terminal stops echoing typed
|
|
131
|
+
input until the command ends. A running container runs the command beside its
|
|
132
|
+
resident Kit; a stopped one runs it in a one-off container over the same Kit
|
|
133
|
+
home and workspace and stays stopped. `kit login` takes the bootstrap's own
|
|
134
|
+
login route, a one-off container on the host network so the host browser can
|
|
135
|
+
return to its loopback listener, or `--manual` for the URL and one-time code.
|
|
136
|
+
Forwarding installs no host-native Kit and gives the container no Docker socket
|
|
137
|
+
or further mount; it refuses when no Kit is installed or the installed one
|
|
138
|
+
differs from this bootstrap's.
|
|
139
|
+
|
|
140
|
+
The owner's working copy push is forwarded the same way: run
|
|
141
|
+
`bash <(curl -fsSL …/connect-linux.sh) house git push [commit] --owner` from a
|
|
142
|
+
directory beneath the workspace root, such as a Room copy under
|
|
143
|
+
`working-copies/rooms/`. The bootstrap runs the container's `house` in the
|
|
144
|
+
matching directory beneath `/agents/house`, through the resident's lease when
|
|
145
|
+
the container runs, and refuses a directory outside the workspace before
|
|
146
|
+
anything reaches House.
|
|
147
|
+
|
|
29
148
|
## Building the package
|
|
30
149
|
|
|
31
|
-
The repository checkout is the development source. Build the package
|
|
32
|
-
|
|
33
|
-
Google OAuth client, its id and its client secret:
|
|
150
|
+
The repository checkout is the development source. Build the package that can
|
|
151
|
+
be published:
|
|
34
152
|
|
|
35
153
|
```sh
|
|
36
|
-
HOUSE_KIT_GOOGLE_OAUTH_CLIENT_ID=kit-client.apps.googleusercontent.com \
|
|
37
|
-
HOUSE_KIT_GOOGLE_OAUTH_CLIENT_SECRET=GOCSPX-kit-installed-app \
|
|
38
154
|
npm run build
|
|
39
155
|
```
|
|
40
156
|
|
|
41
|
-
The command writes the publishable package to `dist/package`.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
from its runtime environment and never requests them from House.
|
|
157
|
+
The command writes the publishable package to `dist/package`. It reads no
|
|
158
|
+
environment and ships no provider OAuth client: each Google account signs in
|
|
159
|
+
with the User's own client, as [the Google preset](#the-google-preset)
|
|
160
|
+
describes.
|
|
46
161
|
|
|
47
162
|
Runtime dependencies stay minimal and exactly pinned in `package.json` and
|
|
48
163
|
`package-lock.json`: House's own `@agentshouse/mdmodel`, `yaml`, which reads
|
|
49
164
|
House's text answers, and the Agent Client Protocol SDK
|
|
50
165
|
`@agentclientprotocol/sdk` with its peer `zod`, which is this Kit's one protocol
|
|
51
|
-
client for the compiled adapter contracts
|
|
166
|
+
client for the compiled adapter contracts, and `ws` for the authenticated Kit
|
|
167
|
+
control stream. The SDK's approval
|
|
52
168
|
receipt is [`docs/agents/acp-sdk-dependency-approval.json`](docs/agents/acp-sdk-dependency-approval.json),
|
|
53
169
|
which the User wrote once this adoption's proof had passed. The adapter
|
|
54
170
|
packages themselves are Environment prerequisites, not Kit dependencies, and
|
|
55
171
|
carry no record.
|
|
56
172
|
|
|
57
|
-
The bootstrap invokes bare `kit login
|
|
173
|
+
The bootstrap invokes bare `kit login`, which connects to `https://agents.house`;
|
|
174
|
+
`--house <origin>` names another House. Login records the House in Kit home
|
|
175
|
+
beside the credential. Every House-bound command talks to that recorded House,
|
|
176
|
+
and every command but login refuses `--house` as an unknown argument. The first login names its new
|
|
58
177
|
Environment after the host computer and stores its Environment id in Kit home;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
178
|
+
the panel renames it. An explicit later login reconnects that retained id, and
|
|
179
|
+
`--environment <uuid>` reconnects the Environment it names instead, whether or
|
|
180
|
+
not Kit home records one, and Kit home then records that id. Reconnecting issues the next credential for the same Environment
|
|
181
|
+
and ends the previous one, including one `envs/revoke` ended; House refuses an
|
|
182
|
+
Environment it no longer holds with its cause and never creates a replacement.
|
|
183
|
+
A malformed id or an answer naming a different Environment is refused before
|
|
184
|
+
installation.
|
|
62
185
|
|
|
63
186
|
Use `--manual` when the browser cannot reach the Kit's loopback listener. The
|
|
64
187
|
command stores the issued Kit User credential in `$HOUSE_KIT_HOME/credential`
|
|
@@ -112,7 +235,8 @@ never printed by Kit.
|
|
|
112
235
|
"settings": "/home/ada/.claude/settings.json"
|
|
113
236
|
}
|
|
114
237
|
],
|
|
115
|
-
"host": null
|
|
238
|
+
"host": null,
|
|
239
|
+
"skills": true
|
|
116
240
|
}
|
|
117
241
|
```
|
|
118
242
|
|
|
@@ -132,13 +256,19 @@ mode: `"intermittent"` for a laptop or other normally offline placement,
|
|
|
132
256
|
any other value refuses as `kit_configuration_invalid`; `kit apply` sends the
|
|
133
257
|
declared mode with the rest of the desired state. An
|
|
134
258
|
instance declares one or more services, and under the `custom` preset each
|
|
135
|
-
service owns the command that produces it.
|
|
259
|
+
service owns the command that produces it. The Kit reads only `custom` instances
|
|
260
|
+
and passes over any other entry of `instances`.
|
|
136
261
|
|
|
137
262
|
`host` declares the Linux host this installation measures for
|
|
138
263
|
[host capacity reporting](#host-capacity). `null` declares that this Kit reports
|
|
139
264
|
no capacity; the section is required like the others, so a host is measured only
|
|
140
265
|
where the Environment owner says so.
|
|
141
266
|
|
|
267
|
+
`skills` is this Environment's choice of [the Skill set](#the-skill-set):
|
|
268
|
+
`true` accepts it and `false` declines it. A configuration that omits it
|
|
269
|
+
accepts the set. The bootstrap writes it on every invocation that is not a
|
|
270
|
+
forwarded command.
|
|
271
|
+
|
|
142
272
|
`clients` is the local Agent client catalogue and never leaves the installation.
|
|
143
273
|
Each entry names one client whose lifecycle hook configuration this Kit
|
|
144
274
|
reconciles: `kind` is `claude-code`, the one client this Kit installs a hook
|
|
@@ -165,7 +295,7 @@ and the batch it produces, and the lease has to outlive both.
|
|
|
165
295
|
Apply the declared source state to House:
|
|
166
296
|
|
|
167
297
|
```sh
|
|
168
|
-
kit apply
|
|
298
|
+
kit apply
|
|
169
299
|
```
|
|
170
300
|
|
|
171
301
|
Only the state House declares - instances, services, `source_ref`, and Room
|
|
@@ -233,119 +363,81 @@ refuses as `kit_hook_rejected` instead of leaving whatever was installed before.
|
|
|
233
363
|
|
|
234
364
|
## The Google preset
|
|
235
365
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
366
|
+
House holds this Environment's Google Sources, and its owner sets them in the
|
|
367
|
+
App. Each entry names an account name the owner chooses, one service -
|
|
368
|
+
`gmail`, `calendar` or `drive` - the Rooms it goes to, and what its first
|
|
369
|
+
capture takes: `{ "new": true }` for new activity only, `{ "days": n }`,
|
|
370
|
+
`{ "items": n }` or `{ "all": true }`. Neither the configuration file nor any
|
|
371
|
+
command on this computer declares one.
|
|
372
|
+
|
|
373
|
+
Each service captures a fixed corpus under its own read-only scope: Gmail every
|
|
374
|
+
message but Spam and Trash, Calendar the account's primary calendar, and Drive
|
|
375
|
+
the files the account owns.
|
|
376
|
+
|
|
377
|
+
The resident reads the list from `/kit/sources/desired` each time its Kit
|
|
378
|
+
control stream connects and each time House signals `sources` on it, then
|
|
379
|
+
reconciles:
|
|
380
|
+
|
|
381
|
+
- a new entry gets its local state and is captured once its account is signed
|
|
382
|
+
in for its service;
|
|
383
|
+
- a changed entry's Rooms take effect on its next capture;
|
|
384
|
+
- an entry House no longer lists stops, and its checkpoint, health, gaps,
|
|
385
|
+
dropped items and unsaved originals are deleted;
|
|
386
|
+
- an account left with no entry has each of its grants revoked at Google's
|
|
387
|
+
revocation endpoint and its credentials, its OAuth client included, deleted.
|
|
388
|
+
Google's revocation ends every grant the Google user gave the client's
|
|
389
|
+
project, so when another listed account is signed in to the same Google user,
|
|
390
|
+
the Kit deletes the local credentials and revokes nothing.
|
|
391
|
+
|
|
392
|
+
It then reports every entry to `/kit/sources/report`, and reports an entry
|
|
393
|
+
again after each sign-in and each capture: `signed_out` while its
|
|
394
|
+
account holds no grant for its service, `failed` with its cause code when its
|
|
395
|
+
last capture failed, and `ready` otherwise, each with the account's signed-in
|
|
396
|
+
email once the Kit knows it.
|
|
397
|
+
|
|
398
|
+
The Kit ships no Google OAuth client. Each account signs in with the User's
|
|
399
|
+
own: an OAuth client of type Desktop app in the User's Google Cloud project,
|
|
400
|
+
with the service's API enabled there. An entry whose account holds no grant for
|
|
401
|
+
its service opens a login renewal for integration `google`, instance the
|
|
402
|
+
account name and service the entry's service, and presents its ceremony on
|
|
403
|
+
House's owner-authenticated page, so the owner's browser never has to reach
|
|
404
|
+
this Environment. When the account has no client yet, the page first collects
|
|
405
|
+
the client id and secret. It then links to Google's consent for that service's
|
|
406
|
+
scope only; Google sends the browser to a `http://127.0.0.1:<port>/` address
|
|
407
|
+
that nothing answers, and the owner pastes that whole address into the page.
|
|
408
|
+
The Kit accepts it only when it carries the state its own consent issued,
|
|
409
|
+
exchanges the code with its PKCE verifier and the account's client, and stores
|
|
410
|
+
the grant beside the client in `state/google/credentials/<account>.json`. The
|
|
411
|
+
collected values pass through House's live relay only; neither they nor any
|
|
412
|
+
token enter a report, a log or anything House stores. Adding a
|
|
413
|
+
service to a signed-in account asks only for that service's consent, and each
|
|
414
|
+
service keeps its own grant. An address that answers another consent, or a code
|
|
415
|
+
Google refuses to exchange, stores nothing; a declined consent or a ceremony
|
|
416
|
+
that outlives its ten-minute bound cancels the sign-in, and the Kit tries again
|
|
417
|
+
at the next reconciliation.
|
|
418
|
+
|
|
419
|
+
The resident captures each signed-in entry every 15 minutes, with no command.
|
|
420
|
+
An occurrence never overlaps its entry's previous one, and one missed while the
|
|
421
|
+
resident was stopped is not replayed: the next resumes from the checkpoint. The
|
|
422
|
+
first capture fixes the initial choice's boundary, so `new` captures nothing
|
|
423
|
+
that existed then and everything that arrives after.
|
|
246
424
|
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
"migrators": [],
|
|
252
|
-
"instances": [
|
|
253
|
-
{
|
|
254
|
-
"id": "google-account",
|
|
255
|
-
"preset": "google",
|
|
256
|
-
"scopes": ["https://www.googleapis.com/auth/contacts.readonly"],
|
|
257
|
-
"services": [
|
|
258
|
-
{
|
|
259
|
-
"service": "gmail",
|
|
260
|
-
"source_ref": "src_google_mail",
|
|
261
|
-
"rooms": ["work-room"],
|
|
262
|
-
"backfill": { "days": 30 },
|
|
263
|
-
"selection": { "labels": ["INBOX"] }
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
"service": "calendar",
|
|
267
|
-
"source_ref": "src_google_calendar",
|
|
268
|
-
"rooms": ["work-room"],
|
|
269
|
-
"backfill": { "all": true },
|
|
270
|
-
"selection": { "calendars": ["primary"] }
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
"service": "drive",
|
|
274
|
-
"source_ref": "src_google_drive",
|
|
275
|
-
"rooms": ["work-room"],
|
|
276
|
-
"backfill": { "count": 500 },
|
|
277
|
-
"selection": { "files": ["file-id"], "folders": ["folder-id"] }
|
|
278
|
-
}
|
|
279
|
-
]
|
|
280
|
-
}
|
|
281
|
-
],
|
|
282
|
-
"clients": [],
|
|
283
|
-
"host": null
|
|
284
|
-
}
|
|
425
|
+
```sh
|
|
426
|
+
kit source capture work # one occurrence of every entry of the account now
|
|
427
|
+
kit source capture work gmail # one occurrence of one entry now
|
|
428
|
+
kit source status work
|
|
285
429
|
```
|
|
286
430
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
Additional Google API scopes are declared once on the preset instance and
|
|
292
|
-
remain local; a declared service names only scopes that instance already
|
|
293
|
-
holds. Drive requires at least one explicit file or folder selection and never
|
|
294
|
-
defaults to the whole account.
|
|
295
|
-
|
|
296
|
-
A Google API outside the three curated services may use the closed declared
|
|
297
|
-
service schema. The declaration is data only: no script or executable transform
|
|
298
|
-
is loaded. Its host must be a Google API domain and it runs under scopes the
|
|
299
|
-
instance already holds.
|
|
300
|
-
|
|
301
|
-
```json
|
|
302
|
-
{
|
|
303
|
-
"service": "people",
|
|
304
|
-
"source_ref": "src_google_people",
|
|
305
|
-
"rooms": ["work-room"],
|
|
306
|
-
"backfill": { "all": true },
|
|
307
|
-
"declaration": {
|
|
308
|
-
"host": "people.googleapis.com",
|
|
309
|
-
"path": "/v1/people/me/connections",
|
|
310
|
-
"query": { "personFields": "names,emailAddresses,metadata" },
|
|
311
|
-
"page_size": "pageSize",
|
|
312
|
-
"scopes": ["https://www.googleapis.com/auth/contacts.readonly"],
|
|
313
|
-
"page_token": {
|
|
314
|
-
"request": "pageToken",
|
|
315
|
-
"response": "nextPageToken",
|
|
316
|
-
"checkpoint_request": "syncToken",
|
|
317
|
-
"checkpoint_response": "nextSyncToken"
|
|
318
|
-
},
|
|
319
|
-
"items": "connections",
|
|
320
|
-
"fields": {
|
|
321
|
-
"native_id": "resourceName",
|
|
322
|
-
"native_version": "etag",
|
|
323
|
-
"provider_modified_at": "metadata.sources.0.updateTime",
|
|
324
|
-
"observed_at": "metadata.sources.0.updateTime",
|
|
325
|
-
"body": ["names.0.displayName", "emailAddresses.0.value"],
|
|
326
|
-
"container": "metadata.sources.0.type"
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
```
|
|
431
|
+
`kit source capture` and `kit source status` take the account name where a
|
|
432
|
+
custom connector takes its instance; a name House lists as an account is read
|
|
433
|
+
as the account. While the resident runs, it performs the requested occurrence
|
|
434
|
+
itself, after any occurrence of that entry already running.
|
|
331
435
|
|
|
332
|
-
A Google
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
nothing answers: the owner copies that whole address from the address bar and
|
|
338
|
-
pastes it into the page. The Kit accepts it only when it carries the state its
|
|
339
|
-
own consent issued, exchanges the code with its PKCE verifier and the built
|
|
340
|
-
client, and stores the grant locally. An address that answers another consent,
|
|
341
|
-
or a code Google refuses to exchange, fails the login and stores nothing; a
|
|
342
|
-
declined consent cancels it. Grants already completed for earlier services stay.
|
|
343
|
-
|
|
344
|
-
`kit source sign-in <instance>` signs in a custom connector instance through
|
|
345
|
-
its own command, described below. It skips an instance whose local
|
|
346
|
-
authorization is already valid and answers `ready`, `skipped`, or
|
|
347
|
-
`needs_attention`. A Google instance refuses it as `kit_connector_login_guided`
|
|
348
|
-
and names House setup.
|
|
436
|
+
A failed occurrence records its cause. A Google 403 for an API disabled in the
|
|
437
|
+
client's project fails as `api_disabled`, and `kit source status` names the API
|
|
438
|
+
to enable; a revoked scope (`google_scope_revoked`), an expired or revoked grant
|
|
439
|
+
(`google_authority_revoked`) and a provider failure
|
|
440
|
+
(`google_provider_unavailable`) keep their own codes.
|
|
349
441
|
|
|
350
442
|
## Environment setup
|
|
351
443
|
|
|
@@ -354,11 +446,13 @@ its owner asks it to renew what the Environment holds. The Kit acts on the
|
|
|
354
446
|
request it acquires, never on its own:
|
|
355
447
|
|
|
356
448
|
```sh
|
|
357
|
-
kit setup
|
|
449
|
+
kit setup
|
|
358
450
|
```
|
|
359
451
|
|
|
360
452
|
`kit worker run` performs the same step at the start of a pass, before it
|
|
361
|
-
hands out any work, so a managed Environment needs no terminal
|
|
453
|
+
hands out any work, so a managed Environment needs no terminal; the resident
|
|
454
|
+
Kit performs it each time its control stream connects and on each `runs`
|
|
455
|
+
signal, which House also sends for every setup request. The walk first
|
|
362
456
|
prepares the absolute `/agents/house` base, then visits every declared agent
|
|
363
457
|
CLI and then every connector instance, in configuration order:
|
|
364
458
|
|
|
@@ -462,15 +556,54 @@ An object whose content changes without its native version changing keeps its
|
|
|
462
556
|
key and is refused by House as a delivery-key conflict rather than silently
|
|
463
557
|
overwriting the earlier Record.
|
|
464
558
|
|
|
465
|
-
The same command owns its module authorization. `kit source sign-in
|
|
466
|
-
|
|
559
|
+
The same command owns its module authorization. `kit source sign-in <instance>`
|
|
560
|
+
skips an instance whose local authorization is already valid and answers
|
|
561
|
+
`ready`, `skipped`, or `needs_attention`. It and the setup walk's status check
|
|
562
|
+
send one JSON line
|
|
467
563
|
with `action: "authorization"` and `mode: "status"` or `mode: "login"`; the
|
|
468
564
|
command returns exactly one JSON object such as `{ "authorized": true }`.
|
|
469
565
|
|
|
566
|
+
## The Kit control stream
|
|
567
|
+
|
|
568
|
+
The resident Kit holds one `/kit/stream` WebSocket for its Environment,
|
|
569
|
+
authenticated with its Environment control lease and the Kit contract header,
|
|
570
|
+
for as long as it holds that lease; `kit worker run` holds one for the length
|
|
571
|
+
of its pass to receive its owner's commands, and `kit telegram serve` holds one
|
|
572
|
+
while it serves the gateway under a lease of its own. The Kit sends no
|
|
573
|
+
subscribe frame and accepts every frame House sends. What it writes there is
|
|
574
|
+
the live view of the turns it runs, as draft and plan frames the
|
|
575
|
+
[Worker runtime](#the-worker-runtime) describes, and a `gap` frame when the
|
|
576
|
+
[Telegram gateway](#the-telegram-gateway) needs a turn's whole view again.
|
|
577
|
+
|
|
578
|
+
Each time the socket connects, the resident acquires everything a signal could
|
|
579
|
+
have named, because a signal House sent while the socket was down is lost: its
|
|
580
|
+
Runs and resumptions with their setup and conversation files, the owner's
|
|
581
|
+
pending commands, the agent CLI list, the saved working copy choice and its
|
|
582
|
+
Google Sources. After that it acquires only what House names. A
|
|
583
|
+
`work_available` frame for `agents`, `working_copy` or `sources` acquires that
|
|
584
|
+
subject alone. `runs` takes a resumption or else a waiting Run, readying the
|
|
585
|
+
agent CLIs, a requested setup and conversation files first. `commands` hands
|
|
586
|
+
the supervised Session its stops, interrupts and answers and takes a
|
|
587
|
+
resumption the same way, without acquiring a Run. An `entries` frame, a change
|
|
588
|
+
in a Room the lease admits, delivers the working copies. A pass that took a Run
|
|
589
|
+
acquires again once that Run ends, and a pass that found nothing waits for the
|
|
590
|
+
next signal. A Run outcome House did not take is reported again every 30
|
|
591
|
+
seconds until House answers. The Kit has no idle acquisition cycle, no command
|
|
592
|
+
poll and no Session heartbeat: a Session is observed when its process starts
|
|
593
|
+
and when its supervisor sees it stop.
|
|
594
|
+
|
|
595
|
+
A socket that closes or never opens reconnects after a delay drawn between half
|
|
596
|
+
and all of one second, doubled for each consecutive failure up to 30 seconds.
|
|
597
|
+
An `authority_changed` close reconnects after a delay drawn between 0 and 2
|
|
598
|
+
seconds, with no error backoff. A `replaced` close, which means a newer
|
|
599
|
+
connection holds the Environment, ends the resident with `kit_stream_replaced`,
|
|
600
|
+
and an upgrade House refuses with `kit_upgrade_required` stops every House call
|
|
601
|
+
as [above](#connect-a-linux-computer) describes; neither is retried.
|
|
602
|
+
|
|
470
603
|
## The Worker runtime
|
|
471
604
|
|
|
472
605
|
```sh
|
|
473
|
-
kit worker run
|
|
606
|
+
kit worker run
|
|
474
607
|
```
|
|
475
608
|
|
|
476
609
|
Worker-runtime readiness validates the tmux this Kit declares support for,
|
|
@@ -538,27 +671,12 @@ inside `/agents/house` is somebody else's default or an owner's own workspace,
|
|
|
538
671
|
never this Agent's. Every path that is not this exact equality, one deeper
|
|
539
672
|
inside `/agents/house` included, must
|
|
540
673
|
already exist in this Environment as a directory the installation can enter;
|
|
541
|
-
Kit never creates
|
|
542
|
-
|
|
543
|
-
When the Agent's own default directory is absent, Kit
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
directory and uses the directory the winner put there, so the pair still leaves
|
|
548
|
-
one complete directory and nothing partial. A present default directory -
|
|
549
|
-
including one whose starter files the owner edited or removed - launches
|
|
550
|
-
exactly as it is, and a deleted default directory is recreated with a fresh
|
|
551
|
-
starter set on its next launch.
|
|
552
|
-
|
|
553
|
-
The starter set is `AGENTS.md` with the single line ``The agents.house `house`
|
|
554
|
-
CLI is available: run `house --help`.``, `CLAUDE.md` as a relative symbolic link to it, `.agents/skills/grilling/`
|
|
555
|
-
vendored from [`mattpocock/skills`](https://github.com/mattpocock/skills)
|
|
556
|
-
`skills/productivity/grilling` at a pinned commit with its MIT license and a
|
|
557
|
-
provenance header naming that commit, and `.claude/skills` as a relative
|
|
558
|
-
symbolic link to `.agents/skills`. Once seeded the files belong to the owner:
|
|
559
|
-
Kit never syncs, refreshes, or restores them, and refreshing the vendored skill
|
|
560
|
-
for new Agents is an ordinary Kit release that never touches an already seeded
|
|
561
|
-
directory.
|
|
674
|
+
Kit never creates it.
|
|
675
|
+
|
|
676
|
+
When the Agent's own default directory is absent, Kit creates it empty; two
|
|
677
|
+
concurrent first launches create the same directory. A present default
|
|
678
|
+
directory launches exactly as it is, and a deleted one is created empty again
|
|
679
|
+
on its next launch. Kit writes no file into any working directory.
|
|
562
680
|
|
|
563
681
|
A relative, missing, inaccessible, or non-directory working directory refuses
|
|
564
682
|
with `kit_launch_directory_unavailable` before any provider process starts. Kit falls back to no other location - not the
|
|
@@ -566,6 +684,52 @@ base, not `$HOUSE_KIT_HOME`, and not its own current directory - and neither
|
|
|
566
684
|
connecting an installation nor launching a session moves, copies, overwrites,
|
|
567
685
|
or removes anything a working directory holds.
|
|
568
686
|
|
|
687
|
+
## The Skill set
|
|
688
|
+
|
|
689
|
+
The Skill set is every skill the `mattpocock/skills` plugin manifest names at
|
|
690
|
+
one pinned commit but `setup-matt-pocock-skills`, `triage` and `wizard`. Each
|
|
691
|
+
is vendored under `src/skill-set/<name>/` with every file it ships, the
|
|
692
|
+
upstream MIT `LICENSE` and a provenance header in `SKILL.md` naming the commit
|
|
693
|
+
and upstream path. Nothing else is edited but two lines: a
|
|
694
|
+
`disable-model-invocation: true` frontmatter line in `SKILL.md` and an
|
|
695
|
+
`allow_implicit_invocation: false` line in `agents/openai.yaml` are removed, so
|
|
696
|
+
an agent reaches every skill without being told its name.
|
|
697
|
+
|
|
698
|
+
Kit installs the Skill set once for the Environment, for every Agent whatever
|
|
699
|
+
its working directory, under the home it launches agent CLIs with: each skill
|
|
700
|
+
as the directory `$HOME/.agents/skills/<name>`, which Codex and Grok Build
|
|
701
|
+
read, and a relative symbolic link `$HOME/.claude/skills/<name>` to it, which
|
|
702
|
+
Claude Code reads; when `$HOME/.claude/skills` already resolves to
|
|
703
|
+
`$HOME/.agents/skills`, Claude Code reads the directory there and Kit makes no
|
|
704
|
+
link. In a container that home is Kit home, so the set survives
|
|
705
|
+
container recreation; on a native host it is the host user's home.
|
|
706
|
+
|
|
707
|
+
`$HOUSE_KIT_HOME/state/skill-set.json` records the names Kit installed and the
|
|
708
|
+
Kit version that installed them, and Kit owns exactly those names: the
|
|
709
|
+
directory and the link of each. At start and on every resident pass, when
|
|
710
|
+
the set is accepted and the record names another version or none, Kit deletes
|
|
711
|
+
every recorded name, installs the current Skill set and rewrites the record. A
|
|
712
|
+
name whose directory or link exists without being recorded is the owner's: Kit
|
|
713
|
+
leaves it untouched and installs nothing under it. Kit never compares, merges
|
|
714
|
+
or restores a file, so an edit to an installed skill is lost at the next
|
|
715
|
+
release and a copy under another name is kept. When `skills` is `false`, Kit
|
|
716
|
+
deletes every recorded name and the record and installs nothing.
|
|
717
|
+
|
|
718
|
+
After Kit first installs the Skill set, the first Session it launches whose
|
|
719
|
+
Profile ceiling lets it write the owner's How-we-work document
|
|
720
|
+
`/private/library/how-we-work.md` creates it, when it is absent, with the text
|
|
721
|
+
Kit ships in `src/how-we-work.md`, over the Session's own bridge before its
|
|
722
|
+
first prompt is built. Kit then notes in `$HOUSE_KIT_HOME/state/how-we-work`,
|
|
723
|
+
apart from the record, that the document exists, and a present document is
|
|
724
|
+
noted the same way without being touched. Nothing ever creates it again: a
|
|
725
|
+
release, a declined Skill set and a later acceptance leave the note, so an
|
|
726
|
+
owner's edit stands and a deleted document stays deleted. A Session whose
|
|
727
|
+
ceiling cannot write the document launches without it and leaves it for the
|
|
728
|
+
next one; any other refused creation refuses the attempt as
|
|
729
|
+
`kit_how_we_work_unwritable` with House's answer before a prompt is sent. A
|
|
730
|
+
Skill set Kit cannot install or remove refuses the pass as
|
|
731
|
+
`kit_skill_set_unavailable` and names the path.
|
|
732
|
+
|
|
569
733
|
## The declared agent CLIs
|
|
570
734
|
|
|
571
735
|
The Environment owner installs no adapter binary by hand. `kit agents update`
|
|
@@ -575,6 +739,17 @@ minimum's major - under
|
|
|
575
739
|
`$HOUSE_KIT_HOME/agents/<kind>/releases/<release>/`, never touching what the
|
|
576
740
|
owner installed globally, and an acquired route's command is that installed
|
|
577
741
|
executable rather than a path anyone writes into `kit.json`.
|
|
742
|
+
The resident Kit also listens for an `agents` availability pointer on its
|
|
743
|
+
control stream. It reads the whole wanted list from House over HTTPS, removes
|
|
744
|
+
Kit-owned CLI directories that are no longer wanted, installs newly wanted
|
|
745
|
+
kinds, and reports its held state immediately, including while another Agent
|
|
746
|
+
run remains active. A newly wanted kind that needs provider authorization uses
|
|
747
|
+
the existing guided House login ceremony; Kit reports readiness again when it
|
|
748
|
+
ends. A reconnect reads the list again, so a pointer missed during a stream
|
|
749
|
+
outage changes no authority.
|
|
750
|
+
Removal waits for an active worker pass or any unresolved live WorkerSession
|
|
751
|
+
binding to stop using a CLI directory; the Kit keeps reporting that kind until
|
|
752
|
+
it removes the directory.
|
|
578
753
|
|
|
579
754
|
Every candidate release is proved before it serves: the Kit installs it beside
|
|
580
755
|
the current release, runs the contract's own conformance check - the protocol's
|
|
@@ -669,11 +844,24 @@ prompt's stop reason through the contract's own table to one of four turn
|
|
|
669
844
|
outcomes: completed, interrupted, refused by the provider, or exhausted. A stop
|
|
670
845
|
reason the contract does not name, including a vendor-specific one a different
|
|
671
846
|
contract names, fails the turn as `kit_adapter_contract_mismatch` rather than
|
|
672
|
-
being guessed.
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
847
|
+
being guessed. After committing the Run, and again on every resumption, the
|
|
848
|
+
Kit reads what the Session was started for from House's
|
|
849
|
+
`/kit/runs/<run>/request` with the Session credential: the Routine Request with
|
|
850
|
+
its input, references, requester and the pinned revision's instruction, or the
|
|
851
|
+
sealed conversation turn. It sends that as the first prompt block, followed by
|
|
852
|
+
current House guidance fetched through the Run connection, so the Agent calls
|
|
853
|
+
nothing to learn it. An unreadable request or guidance refuses the turn.
|
|
854
|
+
A session opened with `session/new` gets one more text block ahead of those,
|
|
855
|
+
the same for every adapter kind: the line
|
|
856
|
+
`The agents.house house CLI is available: run house --help.`, the base
|
|
857
|
+
instructions of the Execution attempt plan House acquired, and the current text
|
|
858
|
+
of the owner's How-we-work document `/private/library/how-we-work.md`, which the
|
|
859
|
+
launcher reads with the `shell` tool over the Session's own bridge, following
|
|
860
|
+
House's cursor to the whole text. An absent document, one the Session's ceiling
|
|
861
|
+
cannot read, and empty base instructions add nothing. Any other failed read
|
|
862
|
+
refuses the attempt as `kit_how_we_work_unreadable` with the bridge's cause
|
|
863
|
+
before a prompt is sent. A session reloaded with `session/load` already holds
|
|
864
|
+
the block and gets none. It forwards only adapter-classified User-visible assistant
|
|
677
865
|
text back over the local channel, and leaves reasoning, tool traces, and
|
|
678
866
|
terminal output where they are. The supervised process's own House calls travel
|
|
679
867
|
that same channel through the `house` CLI. The Kit holds the WorkerRunToken, replaces it in place when
|
|
@@ -686,37 +874,55 @@ what it has seen so far, and seals the turn itself. No Agent is asked to report
|
|
|
686
874
|
text a deterministic observer already sees, and no agent-facing tool admits final
|
|
687
875
|
text.
|
|
688
876
|
|
|
689
|
-
While the adapter generates, the
|
|
690
|
-
of the turn so far
|
|
877
|
+
While the adapter generates, the supervisor writes the whole User-visible
|
|
878
|
+
assistant text of the turn so far as `draft` frames on the Environment's
|
|
879
|
+
[control stream](#the-kit-control-stream); it calls no draft route. Only
|
|
691
880
|
adapter-classified assistant message text enters that stream; reasoning, tool
|
|
692
|
-
calls,
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
and
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
881
|
+
calls, and terminal output never do. The Kit maps the structure it can read in
|
|
882
|
+
that text - paragraphs, headings, fenced code, ordered and unordered lists, pipe
|
|
883
|
+
tables, and `$$` formulas - into House's blocks, and leaves anything it did not
|
|
884
|
+
parse as the paragraph it observed. It invents no structure, renders nothing,
|
|
885
|
+
and holds back or refuses no draft for its length: a frame carries every block
|
|
886
|
+
of the text however long it is.
|
|
887
|
+
|
|
888
|
+
A frame names the turn it belongs to, as House answered the Session's `started`
|
|
889
|
+
observation with the turn's `conversation_id` and `turn_id`, together with the
|
|
890
|
+
Execution attempt as `attempt_id`. It carries a `sequence` that grows by one
|
|
891
|
+
with each paced view of the turn, and replaces the turn's view from the block
|
|
892
|
+
index `from` onward with the `blocks` it carries, so a frame for text that only
|
|
893
|
+
grew carries the blocks from the first one that changed, and a view that
|
|
894
|
+
changed no block is a frame that replaces nothing. The launcher numbers the
|
|
895
|
+
views, so a Kit that restarts mid-turn continues the turn's sequence. The Kit
|
|
896
|
+
coalesces and paces that stream rather than mirroring every chunk: it writes
|
|
897
|
+
the first observed view at once and then at most one view in each
|
|
898
|
+
500-millisecond pacing window, the latest one, even when the adapter completes
|
|
899
|
+
a message inside a window. A frame written while the socket is down is lost,
|
|
900
|
+
so the first frame after each reconnect, and after any frame the socket could not carry, replaces the view
|
|
901
|
+
from block 0. A Session House names no conversation turn for gets no frames. A
|
|
902
|
+
draft persists nowhere - not in this Kit's local state, not as House history -
|
|
903
|
+
is never retried, and can neither delay nor prove turn completion.
|
|
904
|
+
|
|
905
|
+
A `plan` session update is one snapshot of the agent's steps. The Kit writes
|
|
906
|
+
each snapshot as a `plan` frame paced by the same rule, carrying every step's
|
|
907
|
+
`label`, `priority` and `status` exactly as the adapter gave them, its own
|
|
908
|
+
`sequence`, and the step index `from` it replaces the plan onward. The act that
|
|
909
|
+
ends the turn carries the last snapshot the Kit saw as its final `plan`: the
|
|
910
|
+
seal, the observed stop, the Run outcome and an `interrupted` interrupt outcome
|
|
911
|
+
each name the provider turn and every step's `label` and `status`, however many
|
|
912
|
+
steps and however long their text, and a turn that never planned carries none.
|
|
913
|
+
There is no per-snapshot plan route.
|
|
709
914
|
|
|
710
915
|
When the adapter completes the turn, the Kit seals it with one
|
|
711
|
-
`sessions/<session>/assistant-messages` call carrying the same blocks
|
|
712
|
-
UUIDv7 `operation_id`. The exact request - that identity
|
|
713
|
-
written into the WorkerSession binding before the
|
|
714
|
-
call returns the outcome House recorded and never
|
|
715
|
-
House's answer names the turn it closed and the
|
|
716
|
-
the Kit never received leaves the Run unsettled
|
|
717
|
-
next `kit worker run` replays exactly that
|
|
718
|
-
|
|
719
|
-
House did decide is the Run's
|
|
916
|
+
`sessions/<session>/assistant-messages` call carrying the same blocks, the final
|
|
917
|
+
plan, and a UUIDv7 `operation_id`. The exact request - that identity, those
|
|
918
|
+
blocks and that plan - is written into the WorkerSession binding before the
|
|
919
|
+
call leaves, so a recovered call returns the outcome House recorded and never
|
|
920
|
+
seals a turn twice, and House's answer names the turn it closed and the
|
|
921
|
+
delivery it queued. An answer the Kit never received leaves the Run unsettled
|
|
922
|
+
with the request retained: the next `kit worker run` replays exactly that
|
|
923
|
+
operation, those blocks and that plan before settling anything, rather than
|
|
924
|
+
reporting a failure it cannot prove. A refusal House did decide is the Run's
|
|
925
|
+
reported failure.
|
|
720
926
|
|
|
721
927
|
That seal is the one durable record of the turn, and only a seal House accepted
|
|
722
928
|
completes a turn: the Kit reports whole-turn completion to House after the seal
|
|
@@ -736,7 +942,9 @@ nonzero exit status. The CLI holds
|
|
|
736
942
|
no credential: it calls over its Session's bridge, which attaches the Session
|
|
737
943
|
credential and refuses a caller without that Session's nonce as
|
|
738
944
|
`kit_bridge_unauthorized`. House network calls use only the selected
|
|
739
|
-
`2026-07-28` profile.
|
|
945
|
+
`2026-07-28` profile. `house git push` is the one local verb House does not list;
|
|
946
|
+
[working copies](#working-copies) describe it, and `house --help` and
|
|
947
|
+
`house git push --help` explain it.
|
|
740
948
|
|
|
741
949
|
Two verbs name files on the Session's own computer: `upload_attachment` takes
|
|
742
950
|
one `path`, and `append_record` takes `attachments` as local paths. The CLI
|
|
@@ -760,7 +968,7 @@ Within the same live Kit and supervised WorkerSession, a lost response or
|
|
|
760
968
|
infrastructure failure resends that request with the same identifier. A local
|
|
761
969
|
socket reconnect delivers the retained outcome to the process.
|
|
762
970
|
A second deliberate call gets a new identifier; read-only calls carry none.
|
|
763
|
-
House refusals pass through to the CLI without automatic resend. [R193](https://github.com/agentshouse/core/blob/main/docs/concept/implementation/
|
|
971
|
+
House refusals pass through to the CLI without automatic resend. [R193](https://github.com/agentshouse/core/blob/main/docs/concept/implementation/14-agents-profiles-sessions-and-runs.md#r193)
|
|
764
972
|
owns recovery authority, lifetime, and refusal semantics.
|
|
765
973
|
|
|
766
974
|
The launcher speaks only what the adapter contract fixes for this build. Every
|
|
@@ -819,8 +1027,8 @@ receiving a complete byte stream, validating any reported size, and writing the
|
|
|
819
1027
|
file. A lost acknowledgement preserves the completed local file for House's
|
|
820
1028
|
idempotent admission and later cleanup. Failed files remain pending; House's
|
|
821
1029
|
all-files-ready gate keeps their turn unprocessed.
|
|
822
|
-
The provider receives absolute local paths beside the owning messages
|
|
823
|
-
|
|
1030
|
+
The provider receives absolute local paths beside the owning messages in its
|
|
1031
|
+
first prompt. The cache persists across
|
|
824
1032
|
turns; only House-authorized terminal Run cleanup removes its Run directory.
|
|
825
1033
|
|
|
826
1034
|
The accepted attachment's retained original is separate from that cache. The Kit
|
|
@@ -833,8 +1041,9 @@ A save that fails leaves one note in `state/conversation-originals/` naming the
|
|
|
833
1041
|
attachment, its Run, the local file and the descriptor it declared. Each
|
|
834
1042
|
later `kit worker run` retries it from that file without materializing or
|
|
835
1043
|
acknowledging anything again, and reports `source_unavailable` when
|
|
836
|
-
the file is gone or changed rather than saving different bytes.
|
|
837
|
-
WorkerSession
|
|
1044
|
+
the file is gone or changed rather than saving different bytes. When a
|
|
1045
|
+
supervised WorkerSession ends, the same retry runs once more before its Run is
|
|
1046
|
+
reported. The note leaves once
|
|
838
1047
|
House records the save, once House answers that the Run is over, or when House
|
|
839
1048
|
authorizes that Run's cache cleanup; House accepts no save for a Run that has
|
|
840
1049
|
settled, so an unsaved original keeps its failed outcome from then on. The owner
|
|
@@ -845,8 +1054,8 @@ outcome it handled, and exits non-zero while any of them is unsaved.
|
|
|
845
1054
|
One `kit worker run` then takes one House-authorized resumption, or otherwise
|
|
846
1055
|
acquires one waiting Run, and supervises exactly that WorkerSession. A resumed
|
|
847
1056
|
conversation loads its retained native provider session through ACP
|
|
848
|
-
`session/load`, receives the current input
|
|
849
|
-
|
|
1057
|
+
`session/load`, receives the current input House answers for the Run in its
|
|
1058
|
+
first prompt, and executes one turn. Historical output replayed during
|
|
850
1059
|
loading is not emitted as new assistant output. Missing or rejected provider
|
|
851
1060
|
continuation never starts a replacement provider conversation in the same Run.
|
|
852
1061
|
|
|
@@ -861,7 +1070,7 @@ Between turns, Kit retains the opaque provider session identifier and the Run's
|
|
|
861
1070
|
Worker, working directory, and route references in an owner-only local record.
|
|
862
1071
|
The record carries no transcript or Session credential and grants no authority:
|
|
863
1072
|
House must authorize each successor WorkerSession. A reported terminal state and
|
|
864
|
-
owner stops remove the record. [R199](https://github.com/agentshouse/core/blob/main/docs/concept/implementation/
|
|
1073
|
+
owner stops remove the record. [R199](https://github.com/agentshouse/core/blob/main/docs/concept/implementation/14-agents-profiles-sessions-and-runs.md#r199)
|
|
865
1074
|
owns conversation continuity.
|
|
866
1075
|
|
|
867
1076
|
Launcher exit is the terminal process observation. The Kit closes the local
|
|
@@ -913,7 +1122,12 @@ content, no prompt, and no resolved secret, and Session authority is always
|
|
|
913
1122
|
reissued by House rather than recovered from disk. It is evidence for
|
|
914
1123
|
reconciliation, never permission to resume or recreate work, and nothing keeps
|
|
915
1124
|
it once House has answered for the Run: a settled terminal state, a confirmed
|
|
916
|
-
owner stop, and a retained Provider continuation each drop it.
|
|
1125
|
+
owner stop, and a retained Provider continuation each drop it. When the
|
|
1126
|
+
supervised process ends, the binding first records what the Kit observed: the
|
|
1127
|
+
sealed final text, whether the turn completed, the capacity or provider refusal,
|
|
1128
|
+
the execution failure and whether a Provider continuation is retained. The Kit
|
|
1129
|
+
then reports that stop, and a restarted Kit reports the same recorded stop
|
|
1130
|
+
instead of treating the session as lost.
|
|
917
1131
|
|
|
918
1132
|
A restarted `kit worker run` reconciles the records it kept before it acquires
|
|
919
1133
|
anything new. It reports every retained settlement note first, because those
|
|
@@ -937,7 +1151,7 @@ A restore of House's database starts a new log epoch. Until this Environment
|
|
|
937
1151
|
has reported in it, House refuses every act that touches a Run, acquisition and
|
|
938
1152
|
lease release included, as `epoch_report_required` naming the epoch. The first
|
|
939
1153
|
such refusal ends whatever the pass was doing. One raised inside a supervised
|
|
940
|
-
Run's bridge, while it admits or settles a question,
|
|
1154
|
+
Run's bridge, while it admits or settles a question, reports an interrupt, or
|
|
941
1155
|
replaces Session authority for a forwarded call, never becomes an answer to the
|
|
942
1156
|
Agent: it ends the bridge and the pass at once. The Kit then reports, under the
|
|
943
1157
|
lease it holds and at `POST /kit/sessions/report`, every Run it holds a spawn
|
|
@@ -965,7 +1179,10 @@ written into the durable binding. Reconciliation must obtain current House
|
|
|
965
1179
|
authority before the live process can make further calls.
|
|
966
1180
|
|
|
967
1181
|
An owner stop requested through House reaches this Kit as a durable command,
|
|
968
|
-
both at startup and while a Session is supervised
|
|
1182
|
+
both at startup and while a Session is supervised: House signals `commands` on
|
|
1183
|
+
the Kit control stream and the supervisor acquires the pending stops,
|
|
1184
|
+
interrupts and answers at once, so a stop reaches the process within a second.
|
|
1185
|
+
The Kit destroys the exact
|
|
969
1186
|
tmux session, confirms that it is gone, and reports the stopped Session. It
|
|
970
1187
|
reports no continuation for a Run stopped by its owner and never reopens the
|
|
971
1188
|
local channel for that Session.
|
|
@@ -1004,8 +1221,8 @@ into the evidence each spec writes under `tmp/delivery-evidence/`.
|
|
|
1004
1221
|
## Capturing
|
|
1005
1222
|
|
|
1006
1223
|
```sh
|
|
1007
|
-
kit source capture acme
|
|
1008
|
-
kit source capture acme notes
|
|
1224
|
+
kit source capture acme # every declared service
|
|
1225
|
+
kit source capture acme notes # one service
|
|
1009
1226
|
```
|
|
1010
1227
|
|
|
1011
1228
|
Each run reads the checkpoint, acquires one bounded page, submits one batch,
|
|
@@ -1019,8 +1236,8 @@ on the door's own deduplication. When House stops a batch early, its answer
|
|
|
1019
1236
|
settles only the prefix it reached, and the unsettled tail is reoffered with the
|
|
1020
1237
|
rest. The loop repeats while the connector still returns items and no Room
|
|
1021
1238
|
destination is blocked, and every run ends by writing the service's health into
|
|
1022
|
-
this installation's own state. House holds no
|
|
1023
|
-
or health
|
|
1239
|
+
this installation's own state. House holds no custom connector's service, route,
|
|
1240
|
+
checkpoint or health, and no Google entry's checkpoint or health.
|
|
1024
1241
|
|
|
1025
1242
|
A Capture item that declares a `file` attachment answers one Record per Room
|
|
1026
1243
|
destination: Rooms of one owner share that owner's Record, and a Room of another
|
|
@@ -1038,8 +1255,8 @@ Room and Record and exits non-zero while any stays unsaved; acquisition health
|
|
|
1038
1255
|
stays about acquisition, so a failed save never changes it.
|
|
1039
1256
|
|
|
1040
1257
|
```sh
|
|
1041
|
-
kit source retry-files acme
|
|
1042
|
-
kit source retry-files acme notes
|
|
1258
|
+
kit source retry-files acme # every declared service
|
|
1259
|
+
kit source retry-files acme notes # one service
|
|
1043
1260
|
```
|
|
1044
1261
|
|
|
1045
1262
|
`retry-files` saves only the references still outstanding. It runs no connector,
|
|
@@ -1062,10 +1279,27 @@ retained references still waiting to be saved.
|
|
|
1062
1279
|
Every command that changes or reads installation state takes this
|
|
1063
1280
|
installation's exclusive Environment control lease for the length of its run
|
|
1064
1281
|
and renews it before it expires, so two Kit commands never work against the
|
|
1065
|
-
same installation at once. A command that ends, or is interrupted
|
|
1066
|
-
has stopped
|
|
1067
|
-
|
|
1068
|
-
|
|
1282
|
+
same installation at once. A command that ends, is refused, or is interrupted
|
|
1283
|
+
once its work has stopped releases that exact lease so the next command acquires
|
|
1284
|
+
at once. A `kit login` credential is presented only to take that lease.
|
|
1285
|
+
|
|
1286
|
+
While `kit resident` holds that lease, a command runs through it instead: the
|
|
1287
|
+
command presents no credential, the resident confirms its current lease with
|
|
1288
|
+
House and sends the command's House requests under it, an interrupted command
|
|
1289
|
+
cancels its request there, and the lease stays held when the command ends. The
|
|
1290
|
+
resident serves one such command at a time and refuses another with
|
|
1291
|
+
`environment_control_lease_active`, so two commands still never work at once.
|
|
1292
|
+
A resident whose lease House refuses answers the command with that refusal; the
|
|
1293
|
+
command never acquires a lease of its own while a resident serves it. While an
|
|
1294
|
+
update drains, `state/update-drain` refuses every such command, `kit login` and
|
|
1295
|
+
`kit worker run` with `kit_update_draining` before it enrolls, acquires or
|
|
1296
|
+
delegates anything. A command already served keeps the resident's lease until
|
|
1297
|
+
it ends, while the resident refuses its acquisition of new work and its
|
|
1298
|
+
Telegram updates with `kit_update_draining`, which ends a served
|
|
1299
|
+
`kit telegram serve` once each of its activities reports the deliveries and
|
|
1300
|
+
files it already acquired; until it ends, the drain answers that it waits for
|
|
1301
|
+
that command and the bootstrap leaves the container as it is. The bootstrap
|
|
1302
|
+
removes the file when it replaces the container.
|
|
1069
1303
|
|
|
1070
1304
|
Interrupting the command cancels the running connector without advancing the
|
|
1071
1305
|
checkpoint.
|
|
@@ -1078,8 +1312,7 @@ Git credential:
|
|
|
1078
1312
|
```sh
|
|
1079
1313
|
kit repository capture /srv/acme \
|
|
1080
1314
|
--room work-room \
|
|
1081
|
-
--source-handle acme-repository
|
|
1082
|
-
--house https://agents.house
|
|
1315
|
+
--source-handle acme-repository
|
|
1083
1316
|
```
|
|
1084
1317
|
|
|
1085
1318
|
The command runs ordinary `git pull` in the checkout with the local User's Git
|
|
@@ -1104,25 +1337,186 @@ interrupted run is never resumed: the next run opens a new manifest and House
|
|
|
1104
1337
|
answers with what is still needed. The command reports the Publication
|
|
1105
1338
|
reference, the paths delivered, the items refused and the ending.
|
|
1106
1339
|
|
|
1340
|
+
## Working copies
|
|
1341
|
+
|
|
1342
|
+
The Environment owner chooses in House which Rooms this Environment keeps
|
|
1343
|
+
locally, and whether it keeps `/private`. An Environment whose owner never chose
|
|
1344
|
+
copies nothing, and a Room joined later stays uncopied until the owner selects
|
|
1345
|
+
it. The resident Kit reads the saved choice through
|
|
1346
|
+
`POST /kit/working-copy/selection` whenever its control stream connects or
|
|
1347
|
+
reconnects and whenever House points it there after a save;
|
|
1348
|
+
`kit worker run` reads it once before its pass.
|
|
1349
|
+
|
|
1350
|
+
Each selected Room becomes one ordinary Git repository at
|
|
1351
|
+
`/agents/house/working-copies/rooms/<room_ref>`, and `/private` one at
|
|
1352
|
+
`/agents/house/working-copies/private`. The Room reference names the location,
|
|
1353
|
+
so a Room handle change moves nothing. Every Agent launched afterwards receives
|
|
1354
|
+
the House path and local repository of each active copy in its context, one
|
|
1355
|
+
line each, such as `/rooms/work: /agents/house/working-copies/rooms/r_1x.q`.
|
|
1356
|
+
|
|
1357
|
+
A Room repository holds the Room's complete readable content: `ROOM.md`,
|
|
1358
|
+
`library/`, `capture/` with its provenance sidecars, and `collaboration/`. The
|
|
1359
|
+
`/private` repository holds its Library, collaboration, each Room's private
|
|
1360
|
+
`AGENTS.md`, the `agents/` cards and `house/`. Attached settings and attachment
|
|
1361
|
+
bytes are not copied. The branch `main` starts at the commit House served, which
|
|
1362
|
+
tracks exactly the files House declares writable under the Environment's
|
|
1363
|
+
current grant. Every other file is read-only House content: the generated
|
|
1364
|
+
`.gitignore` names and explains it, so Git never tracks it, and the matching
|
|
1365
|
+
`.ignore` keeps it visible to ripgrep and other native search. Neither file
|
|
1366
|
+
grants anything, and House refuses a change to a read-only path however it is
|
|
1367
|
+
committed.
|
|
1368
|
+
|
|
1369
|
+
Local edits, staging and commits change nothing in House until a commit is
|
|
1370
|
+
pushed. `refs/house/received` records the House content last received; each
|
|
1371
|
+
commit Kit wrote there, and each commit it acknowledged for a push, is a House
|
|
1372
|
+
state. The House revision of every file content Kit received, keyed by path,
|
|
1373
|
+
Git blob and the House state that received it, stays in Kit home under
|
|
1374
|
+
`state/working-copies/`, outside the repository. A local commit is a local tree, never a House revision.
|
|
1375
|
+
|
|
1376
|
+
The resident Kit keeps every active copy current. Whenever its control stream
|
|
1377
|
+
carries a Room change, and whenever it reads the saved choice, one
|
|
1378
|
+
`POST /kit/door/discover` tells it where each
|
|
1379
|
+
copied Room stands, and for a Room that moved on it reads the changes after the
|
|
1380
|
+
copy's recorded position through `POST /kit/door/enumerate`. A changed, new or
|
|
1381
|
+
removed authored file becomes a commit on `refs/house/received`, its House
|
|
1382
|
+
revision kept in Kit home; changed, new or removed read-only content, such as
|
|
1383
|
+
Capture with its provenance sidecar or a House projection, is written into or
|
|
1384
|
+
removed from the ignored local tree, with each directory a removal leaves empty,
|
|
1385
|
+
and `.gitignore` and `.ignore` follow it.
|
|
1386
|
+
Delivery never touches the branch, the index or a tracked file, and a push
|
|
1387
|
+
waiting for its outcome or its local integration keeps its record. A push takes
|
|
1388
|
+
each file's revision from the newest House state in its own base's history that
|
|
1389
|
+
received that content, so a local commit keeps the base it was made on even when
|
|
1390
|
+
House returns to the same text under a newer revision. A file new to the copy is tracked when a write scope
|
|
1391
|
+
House declares for the Room covers it more closely than a declared protected
|
|
1392
|
+
path, and a local file already sitting where new read-only content arrives
|
|
1393
|
+
stays yours: Kit neither overwrites nor later removes it. When the write scopes
|
|
1394
|
+
or protected paths House declares for the Room change, Kit reads the Room again
|
|
1395
|
+
as a reselection does. A position older than House
|
|
1396
|
+
retains, or from before House's database was restored, makes Kit read the Room
|
|
1397
|
+
again as a reselection does; while House's replica has not reached the position
|
|
1398
|
+
the copy waits, and the resident delivers again 30 seconds later. A Room House
|
|
1399
|
+
no longer answers under its
|
|
1400
|
+
recorded handle makes Kit read the saved choice again, which follows a handle
|
|
1401
|
+
change or marks the copy inactive, and a Room that lost sync is named on
|
|
1402
|
+
standard error as `operation_denied` and keeps what it holds. `kit worker run`
|
|
1403
|
+
delivers once, after reading the saved choice.
|
|
1404
|
+
|
|
1405
|
+
`house git push [commit]`, run anywhere inside a copy or one of its linked
|
|
1406
|
+
worktrees, submits one commit, `HEAD` by default, resolved once. Kit compares
|
|
1407
|
+
that commit's tree with the newest House state in its history, so every linked
|
|
1408
|
+
worktree keeps its own base, and sends the difference as one ordinary House edit:
|
|
1409
|
+
a changed field, section or preamble against its own prior value, any other
|
|
1410
|
+
change as the whole file against its exact revision, a new file as a create and
|
|
1411
|
+
a committed deletion as a removal. Staged and unstaged work, and files absent
|
|
1412
|
+
only from the working tree, are never sent. Native `git push` reaches no House
|
|
1413
|
+
remote. Inside an Agent Session the push goes through that Session's bridge,
|
|
1414
|
+
under its own authority and provenance; outside one it needs
|
|
1415
|
+
`house git push [commit] --owner`, which the resident Kit carries out under its
|
|
1416
|
+
control lease when a resident runs, and which otherwise acquires and releases
|
|
1417
|
+
its own. A Session refuses `--owner`, and a missing bridge is never replaced by
|
|
1418
|
+
owner authority.
|
|
1419
|
+
|
|
1420
|
+
A Session's edit too large for one MCP request of 4 MiB goes through House's
|
|
1421
|
+
`prepare_edit_upload` Command on that Session's bridge, naming every changed
|
|
1422
|
+
path, the byte count and the SHA-256 of the bytes to upload under the push's
|
|
1423
|
+
operation. Those bytes are the serialized changes, padded with trailing spaces
|
|
1424
|
+
to one byte over 4 MiB when only the request around them passed the bound,
|
|
1425
|
+
because House takes no smaller upload. Kit sends them to the upload address
|
|
1426
|
+
House returns and then calls `edit` with the paths and the returned upload
|
|
1427
|
+
instead of the changes, so House applies them as the same one edit. The upload
|
|
1428
|
+
is recorded in Kit home before the edit is sent, so a push whose answer was lost
|
|
1429
|
+
resends that same edit; when House no longer holds the uploaded bytes and has
|
|
1430
|
+
not applied the edit, the push uploads them again once under the same operation.
|
|
1431
|
+
A change set beyond House's batch bounds is refused whole and never split.
|
|
1432
|
+
|
|
1433
|
+
Inside an Agent Session `git` is Kit's shim in front of the installed Git, and
|
|
1434
|
+
every command runs exactly as that Git runs it. In a copy or one of its linked
|
|
1435
|
+
worktrees the shim compares that worktree's index before and after each
|
|
1436
|
+
command. When `git mv` succeeds, Git's own dry run of the same command names
|
|
1437
|
+
which path went where, and the shim hands each move to the resident Kit, which
|
|
1438
|
+
keeps every moved document's successive paths in Kit home. A staged move
|
|
1439
|
+
belongs to its worktree's index: a command there that takes its path out of the
|
|
1440
|
+
index or brings it in anew, such as `git reset`, `git restore --staged`,
|
|
1441
|
+
`git rm`, `git stash` or `git switch`, takes it back, and so does removing the
|
|
1442
|
+
worktree. A `git commit` whose commit carries the move ties it to that commit.
|
|
1443
|
+
A tied move counts for every pushed commit whose history holds one of its
|
|
1444
|
+
commits, whatever the index does meanwhile. `git commit --amend` and
|
|
1445
|
+
`git rebase`, Kit's own rebase onto House's result included, also tie it to
|
|
1446
|
+
their result when the rewritten branch still carries it, so aborting the rebase
|
|
1447
|
+
or resetting back to the original commit keeps it as well. A `git reset` that
|
|
1448
|
+
leaves every commit of the move behind without touching its latest path in the
|
|
1449
|
+
index returns it to that worktree's index, where the next commit ties it again.
|
|
1450
|
+
Any other rewrite, such as a cherry-pick, leaves the move tied to its earlier
|
|
1451
|
+
commits. A push sends House's rename of the same document from the path its
|
|
1452
|
+
House base holds to the latest of its counted paths the pushed commit holds,
|
|
1453
|
+
when the commit no longer has the first and the base did not have the second;
|
|
1454
|
+
a moved file whose content also changed follows as a
|
|
1455
|
+
whole-file replacement at its destination. House keeps the document's identity
|
|
1456
|
+
and rewrites the links and references that name it; Kit reads those rewrites
|
|
1457
|
+
through `POST /kit/door/enumerate` and records them in the acknowledgment.
|
|
1458
|
+
Anything else records no move and the push sends an ordinary removal and
|
|
1459
|
+
creation, which House refuses while another document still refers to the
|
|
1460
|
+
removed one: a failed `git mv`, one undone or never committed through the
|
|
1461
|
+
shim, and a move made with Git outside the shim such as in the owner's own
|
|
1462
|
+
shell. An accepted push drops the moves its commit's history holds.
|
|
1463
|
+
|
|
1464
|
+
House decides before any local Git step. A refusal changes nothing in House;
|
|
1465
|
+
after `edit_conflict` Kit records the current content House names for the
|
|
1466
|
+
refused paths in `refs/house/received`, reading by revision any content the
|
|
1467
|
+
refusal does not carry, so the agent merges or rebases onto it with native Git,
|
|
1468
|
+
commits, and pushes again. After acceptance Kit records House's result for the
|
|
1469
|
+
pushed paths, the contents an owner push receives or each accepted revision
|
|
1470
|
+
read by name, in a commit that covers the pushed one and in
|
|
1471
|
+
`refs/house/received`; a read-only path House regenerates, such as the Wiki
|
|
1472
|
+
index, stays out of Git. The copy's recorded position goes back to where it
|
|
1473
|
+
stood when the push was sent, so the next delivery brings again anything House
|
|
1474
|
+
changed after the push's result, including what delivery received while the
|
|
1475
|
+
push awaited its answer. Kit then
|
|
1476
|
+
fast-forwards a clean branch still at the pushed commit, or rebases only its
|
|
1477
|
+
later commits. A result not yet readable, uncommitted tracked changes,
|
|
1478
|
+
a moved branch or a rebase conflict leave the branch as it was, with no stash or
|
|
1479
|
+
reset, and the push answers that House accepted it while local integration is
|
|
1480
|
+
pending; the next `house git push` finishes that integration without another
|
|
1481
|
+
House edit. A push whose answer was lost is recorded in Kit home before it is
|
|
1482
|
+
sent, and the next push by the same Session, or by the owner for an owner push,
|
|
1483
|
+
resends it under its original operation. Another caller cannot
|
|
1484
|
+
recover it: while the pushing Session lives it is refused as
|
|
1485
|
+
`kit_working_copy_push_pending`, and once that Session has ended Kit reads House
|
|
1486
|
+
again and drops it. When a retained push's operation has expired, Kit reads the
|
|
1487
|
+
Room again: if House holds the pushed content the push finishes as accepted,
|
|
1488
|
+
otherwise it is dropped and the next push submits it as a new operation.
|
|
1489
|
+
|
|
1490
|
+
Deselecting a Room, or losing read access to it, marks its copy inactive:
|
|
1491
|
+
launches omit it, delivery stops, a new push is refused as
|
|
1492
|
+
`kit_working_copy_inactive`, and nothing local is deleted; a push already sent still settles and integrates. Selecting it again reads the Room
|
|
1493
|
+
again, advances `refs/house/received`, and replaces only the read-only content
|
|
1494
|
+
Kit wrote, never the branch, the index or a tracked file. A Room the owner may
|
|
1495
|
+
read without sync is refused as `operation_denied` and stays uncopied, while its
|
|
1496
|
+
ordinary remote reads are unaffected. Kit names each refused copy on its
|
|
1497
|
+
standard error.
|
|
1498
|
+
|
|
1107
1499
|
## Explicit synchronization
|
|
1108
1500
|
|
|
1109
|
-
Beside
|
|
1501
|
+
Beside [working copies](#working-copies), Kit has one explicit synchronization mode.
|
|
1110
1502
|
It selects prefixes over the User root, materializes them into a named local
|
|
1111
1503
|
directory, enumerates whole content and removals after the recorded positions,
|
|
1112
1504
|
and submits a resolved exact-base change set the caller prepared. Kit does no
|
|
1113
1505
|
local reconciliation. The mode shares no Working Copy manifest, never infers a
|
|
1114
|
-
removal from a locally absent file, and writes authored mutations only
|
|
1115
|
-
|
|
1506
|
+
removal from a locally absent file, and writes authored mutations only within
|
|
1507
|
+
House's declared write scopes: a selected Room's Library and, where granted,
|
|
1508
|
+
`ROOM.md`. `/private` selects the Private Room by its Room reference, records an independent Room
|
|
1509
|
+
position, and keeps its `agents/` cards and Room-specific private `AGENTS.md`
|
|
1510
|
+
beside `library/**`.
|
|
1116
1511
|
|
|
1117
1512
|
```sh
|
|
1118
1513
|
kit sync bootstrap ./replica \
|
|
1119
|
-
--house https://agents.house \
|
|
1120
1514
|
--prefix /rooms/work/library \
|
|
1121
1515
|
--prefix /rooms/work/capture \
|
|
1122
1516
|
--prefix /private/library
|
|
1123
|
-
kit sync pull ./replica
|
|
1124
|
-
kit sync submit ./replica --
|
|
1125
|
-
kit sync rebootstrap ./replica
|
|
1517
|
+
kit sync pull ./replica
|
|
1518
|
+
kit sync submit ./replica --changes ./changes.json
|
|
1519
|
+
kit sync rebootstrap ./replica
|
|
1126
1520
|
```
|
|
1127
1521
|
|
|
1128
1522
|
`bootstrap` writes `ROOM.md`, Library text, House-derived projections, and
|
|
@@ -1135,10 +1529,12 @@ a Room the User can only read answers `bootstrap`, `pull`, and `rebootstrap`
|
|
|
1135
1529
|
with `operation_denied`. Generated `_provenance` files delivered beside authored
|
|
1136
1530
|
Library paths are House metadata, not authored Library documents. `pull` presents
|
|
1137
1531
|
each recorded position with its log epoch, applies each enumerated path's whole
|
|
1138
|
-
content or removal, and advances those positions. A
|
|
1532
|
+
content or removal, and advances those positions. A removal, pulled or accepted
|
|
1533
|
+
from `submit`, also removes each directory it leaves empty up to the authority,
|
|
1534
|
+
so a later file can take that path; a directory still holding a file, such as a
|
|
1535
|
+
local draft, stays. A position older than House's
|
|
1139
1536
|
declared retention, or one of a log epoch before House's database was restored,
|
|
1140
|
-
is reported as `position_expired
|
|
1141
|
-
`rebootstrap` rebuilds the directory.
|
|
1537
|
+
is reported as `position_expired`; only `rebootstrap` rebuilds the directory.
|
|
1142
1538
|
|
|
1143
1539
|
`submit` sends field, section, and preamble operations with that value's prior
|
|
1144
1540
|
content as base, and whole-file, rename, and removal operations with the file
|
|
@@ -1152,7 +1548,12 @@ House alone validates the resulting Library: a batch it refuses answers with
|
|
|
1152
1548
|
House's own file path, field, rule, and version. A refusal is reported with the
|
|
1153
1549
|
current material House returned and the local directory is left for the caller.
|
|
1154
1550
|
An acceptance updates the recorded position, its log epoch, and the affected
|
|
1155
|
-
files from the returned final content.
|
|
1551
|
+
files from the returned final content. It also reads House's own provenance
|
|
1552
|
+
for those files by enumerating from the position the batch started at, and
|
|
1553
|
+
writes each served sidecar whose revision is the accepted one, so a submit,
|
|
1554
|
+
answered or recovered after a lost answer, leaves each file's `_provenance`
|
|
1555
|
+
sidecar at the revision House recorded. Kit never composes that metadata
|
|
1556
|
+
itself.
|
|
1156
1557
|
|
|
1157
1558
|
Pending submissions are written before transfer. A lost response, reconnect, or
|
|
1158
1559
|
lease renewal recovers that exact request under the same identifier. A domain
|
|
@@ -1165,6 +1566,10 @@ the Kit drops it like any other refusal, `rebootstrap` rebuilds the directory,
|
|
|
1165
1566
|
and a change still wanted is a new deliberate submit against the rebuilt bases.
|
|
1166
1567
|
Once House has answered any request for a replica `position_expired`, the
|
|
1167
1568
|
replica refuses `submit` as `position_expired` until `rebootstrap` rebuilds it.
|
|
1569
|
+
A pending submission House answers `operation_expired` is uncertain, so the
|
|
1570
|
+
Kit first pulls confirmed state. If House already holds the pending change,
|
|
1571
|
+
the Kit drops the pending copy and sends nothing more; only if it does not
|
|
1572
|
+
does the Kit send that change again under a new identifier.
|
|
1168
1573
|
`rebootstrap` drops a submission still pending against the directory it
|
|
1169
1574
|
replaces.
|
|
1170
1575
|
|
|
@@ -1179,23 +1584,20 @@ for a batch that reaches it.
|
|
|
1179
1584
|
|
|
1180
1585
|
## Attachments
|
|
1181
1586
|
|
|
1182
|
-
Upload one local file as an attachment to a Room or to your
|
|
1587
|
+
Upload one local file as an attachment to a Room or to your Private Room. Name
|
|
1183
1588
|
the place explicitly. Kit sends the descriptor and the selected bytes; it does
|
|
1184
1589
|
not scan a directory, convert a URL, or attach sibling files, credentials, or
|
|
1185
1590
|
absolute paths.
|
|
1186
1591
|
|
|
1187
1592
|
```sh
|
|
1188
1593
|
kit attachment upload ./notes.bin \
|
|
1189
|
-
--house https://agents.house \
|
|
1190
1594
|
--room room:work \
|
|
1191
1595
|
--media-type application/pdf
|
|
1192
1596
|
|
|
1193
1597
|
kit attachment upload ./notes.bin \
|
|
1194
|
-
--house https://agents.house \
|
|
1195
1598
|
--private
|
|
1196
1599
|
|
|
1197
1600
|
kit attachment get \
|
|
1198
|
-
--house https://agents.house \
|
|
1199
1601
|
--attachment at_1x.q \
|
|
1200
1602
|
--room room:work \
|
|
1201
1603
|
--output ./notes.bin
|
|
@@ -1241,7 +1643,7 @@ Any missing prerequisite refuses the create before House ever presents the
|
|
|
1241
1643
|
workspace as constrained, naming the exact missing piece.
|
|
1242
1644
|
|
|
1243
1645
|
```sh
|
|
1244
|
-
kit workspace host
|
|
1646
|
+
kit workspace host
|
|
1245
1647
|
```
|
|
1246
1648
|
|
|
1247
1649
|
The command acquires this host's workspace work under its Environment control
|
|
@@ -1273,6 +1675,13 @@ House authorizes: a managed workspace House no longer authorizes to run is
|
|
|
1273
1675
|
stopped, and a container this Kit did not create is never adopted, started or
|
|
1274
1676
|
removed.
|
|
1275
1677
|
|
|
1678
|
+
A pass House does not answer, such as one during a House restart, ends that
|
|
1679
|
+
pass only, and the host tries again on the next one; a pass House refuses ends
|
|
1680
|
+
the host. Without `--passes` the host serves until SIGINT or SIGTERM. It
|
|
1681
|
+
asks House to release its control lease when it ends, after its passes, a
|
|
1682
|
+
refusal, SIGINT or SIGTERM; once House has released it, a restarted host is
|
|
1683
|
+
admitted at once.
|
|
1684
|
+
|
|
1276
1685
|
Ceilings are shared ceilings. The ceilings configured across one host may exceed
|
|
1277
1686
|
that host, nothing is reserved for any workspace, and no workspace is promised
|
|
1278
1687
|
its maximum while another one runs.
|
|
@@ -1296,7 +1705,7 @@ image from the original the Session stored.
|
|
|
1296
1705
|
Bind the bot to this Environment:
|
|
1297
1706
|
|
|
1298
1707
|
```sh
|
|
1299
|
-
kit telegram connect
|
|
1708
|
+
kit telegram connect
|
|
1300
1709
|
```
|
|
1301
1710
|
|
|
1302
1711
|
The command asks for the token on a hidden terminal prompt, or reads one line
|
|
@@ -1315,12 +1724,12 @@ proven owner's Telegram user id.
|
|
|
1315
1724
|
Run the gateway:
|
|
1316
1725
|
|
|
1317
1726
|
```sh
|
|
1318
|
-
kit telegram serve
|
|
1727
|
+
kit telegram serve
|
|
1319
1728
|
```
|
|
1320
1729
|
|
|
1321
1730
|
The command holds one Environment control lease for the whole run and performs
|
|
1322
1731
|
three activities inside it, each paced on its own so none of them blocks
|
|
1323
|
-
another:
|
|
1732
|
+
another, beside the live drafts described below:
|
|
1324
1733
|
|
|
1325
1734
|
- **ingress** reads updates from the stored offset, normalizes each one into the
|
|
1326
1735
|
update House accepts, submits it, and advances the stored offset only after
|
|
@@ -1341,15 +1750,39 @@ another:
|
|
|
1341
1750
|
original, and reported the same way; a pull that fails reports
|
|
1342
1751
|
`transfer_failed` and an ambiguous upload answer reports `delivery_unknown`.
|
|
1343
1752
|
Only an image ever becomes a file item, because House offers every other file
|
|
1344
|
-
as a `conversation_file_link` message this queue delivers like any other.
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
the
|
|
1753
|
+
as a `conversation_file_link` message this queue delivers like any other. The
|
|
1754
|
+
queue carries no draft: an answer holding a draft item is refused as
|
|
1755
|
+
`kit_telegram_response_invalid`. House caps no message, so the gateway alone
|
|
1756
|
+
fits one to Telegram's rich message limits, 32,768 characters and 500 blocks:
|
|
1757
|
+
a rich message past them is sent as consecutive messages in order, split
|
|
1758
|
+
between blocks and inside a block only when that block alone exceeds them,
|
|
1759
|
+
and reported once, `delivered` with the first message's id when every part
|
|
1760
|
+
was delivered and otherwise with the answer of the first part that was not.
|
|
1761
|
+
Each answer also names the `threads` the bot's topics carry, a
|
|
1762
|
+
`conversation_id` with its `chat_id` and `topic_id`, which is where live
|
|
1763
|
+
drafts go.
|
|
1764
|
+
|
|
1765
|
+
Live drafts come from the control stream, not from House's queue. Run on its
|
|
1766
|
+
own, the command holds the Environment's [control stream](#the-kit-control-stream)
|
|
1767
|
+
for its lease; served by `kit resident`, it receives the draft and plan frames
|
|
1768
|
+
the resident's socket receives, through the resident, and never opens a second
|
|
1769
|
+
socket. The gateway Environment's socket carries every conversation bound to a
|
|
1770
|
+
topic of the bot, with no subscribe frame. The gateway keeps the latest view of
|
|
1771
|
+
each such conversation's turn: a frame that starts at block 0 replaces a view,
|
|
1772
|
+
the next frame in sequence applies from its `from`, and a frame after a gap in
|
|
1773
|
+
the sequence, or one for a turn it holds no view of, is applied nowhere and
|
|
1774
|
+
answered with one `gap` frame naming the conversation and turn, so House sends
|
|
1775
|
+
the whole view again. It renders each view as one Telegram draft per turn with
|
|
1776
|
+
`sendRichMessageDraft` on the bound topic, the live plan above the assistant
|
|
1777
|
+
text, under one draft id derived from the turn, because Telegram shows one bot
|
|
1778
|
+
draft per topic and a second id would replace the first. A view past the rich
|
|
1779
|
+
message limits is shortened inside that one draft, never split into a second.
|
|
1780
|
+
A live plan is part of the draft and never a sent message; the frozen plan
|
|
1781
|
+
House queues at the turn's end is the turn's one plan message. Drafts coalesce
|
|
1782
|
+
to the latest view, one Bot API call at a time, and are never reported back:
|
|
1783
|
+
the same bot-wide `retry_after` gate drops a draft while it is closed, and a
|
|
1784
|
+
draft answered with `retry_after` closes it. A closed gate drops a preview,
|
|
1785
|
+
never a durable delivery.
|
|
1353
1786
|
|
|
1354
1787
|
Each serve run first asks House to settle the attempts an earlier run abandoned,
|
|
1355
1788
|
so a restarted gateway never leaves a delivery attempted forever. A Telegram
|
|
@@ -1357,11 +1790,14 @@ so a restarted gateway never leaves a delivery attempted forever. A Telegram
|
|
|
1357
1790
|
the delay Telegram supplied has passed. `--passes <count>` bounds each activity
|
|
1358
1791
|
to that many passes and is what tests and one-shot runs use; without it the
|
|
1359
1792
|
command is resident and stops on SIGINT or SIGTERM, printing what it settled.
|
|
1793
|
+
Each refused pass is printed as it happens, naming its activity, item and
|
|
1794
|
+
refusal code, so a gateway refused on every pass says so while it runs; the
|
|
1795
|
+
summary printed when it stops still lists each of them.
|
|
1360
1796
|
|
|
1361
1797
|
Release the bot:
|
|
1362
1798
|
|
|
1363
1799
|
```sh
|
|
1364
|
-
kit telegram disconnect
|
|
1800
|
+
kit telegram disconnect
|
|
1365
1801
|
```
|
|
1366
1802
|
|
|
1367
1803
|
The command writes a local disconnect marker first, deletes the webhook, removes
|
|
@@ -1386,11 +1822,22 @@ $HOUSE_KIT_HOME/
|
|
|
1386
1822
|
state/repositories/<repository identity>.json
|
|
1387
1823
|
state/sync/<replica identity>.json
|
|
1388
1824
|
state/sync/<replica identity>.pending.json
|
|
1825
|
+
state/working-copies/rooms/<room ref>.json
|
|
1826
|
+
state/working-copies/private.json
|
|
1389
1827
|
state/attachments/<upload identity>.json
|
|
1390
1828
|
state/conversation-originals/<attachment identity>.json
|
|
1391
1829
|
state/sessions/<tmux session>.json
|
|
1830
|
+
state/update-drain
|
|
1831
|
+
state/skill-set.json
|
|
1832
|
+
state/how-we-work
|
|
1392
1833
|
state/continuations/<run identity>.json
|
|
1393
|
-
state
|
|
1834
|
+
state/google/entries/<source>.json
|
|
1835
|
+
state/google/credentials/<account>.json
|
|
1836
|
+
state/google/checkpoints/<source>.json
|
|
1837
|
+
state/google/health/<source>.json
|
|
1838
|
+
state/google/gaps/<source>.json
|
|
1839
|
+
state/google/dropped/<source>.json
|
|
1840
|
+
state/google/originals/<source>.json
|
|
1394
1841
|
state/<instance>/checkpoints/<service>.json
|
|
1395
1842
|
state/<instance>/health/<service>.json
|
|
1396
1843
|
state/<instance>/gaps/<service>.json
|
|
@@ -1400,15 +1847,18 @@ $HOUSE_KIT_HOME/
|
|
|
1400
1847
|
|
|
1401
1848
|
Every file is written atomically and readable only by its owner. A file the Kit
|
|
1402
1849
|
cannot read is refused rather than treated as a service that never captured.
|
|
1403
|
-
|
|
1404
|
-
|
|
1850
|
+
A Google entry's state is keyed by its Source reference and lives only while
|
|
1851
|
+
House lists the entry. Disabling a custom service or instance leaves its state
|
|
1852
|
+
in place, so re-enabling resumes from the stored cursor instead of importing
|
|
1853
|
+
again.
|
|
1405
1854
|
|
|
1406
1855
|
```sh
|
|
1407
|
-
kit source reset acme
|
|
1408
|
-
kit source reset acme notes
|
|
1856
|
+
kit source reset acme # every service
|
|
1857
|
+
kit source reset acme notes # one service
|
|
1409
1858
|
```
|
|
1410
1859
|
|
|
1411
|
-
Reset is the only deletion of captured
|
|
1860
|
+
Reset serves custom connectors, and is the only deletion of their captured
|
|
1861
|
+
state. It removes the named checkpoints
|
|
1412
1862
|
and their outstanding retained references so the next capture restarts exactly at
|
|
1413
1863
|
the configured backfill boundary. It takes the same
|
|
1414
1864
|
Environment control lease a capture takes, so it cannot delete a checkpoint a
|
|
@@ -1442,7 +1892,7 @@ refused rather than read as no limit. A ceiling is a shared ceiling, never a
|
|
|
1442
1892
|
reservation, and House infers no supported Agent count from any of these values.
|
|
1443
1893
|
|
|
1444
1894
|
```sh
|
|
1445
|
-
kit host report
|
|
1895
|
+
kit host report
|
|
1446
1896
|
```
|
|
1447
1897
|
|
|
1448
1898
|
The command reads `/proc/stat` twice a second apart, reads `/proc/meminfo`, and
|
|
@@ -1464,7 +1914,7 @@ Description=Report measured host capacity to House
|
|
|
1464
1914
|
[Service]
|
|
1465
1915
|
Type=oneshot
|
|
1466
1916
|
User=house-kit
|
|
1467
|
-
ExecStart=/usr/bin/kit host report
|
|
1917
|
+
ExecStart=/usr/bin/kit host report
|
|
1468
1918
|
```
|
|
1469
1919
|
|
|
1470
1920
|
```
|
|
@@ -1513,11 +1963,10 @@ manifest, URLs, or attachments.
|
|
|
1513
1963
|
|
|
1514
1964
|
```sh
|
|
1515
1965
|
kit migrate emit my-import --package /home/ada/exports/project
|
|
1516
|
-
kit migrate mount /home/ada/exports/project --
|
|
1517
|
-
--subtree /rooms/work/library/project
|
|
1966
|
+
kit migrate mount /home/ada/exports/project --subtree /rooms/work/library/project
|
|
1518
1967
|
# Or emit and mount in one maintained mount session:
|
|
1519
1968
|
kit migrate run my-import --package /home/ada/exports/another-project \
|
|
1520
|
-
--
|
|
1969
|
+
--subtree /private/library/another-project
|
|
1521
1970
|
```
|
|
1522
1971
|
|
|
1523
1972
|
Emission refuses an existing output directory. The module reads one JSON line
|
|
@@ -1583,7 +2032,7 @@ prepared model definitions survive a later content-mount refusal or unmount.
|
|
|
1583
2032
|
|
|
1584
2033
|
The atomic text mount includes a report with pending transfer rows. Kit then
|
|
1585
2034
|
uploads each downloaded file once as an attachment to the mount's Room or
|
|
1586
|
-
|
|
2035
|
+
Private Room, independently retrieves and compares the saved bytes, and only
|
|
1587
2036
|
after that proof succeeds rewrites every link to it, in every referring
|
|
1588
2037
|
document, to its attachment reference, such as `at_1x.q`. The reference is an
|
|
1589
2038
|
identity House resolves, not an HTTP download URL. A link's query and fragment
|
|
@@ -1604,8 +2053,8 @@ leaves the pending mounted report plus the local outcomes. Re-migration is
|
|
|
1604
2053
|
explicit unmount followed by mount.
|
|
1605
2054
|
|
|
1606
2055
|
```sh
|
|
1607
|
-
kit migrate unmount /rooms/work/library/project
|
|
1608
|
-
kit migrate unmount /rooms/work/library/project
|
|
2056
|
+
kit migrate unmount /rooms/work/library/project
|
|
2057
|
+
kit migrate unmount /rooms/work/library/project \
|
|
1609
2058
|
--confirm /rooms/work/library/project
|
|
1610
2059
|
```
|
|
1611
2060
|
|
|
@@ -1629,10 +2078,7 @@ workspaces.
|
|
|
1629
2078
|
```sh
|
|
1630
2079
|
docker compose -f test/compose.yaml build kit
|
|
1631
2080
|
docker compose -f test/compose.yaml run --rm kit npm test
|
|
1632
|
-
docker compose -f test/compose.yaml run --rm
|
|
1633
|
-
-e HOUSE_KIT_GOOGLE_OAUTH_CLIENT_ID=kit-client.apps.googleusercontent.com \
|
|
1634
|
-
-e HOUSE_KIT_GOOGLE_OAUTH_CLIENT_SECRET=GOCSPX-kit-installed-app \
|
|
1635
|
-
kit npm run build
|
|
2081
|
+
docker compose -f test/compose.yaml run --rm kit npm run build
|
|
1636
2082
|
```
|
|
1637
2083
|
|
|
1638
2084
|
`test/pair/run.sh` boots real Core, Auth and PostgreSQL and runs the installed
|
|
@@ -1662,6 +2108,19 @@ the previous control lease before starting the next isolated command. Evidence
|
|
|
1662
2108
|
is written to `tmp/delivery-evidence/migrator-pair.json` with producer revisions
|
|
1663
2109
|
and the installed package digest.
|
|
1664
2110
|
|
|
2111
|
+
Explicit sync has its own paired proof:
|
|
2112
|
+
|
|
2113
|
+
```sh
|
|
2114
|
+
HOUSE_CORE_ROOT=<core checkout> HOUSE_AUTH_ROOT=<auth checkout> \
|
|
2115
|
+
KIT_PAIR_SPECS=/kit/test/pair/sync.vitest.ts bash test/pair/run.sh
|
|
2116
|
+
```
|
|
2117
|
+
|
|
2118
|
+
It proves that an accepted `submit`, answered or recovered after a lost answer,
|
|
2119
|
+
leaves each file's `_provenance` sidecar equal to the provenance House serves,
|
|
2120
|
+
and that a pending submission House answers `operation_expired` is pulled first,
|
|
2121
|
+
then sent again under a new identifier only if it never landed. Evidence is
|
|
2122
|
+
written to `tmp/delivery-evidence/sync-pair.json`.
|
|
2123
|
+
|
|
1665
2124
|
The retained-original consumers have their own paired proofs:
|
|
1666
2125
|
|
|
1667
2126
|
```sh
|