owlrunkit 0.25.0 → 0.25.2
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/CHANGELOG.md +21 -0
- package/NOTICE.md +17 -132
- package/README.md +35 -21
- package/SOURCE.md +6 -2
- package/docs/architecture/OWLCODA_RUNKIT_USAGE_MODE_SELECTION_PRODUCT_DECISION_20260811.md +1 -1
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +15 -13
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
- package/package.json +1 -1
- package/packages/attest/distribution-manifest-v1.json +10 -0
- package/packages/attest/src/quick.mjs +10 -0
- package/registry-release-policy-v2.json +5 -5
- package/sbom.spdx.json +4 -4
- package/scripts/runkit-contract/control-transaction-lock.mjs +108 -0
- package/scripts/runkit-contract/core-contract.mjs +5 -1
- package/scripts/runkit-contract/lease-lifecycle.mjs +14 -21
- package/scripts/runkit-contract/linux-runtime.mjs +13 -0
- package/scripts/runkit-contract/peer-linux-arm64 +0 -0
- package/scripts/runkit-contract/peer-linux-bwrap.mjs +109 -0
- package/scripts/runkit-contract/peer-linux-x64 +0 -0
- package/scripts/runkit-contract/peer-linux.MUSL-COPYRIGHT +193 -0
- package/scripts/runkit-contract/peer-linux.c +276 -0
- package/scripts/runkit-contract/peer-recovery.mjs +88 -15
- package/scripts/runkit-contract/project-cli-resolver.mjs +8 -0
- package/scripts/runkit-contract/resume-execution.mjs +2 -8
- package/scripts/runkit-contract/runkit-cli.mjs +8 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.25.2
|
|
4
|
+
|
|
5
|
+
- Supports managed Linux worker recovery with system Bubblewrap when Landlock
|
|
6
|
+
is unavailable. RunKit verifies the writable attempt, read-only sandbox
|
|
7
|
+
root, hidden host files, and seccomp process and network restrictions before
|
|
8
|
+
selecting the backend.
|
|
9
|
+
- Keeps Landlock as the first Linux backend. If neither backend passes its
|
|
10
|
+
runtime probe, managed peer commands refuse to start.
|
|
11
|
+
|
|
12
|
+
## 0.25.1
|
|
13
|
+
|
|
14
|
+
- Adds enforced Linux peer isolation for x86-64 and ARM64 with Landlock and
|
|
15
|
+
seccomp. The helper verifies kernel support before managed tasks start.
|
|
16
|
+
- A cooperating agent can attach its worker command to `peer recover`.
|
|
17
|
+
A confirmed wake preserves the current owner. After takeover, exactly one
|
|
18
|
+
invocation starts the successor from the last accepted checkpoint.
|
|
19
|
+
- On Linux, control transactions use an OS lock that is released on process
|
|
20
|
+
exit. The next transaction verifies interrupted state before proceeding.
|
|
21
|
+
Partial multi-file changes and ownerless directory locks still require
|
|
22
|
+
reconciliation. Legacy shared-directory worker leases remain explicit.
|
|
23
|
+
|
|
3
24
|
## 0.25.0
|
|
4
25
|
|
|
5
26
|
- Adds opt-in same-host peer recovery for macOS-contained workers. A cooperating
|
package/NOTICE.md
CHANGED
|
@@ -1,137 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# OwlRunKit Notice
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
OwlRunKit is an independent package in the OwlCoda product family. It is not
|
|
4
|
+
affiliated with any model vendor, coding-agent vendor, or hosted agent service.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
The OwlRunKit CLI, Core, contracts, and attestation package are distributed
|
|
7
|
+
under `GPL-3.0-or-later`; see [`LICENSE`](LICENSE). The published package uses
|
|
8
|
+
Node.js built-in modules and currently declares no runtime npm dependencies.
|
|
9
|
+
Files carrying their own license or provenance notice retain those terms.
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
examples, and public release documents. Bundled skills and third-party-derived
|
|
13
|
-
resources keep their own license files and provenance records where applicable.
|
|
11
|
+
Product and provider names may appear only where needed for interoperability,
|
|
12
|
+
portable integration guidance, compatibility history, or evidence captured by
|
|
13
|
+
the user. Such references do not imply endorsement, sponsorship, or
|
|
14
|
+
affiliation.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
those dependencies and does not override the OwlCoda project license.
|
|
16
|
+
OwlRunKit records delivery continuity and verification evidence. It does not
|
|
17
|
+
grant Git, release, deployment, production, automation, money, or business
|
|
18
|
+
authority, and it does not become the Business Truth of a domain product.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- Protocol translation layer (messages API ↔ OpenAI Chat Completions)
|
|
24
|
-
- Local model platform integration (Ollama, LM Studio, vLLM)
|
|
25
|
-
- Native REPL, tool orchestration, and session workflows
|
|
26
|
-
- Production infrastructure (health monitoring, rate limiting, circuit breakers)
|
|
27
|
-
- Extended REPL commands and observability
|
|
28
|
-
|
|
29
|
-
### What OwlCoda Does NOT Provide
|
|
30
|
-
|
|
31
|
-
OwlCoda does not claim to be any third-party coding assistant, does not ship a
|
|
32
|
-
third-party branded UI, and does not rely on an external vendor CLI as its
|
|
33
|
-
primary product surface.
|
|
34
|
-
|
|
35
|
-
### Protocol Interoperability vs Affiliation
|
|
36
|
-
|
|
37
|
-
OwlCoda implements two widely-deployed wire formats so that users can
|
|
38
|
-
plug their existing local runtime into it without rewriting the
|
|
39
|
-
runtime:
|
|
40
|
-
|
|
41
|
-
1. The Messages-shaped API (originated by Anthropic and now implemented
|
|
42
|
-
by many independent open-source servers) — incoming `/v1/messages`
|
|
43
|
-
requests are accepted in this shape and translated as needed.
|
|
44
|
-
2. The OpenAI Chat Completions wire format — outgoing requests to
|
|
45
|
-
user-configured backends use this shape because most local
|
|
46
|
-
inference runtimes (Ollama, LM Studio, vLLM, etc.) expose it.
|
|
47
|
-
|
|
48
|
-
Implementing these wire formats is a technical interoperability
|
|
49
|
-
choice, not a brand affiliation. Where the codebase contains the
|
|
50
|
-
literal strings `Anthropic`, `Anthropic-compatible`,
|
|
51
|
-
`anthropic-version`, `/v1/messages`, or imports the public
|
|
52
|
-
`@anthropic-ai/sdk` package, those references are protocol-level,
|
|
53
|
-
exist solely to maintain over-the-wire compatibility, and do not
|
|
54
|
-
constitute or imply:
|
|
55
|
-
|
|
56
|
-
- endorsement by, or sponsorship from, Anthropic, OpenAI, or any
|
|
57
|
-
other third party;
|
|
58
|
-
- any affiliation, partnership, or contractual relationship with
|
|
59
|
-
those parties; or
|
|
60
|
-
- a claim that OwlCoda is a substitute for, or a derivative of,
|
|
61
|
-
any third-party product.
|
|
62
|
-
|
|
63
|
-
The `@anthropic-ai/sdk` package is listed as a `devDependency` only
|
|
64
|
-
and is used by `tests/sdk-verify.ts` as an interoperability sanity
|
|
65
|
-
check against OwlCoda's own server implementation. It is not loaded
|
|
66
|
-
by the OwlCoda runtime.
|
|
67
|
-
|
|
68
|
-
## Third-Party Source Attributions
|
|
69
|
-
|
|
70
|
-
OwlCoda incorporates source code derived from the following third-party
|
|
71
|
-
projects. Their original copyright notices and MIT permission text are
|
|
72
|
-
reproduced below as required by their licenses.
|
|
73
|
-
|
|
74
|
-
### Ink (https://github.com/vadimdemedes/ink)
|
|
75
|
-
|
|
76
|
-
The `src/ink/` directory contains a fork of the Ink terminal-UI library
|
|
77
|
-
originally authored by Vadim Demedes. OwlCoda's fork extends Ink with
|
|
78
|
-
ScrollBox / viewport-culling / sticky-scroll primitives needed by the
|
|
79
|
-
native REPL, but the underlying reconciler, layout, renderer, DOM, event,
|
|
80
|
-
and component code remain derivative of upstream Ink.
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
MIT License
|
|
84
|
-
|
|
85
|
-
Copyright (c) Vadim Demedes <vadimdemedes@hey.com> (vadimdemedes.com)
|
|
86
|
-
|
|
87
|
-
Permission is hereby granted, free of charge, to any person obtaining a
|
|
88
|
-
copy of this software and associated documentation files (the "Software"),
|
|
89
|
-
to deal in the Software without restriction, including without limitation
|
|
90
|
-
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
91
|
-
and/or sell copies of the Software, and to permit persons to whom the
|
|
92
|
-
Software is furnished to do so, subject to the following conditions:
|
|
93
|
-
|
|
94
|
-
The above copyright notice and this permission notice shall be included
|
|
95
|
-
in all copies or substantial portions of the Software.
|
|
96
|
-
|
|
97
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
98
|
-
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
99
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
100
|
-
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
101
|
-
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
102
|
-
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
103
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
A copy of this attribution also lives at `src/ink/ATTRIBUTION.md` so it
|
|
107
|
-
travels with the fork in any redistribution.
|
|
108
|
-
|
|
109
|
-
### Direct Runtime Dependencies
|
|
110
|
-
|
|
111
|
-
OwlCoda's published tarball ships only `dist/`; runtime dependencies are
|
|
112
|
-
resolved by `npm install` and their full license texts are available
|
|
113
|
-
under `node_modules/<pkg>/LICENSE` after install. The list below is
|
|
114
|
-
provided for transparency; it does not replace the per-package license
|
|
115
|
-
files that npm fetches automatically.
|
|
116
|
-
|
|
117
|
-
For GPL-covered npm packages, corresponding source availability is documented
|
|
118
|
-
in `SOURCE.md`. Dependency-license review for GPLv3 compatibility is a release
|
|
119
|
-
gate distinct from the older "does this project depend on GPL code?" check.
|
|
120
|
-
|
|
121
|
-
| Package | License |
|
|
122
|
-
|---|---|
|
|
123
|
-
| `@anthropic-ai/sdk` (devDependency, type-only import + verify script) | MIT |
|
|
124
|
-
| `@commander-js/extra-typings` | MIT |
|
|
125
|
-
| `@growthbook/growthbook` | MIT |
|
|
126
|
-
| `@modelcontextprotocol/sdk` | MIT |
|
|
127
|
-
| `@opentelemetry/*` (api, core, sdk-logs, sdk-metrics, sdk-trace-base, resources, api-logs, semantic-conventions) | Apache-2.0 |
|
|
128
|
-
| `axios`, `chalk`, `chokidar`, `marked`, `react`, `react-reconciler`, `ws`, `zod`, `undici`, `execa`, `turndown`, `xss`, `yaml`, others | MIT |
|
|
129
|
-
| `cacache`, `cli-highlight`, `semver`, `signal-exit`, `yaml` | ISC |
|
|
130
|
-
| `diff` | BSD-3-Clause |
|
|
131
|
-
| `lru-cache` | BlueOak-1.0.0 |
|
|
132
|
-
| `ink` (npm — co-installed alongside the in-tree fork in `src/ink/`) | MIT (Vadim Demedes) |
|
|
133
|
-
|
|
134
|
-
No GPL / AGPL / SSPL / Business Source / Commons Clause / Elastic License
|
|
135
|
-
dependencies are present in the current transitive graph (verified via
|
|
136
|
-
`npm ls --all`). That is a dependency fact, not a statement about OwlCoda's own
|
|
137
|
-
project license.
|
|
20
|
+
The Linux helper binaries statically link musl. See
|
|
21
|
+
[`peer-linux.MUSL-COPYRIGHT`](scripts/runkit-contract/peer-linux.MUSL-COPYRIGHT)
|
|
22
|
+
for its copyright and license notices.
|
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ separate authority boundaries.
|
|
|
136
136
|
|
|
137
137
|
## Install
|
|
138
138
|
|
|
139
|
-
This package is the lifecycle-stable, registry-gated `owlrunkit@0.25.
|
|
139
|
+
This package is the lifecycle-stable, registry-gated `owlrunkit@0.25.2`
|
|
140
140
|
artifact. Registry adoption remains fail-closed until its exact official npm
|
|
141
141
|
version, shasum, integrity, and tarball URL are independently verified. Local
|
|
142
142
|
tarballs remain candidate-test inputs and are never adoption provenance. Until
|
|
@@ -144,7 +144,7 @@ that registry evidence exists, use the package only for isolated candidate
|
|
|
144
144
|
verification; do not treat the command below as available release truth.
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
|
-
npm install --save-exact owlrunkit@0.25.
|
|
147
|
+
npm install --save-exact owlrunkit@0.25.2
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
Use `npx --no-install owlrunkit` for project commands. The package bootstrap
|
|
@@ -160,9 +160,9 @@ the project Config must independently bind the same Core.
|
|
|
160
160
|
```bash
|
|
161
161
|
npx --no-install owlrunkit --version
|
|
162
162
|
npx --no-install owlrunkit bootstrap --workspace /absolute/path/to/project \
|
|
163
|
-
--exact owlrunkit@0.25.
|
|
163
|
+
--exact owlrunkit@0.25.2 --dry-run
|
|
164
164
|
npx --no-install owlrunkit bootstrap --workspace /absolute/path/to/project \
|
|
165
|
-
--exact owlrunkit@0.25.
|
|
165
|
+
--exact owlrunkit@0.25.2 --apply
|
|
166
166
|
npx --no-install owlrunkit init --workspace /absolute/path/to/project
|
|
167
167
|
npx --no-install owlrunkit doctor --workspace /absolute/path/to/project
|
|
168
168
|
npx --no-install owlrunkit inspect --workspace /absolute/path/to/project --json --compact
|
|
@@ -997,9 +997,9 @@ continuation; fully idle Desktop wake requires a separate supported ingress.
|
|
|
997
997
|
|
|
998
998
|
## Managed local peer recovery
|
|
999
999
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1000
|
+
Opt a new task into peer recovery before starting its writer. The project
|
|
1001
|
+
controller names the current agent, successor, and exact checkpoint paths in
|
|
1002
|
+
`peer.json`, for example:
|
|
1003
1003
|
|
|
1004
1004
|
```json
|
|
1005
1005
|
{"owner":"alpha","successor":"bravo","paths":["result.txt"]}
|
|
@@ -1009,18 +1009,21 @@ paths in `peer.json`, for example:
|
|
|
1009
1009
|
npx --no-install owlrunkit peer create --workspace . --task repair --request peer.json
|
|
1010
1010
|
npx --no-install owlrunkit peer run --workspace . --task repair --agent alpha --generation 1 -- /absolute/worker
|
|
1011
1011
|
npx --no-install owlrunkit peer inspect --workspace . --task repair
|
|
1012
|
-
npx --no-install owlrunkit peer recover --workspace . --task repair --agent bravo --generation 1 --revision 2
|
|
1012
|
+
npx --no-install owlrunkit peer recover --workspace . --task repair --agent bravo --generation 1 --revision 2 -- /absolute/successor-worker
|
|
1013
1013
|
```
|
|
1014
1014
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1015
|
+
The cooperating agent uses the last two commands when it observes an
|
|
1016
|
+
interruption and has authority to run the successor worker. Use the generation
|
|
1017
|
+
and revision returned by `inspect`.
|
|
1017
1018
|
Recovery requests a wake from the current worker. A matching, changed checkpoint
|
|
1018
1019
|
keeps that worker in charge. If wake remains unconfirmed after the bounded wait,
|
|
1019
1020
|
recovery can move ownership to the designated successor because the current
|
|
1020
1021
|
attempt already runs in an isolated directory. One durable revision binds the
|
|
1021
|
-
successor generation to the last accepted checkpoint.
|
|
1022
|
-
|
|
1023
|
-
|
|
1022
|
+
successor generation to the last accepted checkpoint. With a worker command
|
|
1023
|
+
after `--`, recovery starts that worker after takeover and reports its result.
|
|
1024
|
+
A concurrent retry may report the already-started attempt. Without a command,
|
|
1025
|
+
the successor starts its own worker with `peer run`. An ACK or timeout does
|
|
1026
|
+
not prove worker death. Retry the observed revision to read back the handoff.
|
|
1024
1027
|
|
|
1025
1028
|
Use a local worker that speaks newline-delimited JSON. RunKit seeds the attempt
|
|
1026
1029
|
directory from the previous checkpoint and sets `OWLRUNKIT_PEER_PATHS` to the
|
|
@@ -1035,14 +1038,25 @@ go to stderr. `inspect` returns the checkpoint path and hash for handoff and
|
|
|
1035
1038
|
review. Only accepted checkpoints seed the next attempt, and the previous
|
|
1036
1039
|
scratch directory is reported for inspection while it remains on disk.
|
|
1037
1040
|
|
|
1038
|
-
The macOS
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1041
|
+
The macOS and Linux backends confine writes to the attempt and deny network
|
|
1042
|
+
connections and new worker processes. Linux supports x86-64 and ARM64 with
|
|
1043
|
+
seccomp filtering and `close_range`. RunKit tries Landlock ABI 3 or later
|
|
1044
|
+
first. If Landlock is unavailable, it can use a trusted system Bubblewrap
|
|
1045
|
+
executable with user and mount namespaces. The Bubblewrap probe verifies
|
|
1046
|
+
that the attempt is writable, host files are hidden, and new processes and
|
|
1047
|
+
network sockets are denied. If the probe fails, the task stays blocked.
|
|
1048
|
+
On Linux, the worker is terminated if its supervisor is killed. The host
|
|
1049
|
+
caller supplies the worker command and peer identity. Existing Desktop sessions and writers using
|
|
1050
|
+
legacy shared-directory leases follow their own recovery procedure. An
|
|
1051
|
+
existing managed task remains pinned to the core that created it.
|
|
1052
|
+
|
|
1053
|
+
Linux control transactions use a kernel lock and a marker in the runtime
|
|
1054
|
+
directory. If the process exits during an atomic lease operation, the next
|
|
1055
|
+
transaction reads the lease state from the committed artifact. For other
|
|
1056
|
+
transactions, automatic recovery requires unchanged control state. A partial
|
|
1057
|
+
transaction returns `runkit_control_reconciliation_required` and preserves its
|
|
1058
|
+
state. An older `control.lock` directory has no kernel ownership record and
|
|
1059
|
+
requires the existing explicit recovery procedure.
|
|
1046
1060
|
|
|
1047
1061
|
## Shared Skill upgrades
|
|
1048
1062
|
|
package/SOURCE.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Source
|
|
2
2
|
|
|
3
3
|
OwlRunKit is maintained in the private OwlCoda source repository. The npm
|
|
4
|
-
tarball contains the
|
|
5
|
-
|
|
4
|
+
tarball contains the JavaScript runtime, the read-only verifier and the C
|
|
5
|
+
source for the two Linux helper binaries. The distributed binaries link musl
|
|
6
|
+
statically and include its copyright notice. Build the helper on each supported
|
|
7
|
+
Linux architecture with `sh packages/runkit/build-linux-helper.sh <output>`
|
|
8
|
+
in Alpine Linux with `build-base` and `linux-headers`, then pass their output directory to
|
|
9
|
+
`packages/runkit/build-package.mjs --linux-helpers`.
|
|
6
10
|
|
|
7
11
|
The authoritative release is identified by the npm registry version, shasum,
|
|
8
12
|
integrity, and tarball URL. Local directories, `file:` dependencies, local
|
|
@@ -7,14 +7,14 @@ description: Run receipt-backed, project-owned work with OwlCoda RunKit. Use whe
|
|
|
7
7
|
|
|
8
8
|
Use the bundled deterministic Core to coordinate work through project artifacts rather than chat memory. Require Node.js 20 or later.
|
|
9
9
|
|
|
10
|
-
Bundled registry-gated artifact: standalone `owlrunkit@0.25.
|
|
11
|
-
`0.2` and Core `0.25.
|
|
12
|
-
`sha256:
|
|
10
|
+
Bundled registry-gated artifact: standalone `owlrunkit@0.25.2`, bundling Contract
|
|
11
|
+
`0.2` and Core `0.25.2` with manifest
|
|
12
|
+
`sha256:da816d343597b91c30e4f96c0a3d765bf5c00d6013d6bee430f58bc701399acc`.
|
|
13
13
|
Registry adoption remains fail-closed until exact official npm registry
|
|
14
|
-
provenance for `owlrunkit@0.25.
|
|
15
|
-
published rollback baseline for this artifact is `owlrunkit@0.
|
|
16
|
-
`
|
|
17
|
-
`https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.
|
|
14
|
+
provenance for `owlrunkit@0.25.2` is independently verified. The
|
|
15
|
+
published rollback baseline for this artifact is `owlrunkit@0.25.1`, with SHA-1
|
|
16
|
+
`755bdcef5f6df55977ee64d2d4391d1098c00168` and canonical npm tarball URL
|
|
17
|
+
`https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.25.1.tgz`.
|
|
18
18
|
The root `owlcoda` package has a separate version lifecycle.
|
|
19
19
|
|
|
20
20
|
The session is an execution interface. Project artifacts are the system of record.
|
|
@@ -25,10 +25,12 @@ For a task already enrolled in `owlrunkit peer` with an isolated worker, inspect
|
|
|
25
25
|
the task when your cooperating agent stops progressing. As the designated
|
|
26
26
|
successor, run `peer recover` with the observed generation and revision. A
|
|
27
27
|
new checkpoint tied to the wake challenge keeps the original agent active.
|
|
28
|
-
|
|
29
|
-
worker
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
Append `-- /absolute/worker` when you already have authority to run the
|
|
29
|
+
successor worker. The command only launches it if ownership transfers and
|
|
30
|
+
seeds it from the last accepted checkpoint. Read the returned attempt status
|
|
31
|
+
before treating the work as finished. Treat an ACK without progress as
|
|
32
|
+
unconfirmed. Keep legacy shared-workspace leases on the manual recovery path.
|
|
33
|
+
Use the package README and `peer --help` for setup.
|
|
32
34
|
|
|
33
35
|
## Optional file-event continuation
|
|
34
36
|
|
|
@@ -368,9 +370,9 @@ below has no CLI entry.
|
|
|
368
370
|
|
|
369
371
|
```bash
|
|
370
372
|
npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
|
|
371
|
-
--exact owlrunkit@0.25.
|
|
373
|
+
--exact owlrunkit@0.25.2 --dry-run
|
|
372
374
|
npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
|
|
373
|
-
--exact owlrunkit@0.25.
|
|
375
|
+
--exact owlrunkit@0.25.2 --apply
|
|
374
376
|
npx --no-install owlrunkit init --workspace "$PROJECT_ROOT"
|
|
375
377
|
npx --no-install owlrunkit inspect --json --workspace "$PROJECT_ROOT"
|
|
376
378
|
npx --no-install owlrunkit inspect --json --compact --workspace "$PROJECT_ROOT"
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schemaVersion": "OwlCodaRunKitConfigV2",
|
|
3
3
|
"core": {
|
|
4
4
|
"contractVersion": "0.2",
|
|
5
|
-
"coreVersion": "0.25.
|
|
6
|
-
"coreManifestSha256": "sha256:
|
|
7
|
-
"coreSourceRef": "artifact:sha256:
|
|
5
|
+
"coreVersion": "0.25.2",
|
|
6
|
+
"coreManifestSha256": "sha256:da816d343597b91c30e4f96c0a3d765bf5c00d6013d6bee430f58bc701399acc",
|
|
7
|
+
"coreSourceRef": "artifact:sha256:da816d343597b91c30e4f96c0a3d765bf5c00d6013d6bee430f58bc701399acc"
|
|
8
8
|
},
|
|
9
9
|
"authorizationPolicy": "external_explicit_authority_required"
|
|
10
10
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "owlrunkit",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.2",
|
|
4
4
|
"description": "Project Driver for cross-Agent project continuity and progression; execution, evidence, verification, and recovery are the underlying trust substrate.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"author": "yeemio <owlclaw@163.com>",
|
|
@@ -42,6 +42,16 @@
|
|
|
42
42
|
"sha256": "sha256:3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986"
|
|
43
43
|
},
|
|
44
44
|
"supportedProducerCoreIdentities": [
|
|
45
|
+
{
|
|
46
|
+
"contractVersion": "0.2",
|
|
47
|
+
"coreVersion": "0.25.2",
|
|
48
|
+
"coreManifestSha256": "sha256:da816d343597b91c30e4f96c0a3d765bf5c00d6013d6bee430f58bc701399acc"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"contractVersion": "0.2",
|
|
52
|
+
"coreVersion": "0.25.1",
|
|
53
|
+
"coreManifestSha256": "sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5"
|
|
54
|
+
},
|
|
45
55
|
{
|
|
46
56
|
"contractVersion": "0.2",
|
|
47
57
|
"coreVersion": "0.25.0",
|
|
@@ -23,6 +23,16 @@ import {
|
|
|
23
23
|
export { validQuickReceiptShape } from "./quick-receipt-contract.mjs";
|
|
24
24
|
|
|
25
25
|
export const SUPPORTED_QUICK_CORE_IDENTITIES = Object.freeze([
|
|
26
|
+
{
|
|
27
|
+
contractVersion: "0.2",
|
|
28
|
+
coreVersion: "0.25.2",
|
|
29
|
+
coreManifestSha256: "sha256:da816d343597b91c30e4f96c0a3d765bf5c00d6013d6bee430f58bc701399acc",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
contractVersion: "0.2",
|
|
33
|
+
coreVersion: "0.25.1",
|
|
34
|
+
coreManifestSha256: "sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5",
|
|
35
|
+
},
|
|
26
36
|
{
|
|
27
37
|
contractVersion: "0.2",
|
|
28
38
|
coreVersion: "0.25.0",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": "OwlCodaRunKitRegistryReleasePolicyV2",
|
|
3
3
|
"status": "release_artifact_registry_gated",
|
|
4
4
|
"packageName": "owlrunkit",
|
|
5
|
-
"artifactVersion": "0.25.
|
|
5
|
+
"artifactVersion": "0.25.2",
|
|
6
6
|
"registry": "https://registry.npmjs.org",
|
|
7
7
|
"registryRequiredBeforeAdoption": true,
|
|
8
8
|
"exactVersionRequired": true,
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
],
|
|
24
24
|
"rollbackRelease": {
|
|
25
25
|
"packageName": "owlrunkit",
|
|
26
|
-
"version": "0.
|
|
27
|
-
"shasum": "
|
|
28
|
-
"integrity": "sha512
|
|
29
|
-
"tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.
|
|
26
|
+
"version": "0.25.1",
|
|
27
|
+
"shasum": "755bdcef5f6df55977ee64d2d4391d1098c00168",
|
|
28
|
+
"integrity": "sha512-+s+PHZXemJIgBo8ScT65+OngqniojRFMxpoUOTjp/Xkq/szB8FqEUOH1BFlokMz6dx64FSOKb30rDPZWC2lS4w==",
|
|
29
|
+
"tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.25.1.tgz"
|
|
30
30
|
},
|
|
31
31
|
"registryEvidenceMustBeExternal": true,
|
|
32
32
|
"registryEvidenceSchemaVersion": "OwlCodaRunKitRegistryReleaseEvidenceV1",
|
package/sbom.spdx.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"spdxVersion": "SPDX-2.3",
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
|
-
"name": "owlrunkit-0.25.
|
|
6
|
-
"documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.25.
|
|
5
|
+
"name": "owlrunkit-0.25.2",
|
|
6
|
+
"documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.25.2",
|
|
7
7
|
"creationInfo": {
|
|
8
8
|
"created": "2026-11-11T00:00:00Z",
|
|
9
9
|
"creators": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"name": "owlrunkit",
|
|
16
16
|
"SPDXID": "SPDXRef-Package-OwlRunKit",
|
|
17
|
-
"versionInfo": "0.25.
|
|
17
|
+
"versionInfo": "0.25.2",
|
|
18
18
|
"downloadLocation": "NOASSERTION",
|
|
19
19
|
"filesAnalyzed": false,
|
|
20
20
|
"licenseConcluded": "GPL-3.0-or-later",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
{
|
|
25
25
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
26
26
|
"referenceType": "purl",
|
|
27
|
-
"referenceLocator": "pkg:npm/owlrunkit@0.25.
|
|
27
|
+
"referenceLocator": "pkg:npm/owlrunkit@0.25.2"
|
|
28
28
|
}
|
|
29
29
|
]
|
|
30
30
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
3
|
+
import {
|
|
4
|
+
closeSync, constants, fstatSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync,
|
|
5
|
+
readFileSync, readdirSync, rmdirSync, unlinkSync, writeFileSync,
|
|
6
|
+
} from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
|
|
9
|
+
import { linuxRuntimeHelper } from "./linux-runtime.mjs";
|
|
10
|
+
|
|
11
|
+
const LOCK = "control.lock";
|
|
12
|
+
const GUARD = "control.lock.guard";
|
|
13
|
+
const TEMP_PREFIX = ".control-lock-";
|
|
14
|
+
const SCHEMA = "OwlRunKitControlLockV1";
|
|
15
|
+
const ACTIVE = "Another RunKit control transaction is already active.";
|
|
16
|
+
|
|
17
|
+
function fileIdentity(stat) {
|
|
18
|
+
return `${stat.dev}:${stat.ino}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function controlStateDigest(root) {
|
|
22
|
+
const hash = createHash("sha256");
|
|
23
|
+
function visit(directory, prefix) {
|
|
24
|
+
for (const name of readdirSync(directory).sort()) {
|
|
25
|
+
if (!prefix && (name === LOCK || name === GUARD || name === "peer-recovery"
|
|
26
|
+
|| name.startsWith(TEMP_PREFIX))) continue;
|
|
27
|
+
const absolute = path.join(directory, name);
|
|
28
|
+
const relative = `${prefix}${name}`;
|
|
29
|
+
const stat = lstatSync(absolute, { bigint: true });
|
|
30
|
+
hash.update(JSON.stringify([
|
|
31
|
+
relative, fileIdentity(stat), String(stat.mode), String(stat.size),
|
|
32
|
+
String(stat.mtimeNs), String(stat.ctimeNs),
|
|
33
|
+
]) + "\n");
|
|
34
|
+
if (stat.isDirectory()) visit(absolute, `${relative}/`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
visit(root, "");
|
|
38
|
+
return hash.digest("hex");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function recoverInterruptedLock(root, lockPath, guard) {
|
|
42
|
+
let stat;
|
|
43
|
+
try { stat = lstatSync(lockPath); }
|
|
44
|
+
catch (error) { if (error.code === "ENOENT") return; throw error; }
|
|
45
|
+
// Releases without an ownership record still use a directory at this
|
|
46
|
+
// path. Its presence alone cannot establish who owns it or if it is stale.
|
|
47
|
+
if (!stat.isFile() || stat.size > 1024) throw new Error(ACTIVE);
|
|
48
|
+
const fd = openSync(lockPath, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
49
|
+
let previous;
|
|
50
|
+
try { previous = JSON.parse(readFileSync(fd, "utf8")); }
|
|
51
|
+
finally { closeSync(fd); }
|
|
52
|
+
if (previous?.schemaVersion !== SCHEMA || previous.guard !== guard
|
|
53
|
+
|| !["atomic-lease", "control-state"].includes(previous.kind)) throw new Error(ACTIVE);
|
|
54
|
+
if (previous.kind === "control-state" && previous.before !== controlStateDigest(root)) {
|
|
55
|
+
throw new Error("runkit_control_reconciliation_required: interrupted transaction changed control state.");
|
|
56
|
+
}
|
|
57
|
+
unlinkSync(lockPath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function acquireLinuxLock(root, lockPath, helper, kind) {
|
|
61
|
+
const guardPath = path.join(root, GUARD);
|
|
62
|
+
const fd = openSync(guardPath,
|
|
63
|
+
constants.O_RDWR | constants.O_CREAT | constants.O_NOFOLLOW | constants.O_NONBLOCK, 0o600);
|
|
64
|
+
try {
|
|
65
|
+
const guardStat = fstatSync(fd, { bigint: true });
|
|
66
|
+
if (!guardStat.isFile() || guardStat.nlink !== 1n) throw new Error("Invalid RunKit control lock guard.");
|
|
67
|
+
const result = spawnSync(helper, ["lock"], {
|
|
68
|
+
env: {}, timeout: 3000, stdio: ["ignore", "ignore", "pipe", fd], encoding: "utf8",
|
|
69
|
+
});
|
|
70
|
+
if (result.status === 73) throw new Error(ACTIVE);
|
|
71
|
+
if (result.status !== 0) {
|
|
72
|
+
throw new Error(`RunKit control lock unavailable: ${result.stderr?.trim() || result.error?.code}`);
|
|
73
|
+
}
|
|
74
|
+
// The helper locks the open description shared with this process. Keep
|
|
75
|
+
// the descriptor open until the transaction ends or the kernel reaps it.
|
|
76
|
+
const guard = fileIdentity(guardStat);
|
|
77
|
+
if (fileIdentity(lstatSync(guardPath, { bigint: true })) !== guard) {
|
|
78
|
+
throw new Error("RunKit control lock guard was replaced.");
|
|
79
|
+
}
|
|
80
|
+
recoverInterruptedLock(root, lockPath, guard);
|
|
81
|
+
const record = { schemaVersion: SCHEMA, guard, kind,
|
|
82
|
+
before: kind === "control-state" ? controlStateDigest(root) : null };
|
|
83
|
+
const scratch = path.join(root, `${TEMP_PREFIX}${randomUUID()}`);
|
|
84
|
+
const marker = openSync(scratch, "wx", 0o600);
|
|
85
|
+
try {
|
|
86
|
+
writeFileSync(marker, JSON.stringify(record));
|
|
87
|
+
fsyncSync(marker);
|
|
88
|
+
try { linkSync(scratch, lockPath); }
|
|
89
|
+
catch (error) { if (error.code === "EEXIST") throw new Error(ACTIVE); throw error; }
|
|
90
|
+
} finally { closeSync(marker); unlinkSync(scratch); }
|
|
91
|
+
return () => {
|
|
92
|
+
try { unlinkSync(lockPath); }
|
|
93
|
+
finally { closeSync(fd); }
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
closeSync(fd);
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function acquireRunKitControlLock(root, { atomicLease = false } = {}) {
|
|
102
|
+
const lockPath = path.join(root, LOCK);
|
|
103
|
+
const helper = linuxRuntimeHelper();
|
|
104
|
+
if (helper) return acquireLinuxLock(root, lockPath, helper, atomicLease ? "atomic-lease" : "control-state");
|
|
105
|
+
try { mkdirSync(lockPath); }
|
|
106
|
+
catch (error) { if (error.code === "EEXIST") throw new Error(ACTIVE); throw error; }
|
|
107
|
+
return () => rmdirSync(lockPath);
|
|
108
|
+
}
|
|
@@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url";
|
|
|
14
14
|
import { parseProjectControlState } from "./project-control-parser.mjs";
|
|
15
15
|
|
|
16
16
|
export const CONTRACT_VERSION = "0.2";
|
|
17
|
-
export const CORE_VERSION = "0.25.
|
|
17
|
+
export const CORE_VERSION = "0.25.2";
|
|
18
18
|
export const RUNTIME_ROOT = ".owlcoda/runkit";
|
|
19
19
|
|
|
20
20
|
const CORE_FILES = [
|
|
@@ -23,6 +23,7 @@ const CORE_FILES = [
|
|
|
23
23
|
"core-successor.mjs",
|
|
24
24
|
"coverage-adoption.mjs",
|
|
25
25
|
"core-contract.mjs",
|
|
26
|
+
"control-transaction-lock.mjs",
|
|
26
27
|
"delivery-create.mjs",
|
|
27
28
|
"delivery-selection.mjs",
|
|
28
29
|
"deployment-workflow.mjs",
|
|
@@ -40,8 +41,11 @@ const CORE_FILES = [
|
|
|
40
41
|
"install-codex-skill.mjs",
|
|
41
42
|
"lease-lifecycle.mjs",
|
|
42
43
|
"lifecycle-orchestration.mjs",
|
|
44
|
+
"linux-runtime.mjs",
|
|
43
45
|
"offline-store.mjs",
|
|
44
46
|
"outcome-presentation.mjs",
|
|
47
|
+
"peer-linux-bwrap.mjs",
|
|
48
|
+
"peer-linux.c",
|
|
45
49
|
"peer-recovery.mjs",
|
|
46
50
|
"onboarding-doctor.mjs",
|
|
47
51
|
"onboarding-bootstrap.mjs",
|