You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .agent/contracts/kernel.md
+154Lines changed: 154 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,10 @@ The kernel VFS SHALL provide a POSIX-like filesystem interface with consistent e
28
28
-**WHEN** a caller invokes `removeFile(path)` on an existing regular file
29
29
-**THEN** the file MUST be deleted and subsequent `exists(path)` MUST return false
30
30
31
+
#### Scenario: removeFile defers inode data deletion while FDs remain open
32
+
-**WHEN** the last directory entry for a file is removed while one or more existing FDs still reference that inode
33
+
-**THEN** the pathname MUST disappear from directory listings and `exists(path)` MUST return false, but reads and writes through the already-open FDs MUST continue to operate until the last reference closes
34
+
31
35
#### Scenario: removeDir deletes a directory
32
36
-**WHEN** a caller invokes `removeDir(path)` on an existing empty directory
33
37
-**THEN** the directory MUST be deleted
@@ -52,10 +56,18 @@ The kernel VFS SHALL provide a POSIX-like filesystem interface with consistent e
52
56
-**WHEN** a caller invokes `link(oldPath, newPath)`
53
57
-**THEN** both paths MUST reference the same content, and `stat` for both MUST report `nlink >= 2`
54
58
59
+
#### Scenario: hard links share a stable inode number
60
+
-**WHEN** two directory entries refer to the same file through `link(oldPath, newPath)`
61
+
-**THEN**`stat(oldPath).ino` and `stat(newPath).ino` MUST be identical until the inode is deleted
62
+
55
63
#### Scenario: readDirWithTypes returns entries with type information
56
64
-**WHEN** a caller invokes `readDirWithTypes(path)` on a directory containing files and subdirectories
57
65
-**THEN** the VFS MUST return `VirtualDirEntry[]` where each entry has `name`, `isDirectory`, and `isSymbolicLink` fields
58
66
67
+
#### Scenario: InMemoryFileSystem directory listings include self and parent entries
68
+
-**WHEN** a caller invokes `readDir(path)` or `readDirWithTypes(path)` against an `InMemoryFileSystem` directory
69
+
-**THEN** the listing MUST begin with `.` and `..`, and for `/` the `..` entry MUST refer back to the root directory
70
+
59
71
#### Scenario: chmod updates file permissions
60
72
-**WHEN** a caller invokes `chmod(path, mode)` on an existing file
61
73
-**THEN** subsequent `stat(path)` MUST reflect the updated `mode`
@@ -71,6 +83,18 @@ The kernel FD table SHALL manage per-process file descriptor allocation with ref
71
83
-**WHEN** a process opens a file via `fdOpen(pid, path, flags)`
72
84
-**THEN** the FD table MUST allocate and return the lowest available file descriptor number
73
85
86
+
#### Scenario: Open with O_CREAT|O_EXCL rejects existing paths
87
+
-**WHEN** a process opens an already-existing path with `O_CREAT | O_EXCL`
88
+
-**THEN**`fdOpen` MUST fail with `EEXIST` before allocating a new FD
89
+
90
+
#### Scenario: Open with O_TRUNC truncates at open time
91
+
-**WHEN** a process opens an existing regular file with `O_TRUNC`
92
+
-**THEN** the file contents MUST be truncated to zero bytes before subsequent reads or writes through the returned FD
93
+
94
+
#### Scenario: Open with O_TRUNC|O_CREAT materializes an empty file
95
+
-**WHEN** a process opens a missing path with `O_TRUNC | O_CREAT`
96
+
-**THEN** the kernel MUST create an empty regular file during `fdOpen`
97
+
74
98
#### Scenario: Close decrements reference count and releases FD
75
99
-**WHEN** a process closes an FD via `fdClose(pid, fd)`
76
100
-**THEN** the FD entry MUST be removed from the process table and the underlying FileDescription's `refCount` MUST be decremented
@@ -79,6 +103,10 @@ The kernel FD table SHALL manage per-process file descriptor allocation with ref
79
103
-**WHEN** the last FD referencing a FileDescription is closed (refCount reaches 0)
80
104
-**THEN** the FileDescription MUST be eligible for cleanup
81
105
106
+
#### Scenario: Close last reference releases deferred-unlink inode data
107
+
-**WHEN** the last FD referencing an already-unlinked inode is closed
108
+
-**THEN** the kernel MUST release the inode's retained file data so no hidden data remains after the final close
109
+
82
110
#### Scenario: Dup creates a new FD sharing the same FileDescription
83
111
-**WHEN** a process duplicates an FD via `fdDup(pid, fd)`
84
112
-**THEN** a new FD MUST be allocated pointing to the same FileDescription, and the FileDescription's `refCount` MUST be incremented
@@ -107,6 +135,25 @@ The kernel FD table SHALL manage per-process file descriptor allocation with ref
107
135
-**WHEN** a process exits and `closeAll()` is invoked on its FD table
108
136
-**THEN** all FDs MUST be closed and all FileDescription refCounts MUST be decremented
109
137
138
+
### Requirement: Advisory flock Semantics
139
+
The kernel SHALL provide advisory `flock()` semantics per file description, including blocking waits and cleanup on last close.
140
+
141
+
#### Scenario: Exclusive flock blocks until the prior holder unlocks
142
+
-**WHEN** process A holds `LOCK_EX` on a file and process B calls `flock(fd, LOCK_EX)` on the same file without `LOCK_NB`
143
+
-**THEN** process B MUST remain blocked until process A releases the lock, after which process B acquires it
144
+
145
+
#### Scenario: Non-blocking flock returns EAGAIN on conflict
146
+
-**WHEN** a conflicting advisory lock is already held and a caller uses `LOCK_NB`
147
+
-**THEN**`flock()` MUST fail immediately with `EAGAIN`
148
+
149
+
#### Scenario: flock waiters are served in FIFO order
150
+
-**WHEN** multiple callers are queued waiting for the same file lock
151
+
-**THEN** unlock MUST wake the next waiter in FIFO order so lock ownership advances predictably
152
+
153
+
#### Scenario: Last file description close releases flock state
154
+
-**WHEN** the final FD referencing a locked file description is closed or the owning process exits
155
+
-**THEN** the lock MUST be released and the next queued waiter MUST be eligible to acquire it
156
+
110
157
### Requirement: Process Table Register/Waitpid/Kill/Zombie Cleanup
111
158
The kernel process table SHALL manage process lifecycle with atomic PID allocation, signal delivery, and time-bounded zombie cleanup.
112
159
@@ -154,6 +201,17 @@ The kernel process table SHALL manage process lifecycle with atomic PID allocati
154
201
-**WHEN**`listProcesses()` is invoked
155
202
-**THEN** it MUST return a Map of PID to ProcessInfo containing `pid`, `ppid`, `driver`, `command`, `status`, and `exitCode` for every registered process
156
203
204
+
### Requirement: Kernel TimerTable Ownership And Process Cleanup
205
+
The kernel SHALL expose a shared timer table so runtimes can enforce per-process timer budgets and clear timer ownership on process exit.
206
+
207
+
#### Scenario: TimerTable is exposed to runtimes
208
+
-**WHEN** a runtime receives a kernel interface in a kernel-mediated environment
209
+
-**THEN** it MUST be able to access the shared `timerTable` for per-process timer allocation and cleanup
210
+
211
+
#### Scenario: Process exit clears kernel-owned timers
212
+
-**WHEN** a process exits through the kernel process lifecycle
213
+
-**THEN** any timers owned by that PID MUST be removed from the kernel `TimerTable`
214
+
157
215
### Requirement: Device Layer Intercepts and EPERM Rules
158
216
The kernel device layer SHALL transparently intercept `/dev/*` paths with fixed device semantics, pass non-device paths through to the underlying VFS, and deny mutation operations on devices.
159
217
@@ -197,6 +255,37 @@ The kernel device layer SHALL transparently intercept `/dev/*` paths with fixed
197
255
-**WHEN** any filesystem operation targets a path outside `/dev/`
198
256
-**THEN** the device layer MUST delegate the operation to the underlying VFS without interception
199
257
258
+
### Requirement: Proc Filesystem Introspection
259
+
The kernel SHALL expose a read-only `/proc` pseudo-filesystem backed by live process and FD table state so runtimes can inspect `/proc/<pid>` consistently, while process-scoped runtime adapters resolve `/proc/self` to the caller PID.
260
+
261
+
#### Scenario: /proc root lists self and running PIDs
262
+
-**WHEN** a caller invokes `readDir("/proc")`
263
+
-**THEN** the listing MUST include a `self` entry and directory entries for every PID currently tracked by the kernel process table
264
+
265
+
#### Scenario: /proc/<pid>/fd lists live file descriptors
266
+
-**WHEN** a caller invokes `readDir("/proc/<pid>/fd")` for a live process
267
+
-**THEN** the listing MUST contain the process's currently open FD numbers from the kernel FD table
268
+
269
+
#### Scenario: /proc/<pid>/fd/<n> resolves to the underlying description path
270
+
-**WHEN** a caller invokes `readlink("/proc/<pid>/fd/<n>")` for an open FD
271
+
-**THEN** the kernel MUST return the backing file description path for that FD
272
+
273
+
#### Scenario: /proc/<pid>/cwd and exe expose process metadata
274
+
-**WHEN** a caller reads `/proc/<pid>/cwd` or `/proc/<pid>/exe`
275
+
-**THEN** the kernel MUST expose the process working directory and executable path for that PID
-**THEN** the kernel MUST return the process environment as `KEY=value` entries delimited by `\0`, or an empty file when the process environment is empty
280
+
281
+
#### Scenario: /proc paths are read-only
282
+
-**WHEN** a caller invokes a mutating filesystem operation against `/proc` or any `/proc/...` path
283
+
-**THEN** the kernel MUST reject the operation with `EPERM`
284
+
285
+
#### Scenario: Process-scoped runtimes resolve /proc/self to the caller PID
286
+
-**WHEN** sandboxed code in a process-scoped runtime accesses `/proc/self/...`
287
+
-**THEN** the runtime-facing VFS MUST resolve that path as `/proc/<current_pid>/...` before delegating into the shared kernel proc filesystem
-**WHEN** only part of a blocking write fits before the pipe buffer becomes full
326
+
-**THEN** the pipe manager MUST commit the bytes that fit, then block for the remainder until more capacity is available
327
+
223
328
#### Scenario: Read returns null (EOF) when write end is closed and buffer is empty
224
329
-**WHEN** a read is performed on a pipe's read end after the write end has been closed and the buffer is drained
225
330
-**THEN** the read MUST return `null` signaling EOF
@@ -228,6 +333,10 @@ The kernel pipe manager SHALL provide buffered unidirectional pipes with blockin
228
333
-**WHEN** the write end of a pipe is closed and readers are blocked waiting for data
229
334
-**THEN** all blocked readers MUST be notified with `null` (EOF)
230
335
336
+
#### Scenario: Closing the read end wakes blocked writers with EPIPE
337
+
-**WHEN** writers are blocked waiting for pipe capacity and the read end is closed
338
+
-**THEN** those writers MUST wake and fail with `EPIPE`
339
+
231
340
#### Scenario: Pipes work across runtime drivers
232
341
-**WHEN** a pipe connects a process in one runtime driver (e.g., WasmVM) to a process in another (e.g., Node)
233
342
-**THEN** data MUST flow through the kernel pipe manager transparently, with the same blocking/EOF semantics
@@ -236,6 +345,51 @@ The kernel pipe manager SHALL provide buffered unidirectional pipes with blockin
236
345
-**WHEN**`createPipeFDs(fdTable)` is invoked
237
346
-**THEN** the pipe manager MUST create a pipe and install both read and write FileDescriptions as FDs in the specified FD table, returning `{ readFd, writeFd }`
238
347
348
+
### Requirement: Socket Blocking Waits Respect Signal Handlers
349
+
The kernel socket table SHALL allow blocking accept/recv waits to observe delivered signals so POSIX-style syscall interruption semantics can be enforced.
350
+
351
+
#### Scenario: SA_RESETHAND resets a caught handler after first delivery
352
+
-**WHEN** a process delivers a caught signal whose registered handler includes `SA_RESETHAND`
353
+
-**THEN** the kernel MUST invoke that handler once and reset the disposition to `SIG_DFL` before any subsequent delivery of the same signal
354
+
355
+
#### Scenario: recv interrupted without SA_RESTART returns EINTR
356
+
-**WHEN** a process is blocked in a socket `recv` wait and a caught signal is delivered whose handler does not include `SA_RESTART`
357
+
-**THEN** the wait MUST reject with `EINTR`
358
+
359
+
#### Scenario: recv interrupted with SA_RESTART resumes waiting
360
+
-**WHEN** a process is blocked in a socket `recv` wait and a caught signal is delivered whose handler includes `SA_RESTART`
361
+
-**THEN** the wait MUST resume transparently until data arrives or EOF occurs
362
+
363
+
### Requirement: Non-blocking Socket Operations Return Immediate Status
364
+
The kernel socket table SHALL respect per-socket non-blocking mode for read, accept, and external connect operations.
365
+
366
+
#### Scenario: recv on a non-blocking socket returns EAGAIN when empty
367
+
-**WHEN**`recv` is called on a socket whose `nonBlocking` flag is set and no data or EOF is available
368
+
-**THEN** the call MUST fail immediately with `EAGAIN`
369
+
370
+
#### Scenario: accept on a non-blocking listening socket returns EAGAIN when backlog is empty
371
+
-**WHEN**`accept` is called on a listening socket whose `nonBlocking` flag is set and there are no queued connections
372
+
-**THEN** the call MUST fail immediately with `EAGAIN`
373
+
374
+
#### Scenario: external connect on a non-blocking socket returns EINPROGRESS
375
+
-**WHEN**`connect` is called on a non-blocking socket for an external address routed through the host adapter
376
+
-**THEN** the call MUST fail immediately with `EINPROGRESS` while the host-side connection continues asynchronously
377
+
378
+
#### Scenario: accept interrupted with SA_RESTART resumes waiting
379
+
-**WHEN** a process is blocked in a socket `accept` wait and a caught signal is delivered whose handler includes `SA_RESTART`
380
+
-**THEN** the wait MUST resume transparently until a connection is available
381
+
382
+
### Requirement: Socket Bind and Listen Preserve Bounded Listener State
383
+
The kernel socket table SHALL reserve listener ports deterministically for loopback routing while keeping pending connection queues bounded.
384
+
385
+
#### Scenario: bind with port 0 assigns a kernel ephemeral port
386
+
-**WHEN** an internet-domain socket is bound with `port: 0` for kernel-managed routing
387
+
-**THEN** the socket MUST be assigned a free port in the ephemeral range and `localAddr.port` MUST reflect that assigned value instead of `0`
388
+
389
+
#### Scenario: loopback connect refuses when listener backlog is full
390
+
-**WHEN** a loopback `connect()` targets a listening socket whose pending backlog already reached the configured `listen(backlog)` capacity
391
+
-**THEN** the connection MUST fail with `ECONNREFUSED` instead of growing the backlog without bound
392
+
239
393
### Requirement: Command Registry Resolution and /bin Population
240
394
The kernel command registry SHALL map command names to runtime drivers and populate `/bin` stubs for shell PATH-based resolution.
Copy file name to clipboardExpand all lines: .agent/contracts/node-bridge.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -157,3 +157,6 @@ The bridge global key registry consumed by host runtime setup, bridge modules, a
157
157
-**WHEN** contributors add a new bridge global used by host/isolate boundary wiring
158
158
-**THEN** that global MUST be added to the canonical shared key registry and corresponding shared contract typing in the same change
159
159
160
+
#### Scenario: Native V8 bridge registries stay aligned with async and sync lifecycle hooks
161
+
-**WHEN** bridge modules depend on a host bridge global via async `.apply(..., { result: { promise: true } })` or sync `.applySync(...)` semantics
162
+
-**THEN** the native V8 bridge function registries MUST expose a matching callable shape for that global (or an equivalent tested shim), and automated verification MUST cover the registry alignment
0 commit comments