owlrunkit 0.24.1 → 0.25.1

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 CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.25.1
4
+
5
+ - Adds enforced Linux peer isolation for x86-64 and ARM64 with Landlock and
6
+ seccomp. The helper verifies kernel support before managed tasks start.
7
+ - A cooperating agent can attach its worker command to `peer recover`.
8
+ A confirmed wake preserves the current owner. After takeover, exactly one
9
+ invocation starts the successor from the last accepted checkpoint.
10
+ - On Linux, control transactions use an OS lock that is released on process
11
+ exit. The next transaction verifies interrupted state before proceeding.
12
+ Partial multi-file changes and ownerless directory locks still require
13
+ reconciliation. Legacy shared-directory worker leases remain explicit.
14
+
15
+ ## 0.25.0
16
+
17
+ - Adds opt-in same-host peer recovery for macOS-contained workers. A cooperating
18
+ agent can request a wake, observe a fresh correlated checkpoint, or continue
19
+ from the last checkpoint as the designated successor.
20
+ - Records a single successor generation and rejects writes and checkpoint
21
+ submissions from the superseded attempt. Recovery remains scoped to the
22
+ managed task and preserves the existing manual path for legacy leases.
23
+ - Retains 0.24.1 as the exact published rollback baseline.
24
+
3
25
  ## 0.24.1
4
26
 
5
27
  - Corrects the optional Stop hook to notify on RunKit data file changes, including
@@ -0,0 +1,2 @@
1
+ acbc0a76363cbb81700fdb3e7924c6b1403b30af82dbbda9ad8855a6bb53f988 peer-linux-arm64
2
+ c6a4b270df2482f52ef1463b6ced5205f34c9abda8d4af0a55a1ac3273985436 peer-linux-x64
package/NOTICE.md CHANGED
@@ -1,137 +1,22 @@
1
- # NOTICE
1
+ # OwlRunKit Notice
2
2
 
3
- ## OwlCoda Positioning
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
- OwlCoda is an independent local AI coding platform. It is not affiliated with
6
- any external coding assistant vendor.
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
- Third-party product names may appear where they are needed for protocol
9
- interoperability, optional user-provided provider integrations, migration
10
- history, or competitive analysis. The default npm release package contains the
11
- OwlCoda runtime, bundled skill resources, branding assets, configuration
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
- Starting with the `0.15.0` license boundary, the OwlCoda core package is
16
- released under `GPL-3.0-or-later`. Third-party dependencies and in-tree
17
- attributions keep their own licenses as listed below; this notice records
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
- ### What OwlCoda Provides
21
-
22
- OwlCoda provides:
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
@@ -134,9 +134,29 @@ automatically promote an authoritative writer. Core successor, release
134
134
  compatibility, publication, Project Successor, and project adoption remain
135
135
  separate authority boundaries.
136
136
 
137
+ ## Current release
138
+
139
+ `owlrunkit@0.25.1` is the version documented here. Its public surfaces
140
+ include:
141
+
142
+ - Project Driver and typed delivery lifecycle;
143
+ - Quick and Formal verification with source-bound receipts;
144
+ - controller/target worktree separation and foreign-candidate verification;
145
+ - Team Delivery read-only recommendations and portable transfer packets;
146
+ - bounded compact-session Hook Recovery;
147
+ - optional native Codex Stop continuation on a bound RunKit file event;
148
+ - managed local peer recovery for isolated macOS and Linux workers;
149
+ - completed-project drift detection and read-only successor scaffolding;
150
+ - fail-closed bootstrap, profile, registry, Core, and shared-Skill diagnostics.
151
+
152
+ This repository is the public corresponding-source, documentation, issue,
153
+ release, and trust surface for OwlRunKit. Day-to-day development remains in a
154
+ private source repository; every GPL-covered npm release must map to an exact
155
+ public source tag.
156
+
137
157
  ## Install
138
158
 
139
- This package is the lifecycle-stable, registry-gated `owlrunkit@0.24.1`
159
+ This package is the lifecycle-stable, registry-gated `owlrunkit@0.25.1`
140
160
  artifact. Registry adoption remains fail-closed until its exact official npm
141
161
  version, shasum, integrity, and tarball URL are independently verified. Local
142
162
  tarballs remain candidate-test inputs and are never adoption provenance. Until
@@ -144,7 +164,7 @@ that registry evidence exists, use the package only for isolated candidate
144
164
  verification; do not treat the command below as available release truth.
145
165
 
146
166
  ```bash
147
- npm install --save-exact owlrunkit@0.24.1
167
+ npm install --save-exact owlrunkit@0.25.1
148
168
  ```
149
169
 
150
170
  Use `npx --no-install owlrunkit` for project commands. The package bootstrap
@@ -160,9 +180,9 @@ the project Config must independently bind the same Core.
160
180
  ```bash
161
181
  npx --no-install owlrunkit --version
162
182
  npx --no-install owlrunkit bootstrap --workspace /absolute/path/to/project \
163
- --exact owlrunkit@0.24.1 --dry-run
183
+ --exact owlrunkit@0.25.1 --dry-run
164
184
  npx --no-install owlrunkit bootstrap --workspace /absolute/path/to/project \
165
- --exact owlrunkit@0.24.1 --apply
185
+ --exact owlrunkit@0.25.1 --apply
166
186
  npx --no-install owlrunkit init --workspace /absolute/path/to/project
167
187
  npx --no-install owlrunkit doctor --workspace /absolute/path/to/project
168
188
  npx --no-install owlrunkit inspect --workspace /absolute/path/to/project --json --compact
@@ -995,6 +1015,66 @@ Installing the package enables nothing and changes no global configuration,
995
1015
  shared Skill or other workspace. This is same-session synchronous Stop
996
1016
  continuation; fully idle Desktop wake requires a separate supported ingress.
997
1017
 
1018
+ ## Managed local peer recovery
1019
+
1020
+ Opt a new task into peer recovery before starting its writer. The project
1021
+ controller names the current agent, successor, and exact checkpoint paths in
1022
+ `peer.json`, for example:
1023
+
1024
+ ```json
1025
+ {"owner":"alpha","successor":"bravo","paths":["result.txt"]}
1026
+ ```
1027
+
1028
+ ```bash
1029
+ npx --no-install owlrunkit peer create --workspace . --task repair --request peer.json
1030
+ npx --no-install owlrunkit peer run --workspace . --task repair --agent alpha --generation 1 -- /absolute/worker
1031
+ npx --no-install owlrunkit peer inspect --workspace . --task repair
1032
+ npx --no-install owlrunkit peer recover --workspace . --task repair --agent bravo --generation 1 --revision 2 -- /absolute/successor-worker
1033
+ ```
1034
+
1035
+ The cooperating agent uses the last two commands when it observes an
1036
+ interruption and has authority to run the successor worker. Use the generation
1037
+ and revision returned by `inspect`.
1038
+ Recovery requests a wake from the current worker. A matching, changed checkpoint
1039
+ keeps that worker in charge. If wake remains unconfirmed after the bounded wait,
1040
+ recovery can move ownership to the designated successor because the current
1041
+ attempt already runs in an isolated directory. One durable revision binds the
1042
+ successor generation to the last accepted checkpoint. With a worker command
1043
+ after `--`, recovery starts that worker after takeover and reports its result.
1044
+ A concurrent retry may report the already-started attempt. Without a command,
1045
+ the successor starts its own worker with `peer run`. An ACK or timeout does
1046
+ not prove worker death. Retry the observed revision to read back the handoff.
1047
+
1048
+ Use a local worker that speaks newline-delimited JSON. RunKit seeds the attempt
1049
+ directory from the previous checkpoint and sets `OWLRUNKIT_PEER_PATHS` to the
1050
+ ordered path array. The worker reads a wake challenge from stdin as
1051
+ `{"type":"wake","wakeId":"..."}`. Stdout is reserved for protocol messages.
1052
+ Report work as `{"type":"checkpoint","wakeId":"...","files":[{"path":"result.txt","content":"..."}]}`.
1053
+ Use the wake ID only when reporting progress in response to that challenge.
1054
+ The `files` array covers the exact ordered paths, with canonical base64 bytes
1055
+ or `null` for a missing file. The decoded checkpoint limit is 1 MiB. Emit
1056
+ `finish` with the same `files` shape to record the result. Human diagnostics
1057
+ go to stderr. `inspect` returns the checkpoint path and hash for handoff and
1058
+ review. Only accepted checkpoints seed the next attempt, and the previous
1059
+ scratch directory is reported for inspection while it remains on disk.
1060
+
1061
+ The macOS and Linux backends confine writes to the attempt and deny network
1062
+ connections and new worker processes. Linux supports x86-64 and ARM64 with
1063
+ Landlock ABI 3 or later, seccomp filtering, and `close_range`. The packaged
1064
+ helper checks the effective policy before a managed task starts. It terminates
1065
+ the worker if the supervisor process is killed. The host caller supplies the
1066
+ worker command and peer identity. Existing Desktop sessions and writers using
1067
+ legacy shared-directory leases follow their own recovery procedure. An
1068
+ existing managed task remains pinned to the core that created it.
1069
+
1070
+ Linux control transactions use a kernel lock and a marker in the runtime
1071
+ directory. If the process exits during an atomic lease operation, the next
1072
+ transaction reads the lease state from the committed artifact. For other
1073
+ transactions, automatic recovery requires unchanged control state. A partial
1074
+ transaction returns `runkit_control_reconciliation_required` and preserves its
1075
+ state. An older `control.lock` directory has no kernel ownership record and
1076
+ requires the existing explicit recovery procedure.
1077
+
998
1078
  ## Shared Skill upgrades
999
1079
 
1000
1080
  Process-wide Codex Skill updates automatically use the registered fleet:
package/SOURCE.md CHANGED
@@ -1,10 +1,28 @@
1
- # Source
1
+ # Corresponding source
2
2
 
3
- OwlRunKit is maintained in the private OwlCoda source repository. The npm
4
- tarball contains the complete JavaScript source for the published runtime and
5
- read-only verifier; it does not contain generated minified binaries.
3
+ OwlRunKit is distributed under GPL-3.0-or-later. The corresponding public
4
+ source for this release is [OwlRunKit v0.25.1](https://github.com/yeemio/owlrunkit/tree/v0.25.1).
5
+ It includes the JavaScript runtime, C source and build script for the Linux
6
+ helpers, package metadata, public contracts, and bundled integration resources.
6
7
 
7
- The authoritative release is identified by the npm registry version, shasum,
8
- integrity, and tarball URL. Local directories, `file:` dependencies, local
9
- tarballs, Git URLs, workspace links, and mutable dist-tags are not accepted as
10
- formal cross-project adoption evidence.
8
+ ## Rebuild the Linux helpers
9
+
10
+ Check out the public tag, then run these commands from its root. The helper
11
+ build uses the Alpine 3.22 image and the compiler and Linux headers from its
12
+ package repository. Build on each architecture or use a Docker environment
13
+ that supports both build platforms.
14
+
15
+ ```sh
16
+ mkdir -p .build
17
+ for platform in linux/arm64 linux/amd64; do
18
+ docker run --rm --platform "$platform" \
19
+ -v "$PWD:/source:ro" -v "$PWD/.build:/out" \
20
+ alpine:3.22@sha256:49340b346798875b5592e5d420241f2f9cfba5f47e62ebb1446a1b34734e898f \
21
+ sh -ec 'apk add --no-cache build-base linux-headers; sh /source/packages/runkit/build-linux-helper.sh /out'
22
+ done
23
+ (cd .build && sha256sum -c ../LINUX-HELPERS.sha256)
24
+ ```
25
+
26
+ The npm tarball contains both helper executables alongside their C source and
27
+ the musl copyright notice. Its official registry version, shasum, integrity,
28
+ and tarball URL identify the published package.
@@ -6,7 +6,7 @@
6
6
  ## 已验证现场事实
7
7
 
8
8
  以下结论来自对
9
- `/Users/yeemio/AI/project/sieracMes-AI/.owlcoda/runkit/` 的只读检查,
9
+ 一个真实 MES 项目的 `.owlcoda/runkit/` 只读检查,
10
10
  不是体验推测:
11
11
 
12
12
  - W1.6 留下四份 Quick Receipt V1。按回执生成时的 `exitResult` 与
@@ -7,18 +7,31 @@ 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.24.1`, bundling Contract
11
- `0.2` and Core `0.24.1` with manifest
12
- `sha256:94aaa2e3a6d504374fa78cfcd341e31b33087806c9ddf5f84b3d3b47a6328e08`.
10
+ Bundled registry-gated artifact: standalone `owlrunkit@0.25.1`, bundling Contract
11
+ `0.2` and Core `0.25.1` with manifest
12
+ `sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5`.
13
13
  Registry adoption remains fail-closed until exact official npm registry
14
- provenance for `owlrunkit@0.24.1` is independently verified. The
15
- published rollback baseline for this artifact is `owlrunkit@0.24.0`, with SHA-1
16
- `9408b579faf58f85a3e8d7bd3d64c34256f85fe8` and canonical npm tarball URL
17
- `https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.24.0.tgz`.
14
+ provenance for `owlrunkit@0.25.1` is independently verified. The
15
+ published rollback baseline for this artifact is `owlrunkit@0.25.0`, with SHA-1
16
+ `8cfb52126320bfdafc722bcc41db6cada19f91cc` and canonical npm tarball URL
17
+ `https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.25.0.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.
21
21
 
22
+ ## Optional managed local peer recovery
23
+
24
+ For a task already enrolled in `owlrunkit peer` with an isolated worker, inspect
25
+ the task when your cooperating agent stops progressing. As the designated
26
+ successor, run `peer recover` with the observed generation and revision. A
27
+ new checkpoint tied to the wake challenge keeps the original agent active.
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.
34
+
22
35
  ## Optional file-event continuation
23
36
 
24
37
  RunKit includes `scripts/runkit-contract/file-event-stop-hook.mjs` for an
@@ -357,9 +370,9 @@ below has no CLI entry.
357
370
 
358
371
  ```bash
359
372
  npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
360
- --exact owlrunkit@0.24.1 --dry-run
373
+ --exact owlrunkit@0.25.1 --dry-run
361
374
  npx --no-install owlrunkit bootstrap --workspace "$PROJECT_ROOT" \
362
- --exact owlrunkit@0.24.1 --apply
375
+ --exact owlrunkit@0.25.1 --apply
363
376
  npx --no-install owlrunkit init --workspace "$PROJECT_ROOT"
364
377
  npx --no-install owlrunkit inspect --json --workspace "$PROJECT_ROOT"
365
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.24.1",
6
- "coreManifestSha256": "sha256:94aaa2e3a6d504374fa78cfcd341e31b33087806c9ddf5f84b3d3b47a6328e08",
7
- "coreSourceRef": "artifact:sha256:94aaa2e3a6d504374fa78cfcd341e31b33087806c9ddf5f84b3d3b47a6328e08"
5
+ "coreVersion": "0.25.1",
6
+ "coreManifestSha256": "sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5",
7
+ "coreSourceRef": "artifact:sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5"
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.24.1",
3
+ "version": "0.25.1",
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.1",
48
+ "coreManifestSha256": "sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5"
49
+ },
50
+ {
51
+ "contractVersion": "0.2",
52
+ "coreVersion": "0.25.0",
53
+ "coreManifestSha256": "sha256:20e75c386f1408f11e908a6d3ee1a39316d9728d5719fa06f8d6a5aa45abd83e"
54
+ },
45
55
  {
46
56
  "contractVersion": "0.2",
47
57
  "coreVersion": "0.24.1",
@@ -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.1",
29
+ coreManifestSha256: "sha256:0934a076b147847a4623bc89263b677c88088b493495fc74f11485985b7903b5",
30
+ },
31
+ {
32
+ contractVersion: "0.2",
33
+ coreVersion: "0.25.0",
34
+ coreManifestSha256: "sha256:20e75c386f1408f11e908a6d3ee1a39316d9728d5719fa06f8d6a5aa45abd83e",
35
+ },
26
36
  {
27
37
  contractVersion: "0.2",
28
38
  coreVersion: "0.24.1",
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": "OwlCodaRunKitRegistryReleasePolicyV2",
3
3
  "status": "release_artifact_registry_gated",
4
4
  "packageName": "owlrunkit",
5
- "artifactVersion": "0.24.1",
5
+ "artifactVersion": "0.25.1",
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.24.0",
27
- "shasum": "9408b579faf58f85a3e8d7bd3d64c34256f85fe8",
28
- "integrity": "sha512-AbivZPDxYhOCxemfsT8Q01P6igKCed2P0V15kSzhrNLW548aHqUmIHVmvdZOnvWI/f8p5YBe53cVa4wRq8O1lg==",
29
- "tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.24.0.tgz"
26
+ "version": "0.25.0",
27
+ "shasum": "8cfb52126320bfdafc722bcc41db6cada19f91cc",
28
+ "integrity": "sha512-YgO+KFQ+wmiPVzTRJay9RIyIEYk9e4ViuM0otBIjF8RpkjLcALq2LUJRlo8vmymwxm7TtPCuSNc7UD2gNKFOAA==",
29
+ "tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.25.0.tgz"
30
30
  },
31
31
  "registryEvidenceMustBeExternal": true,
32
32
  "registryEvidenceSchemaVersion": "OwlCodaRunKitRegistryReleaseEvidenceV1",
package/sbom.spdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "spdxVersion": "SPDX-2.3",
3
3
  "dataLicense": "CC0-1.0",
4
4
  "SPDXID": "SPDXRef-DOCUMENT",
5
- "name": "owlrunkit-0.24.1",
6
- "documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.24.1",
5
+ "name": "owlrunkit-0.25.1",
6
+ "documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.25.1",
7
7
  "creationInfo": {
8
- "created": "2026-10-08T00:00:00Z",
8
+ "created": "2026-11-11T00:00:00Z",
9
9
  "creators": [
10
10
  "Organization: OwlCoda"
11
11
  ]
@@ -14,7 +14,7 @@
14
14
  {
15
15
  "name": "owlrunkit",
16
16
  "SPDXID": "SPDXRef-Package-OwlRunKit",
17
- "versionInfo": "0.24.1",
17
+ "versionInfo": "0.25.1",
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.24.1"
27
+ "referenceLocator": "pkg:npm/owlrunkit@0.25.1"
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
+ }