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/compatibility-governance.md
+37Lines changed: 37 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,6 +29,32 @@ Changes affecting bridged or polyfilled Node APIs MUST keep `docs/nodejs-compati
29
29
-**WHEN**`docs/nodejs-compatibility.mdx` is updated
30
30
-**THEN** the page MUST retain an explicit target Node version statement at the top
31
31
32
+
### Requirement: Node Conformance Vacuous Self-Skips Must Not Inflate Genuine Pass Counts
33
+
Node conformance expectation and reporting flows SHALL reserve `category: "vacuous-skip"` for expected-pass vendored tests that exit `0` only because the test self-skipped without exercising functionality.
34
+
35
+
#### Scenario: Self-skipping vendored file is treated as vacuous pass
36
+
-**WHEN** an expectation is marked `expected: "pass"` only because the vendored test self-skips
37
+
-**THEN** it MUST use `category: "vacuous-skip"` and reporting MUST exclude it from the genuine-pass count
38
+
39
+
#### Scenario: Intentionally skipped file is still a skip
40
+
-**WHEN** secure-exec keeps a vendored file under `expected: "skip"` because functionality remains broken or intentionally unsupported
41
+
-**THEN** that entry MUST stay under its real failure category rather than `vacuous-skip`
42
+
43
+
### Requirement: Node Conformance Non-Pass Expectations Must Be Classified By Implementation Intent
44
+
Node conformance expectation and reporting flows SHALL classify every non-passing vendored test into exactly one implementation-intent bucket: `implementable`, `will-not-implement`, or `cannot-implement`.
45
+
46
+
#### Scenario: Remaining non-pass inventory is reported
47
+
-**WHEN** expectations or the generated conformance report are updated
48
+
-**THEN** the maintained conformance artifacts MUST expose the remaining non-pass counts grouped by implementation intent alongside the existing failure-category breakdown
49
+
50
+
#### Scenario: Non-pass expectation is categorized
51
+
-**WHEN** an expectation remains `expected: "fail"` or `expected: "skip"`
52
+
-**THEN** it MUST resolve to exactly one implementation-intent bucket using a specific, verifiable reason that distinguishes policy/out-of-scope exclusions from fundamental architectural blockers
53
+
54
+
#### Scenario: Conformance target is communicated
55
+
-**WHEN** the generated Node conformance report is regenerated
56
+
-**THEN** it MUST state that the tracked completion target is 100% of the `implementable` bucket rather than 100% of the upstream vendored suite
57
+
32
58
### Requirement: Node Compatibility Target Version Tracks Test Type Baseline
33
59
The runtime compatibility target MUST align with the `@types/node` package major version used to validate secure-exec tests and type checks. Compatibility documentation and spec references MUST describe the same target major Node line.
34
60
@@ -106,6 +132,17 @@ Fixture dependency installation SHALL be cached across repeated test invocations
106
132
-**WHEN** fixture files or cache key factors change
107
133
-**THEN** the matrix MUST prepare a new cache entry and reinstall dependencies before execution
108
134
135
+
### Requirement: Kernel-Consolidation Proof Must Use Kernel-Mounted Verification
136
+
Stories or docs that claim kernel-consolidation networking behavior is complete SHALL distinguish kernel-mounted proof from compatibility coverage for the retained legacy adapter path.
137
+
138
+
#### Scenario: Verification targets a retained legacy adapter path
139
+
-**WHEN** a test instantiates `createDefaultNetworkAdapter()` or `useDefaultNetwork`
140
+
-**THEN** that test MUST be treated as compatibility coverage for the standalone legacy path rather than as proof that kernel-consolidation work is complete
141
+
142
+
#### Scenario: Verification is used as evidence for kernel-consolidation networking
143
+
-**WHEN** a test or document is cited as proof that kernel-backed Node networking works
144
+
-**THEN** it MUST execute through `createNodeRuntime()` mounted into a real `Kernel` or an equivalent kernel-mediated path that exercises the shared socket table and host-adapter delegation
145
+
109
146
### Requirement: Parity Mismatches Remain Failing Until Resolved
110
147
Compatibility project-matrix policy SHALL NOT include a "known mismatch" or equivalent pass-through state for parity failures.
Copy file name to clipboardExpand all lines: .agent/contracts/kernel.md
+115-2Lines changed: 115 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,6 +60,10 @@ The kernel VFS SHALL provide a POSIX-like filesystem interface with consistent e
60
60
-**WHEN** two directory entries refer to the same file through `link(oldPath, newPath)`
61
61
-**THEN**`stat(oldPath).ino` and `stat(newPath).ino` MUST be identical until the inode is deleted
62
62
63
+
#### Scenario: directory nlink reflects self, parent, and child directories
64
+
-**WHEN** the InMemoryFileSystem creates or removes directories
65
+
-**THEN** each directory MUST report POSIX-style `nlink` metadata: `2` for an empty directory, `2 + childDirectoryCount` for non-root directories, and root `nlink` MUST increase for each immediate child directory
66
+
63
67
#### Scenario: readDirWithTypes returns entries with type information
64
68
-**WHEN** a caller invokes `readDirWithTypes(path)` on a directory containing files and subdirectories
65
69
-**THEN** the VFS MUST return `VirtualDirEntry[]` where each entry has `name`, `isDirectory`, and `isSymbolicLink` fields
@@ -111,6 +115,10 @@ The kernel FD table SHALL manage per-process file descriptor allocation with ref
111
115
-**WHEN** a process duplicates an FD via `fdDup(pid, fd)`
112
116
-**THEN** a new FD MUST be allocated pointing to the same FileDescription, and the FileDescription's `refCount` MUST be incremented
113
117
118
+
#### Scenario: Duplicated FDs keep deferred-unlink inode data until the last shared close
119
+
-**WHEN** a file's pathname is unlinked after `dup`, `dup2`, or fork creates additional FDs that share the same FileDescription
120
+
-**THEN** the inode-backed data MUST remain accessible through the remaining shared FD references and MUST be released only when that shared FileDescription's final reference closes
121
+
114
122
#### Scenario: Dup2 redirects target FD to source FileDescription
115
123
-**WHEN** a process invokes `fdDup2(pid, oldFd, newFd)` and `newFd` is already open
116
124
-**THEN**`newFd` MUST be closed first, then reassigned to share `oldFd`'s FileDescription with `refCount` incremented
@@ -177,14 +185,29 @@ The kernel process table SHALL manage process lifecycle with atomic PID allocati
177
185
-**WHEN** a caller invokes `waitpid(pid)` on a process that has already exited
178
186
-**THEN** the Promise MUST resolve immediately with the recorded exit status
179
187
180
-
#### Scenario: kill sends signal to running process via driver
181
-
-**WHEN** a caller invokes `kill(pid, signal)` on a running process
188
+
#### Scenario: kill routes default-action signals to the driver
189
+
-**WHEN** a caller invokes `kill(pid, signal)` on a running process and the delivered disposition resolves to `SIG_DFL`
182
190
-**THEN** the kernel MUST route the signal through `driverProcess.kill(signal)` on the process's DriverProcess handle
183
191
184
192
#### Scenario: kill on exited process is a no-op or throws
185
193
-**WHEN** a caller invokes `kill(pid, signal)` on a process with `status: "exited"`
186
194
-**THEN** the kernel MUST NOT attempt to deliver the signal to the driver
187
195
196
+
### Requirement: Process Signal Handlers And Pending Delivery
197
+
The kernel process table SHALL preserve per-process signal dispositions, blocked masks, and pending caught-signal delivery state.
198
+
199
+
#### Scenario: caught signal handler runs instead of the default driver action
200
+
-**WHEN** a running process has a registered caught disposition for a delivered signal
201
+
-**THEN** the kernel MUST invoke that handler and MUST NOT route the signal through `driverProcess.kill(signal)` unless a later delivery falls back to `SIG_DFL`
202
+
203
+
#### Scenario: blocked caught signals remain pending until unmasked
204
+
-**WHEN**`sigprocmask()` blocks a delivered signal for a running process
205
+
-**THEN** the kernel MUST queue that signal in the process's pending set instead of dispatching it immediately
-**WHEN**`sigprocmask()` later unblocks one or more queued pending signals
209
+
-**THEN** the kernel MUST dispatch those pending signals immediately in ascending signal-number order, skipping any that remain blocked
210
+
188
211
#### Scenario: Zombie processes are cleaned up after TTL
189
212
-**WHEN** a process exits and transitions to zombie state
190
213
-**THEN** the process entry MUST be cleaned up (removed from the table) after a bounded TTL (60 seconds)
@@ -345,9 +368,20 @@ The kernel pipe manager SHALL provide buffered unidirectional pipes with blockin
345
368
-**WHEN**`createPipeFDs(fdTable)` is invoked
346
369
-**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 }`
347
370
371
+
### Requirement: FD Poll Waits Support Indefinite Blocking
372
+
The kernel SHALL expose `fdPollWait` readiness waits that can either time out or remain pending until an FD state change occurs.
373
+
374
+
#### Scenario: poll timeout -1 waits until FD readiness changes
375
+
-**WHEN** a runtime calls `fdPollWait(pid, fd, -1)` for a pipe or other waitable FD that is not yet ready
376
+
-**THEN** the wait MUST remain pending until that FD becomes readable, writable, or hung up, rather than timing out because of an internal guard interval
377
+
348
378
### Requirement: Socket Blocking Waits Respect Signal Handlers
349
379
The kernel socket table SHALL allow blocking accept/recv waits to observe delivered signals so POSIX-style syscall interruption semantics can be enforced.
350
380
381
+
#### Scenario: sigaction registration preserves mask and flags
382
+
-**WHEN** a runtime registers a caught signal disposition with a signal mask and `SA_*` flags
383
+
-**THEN** the kernel MUST retain the handler, blocked-signal mask, and raw flag bits so later delivery and wait-restart behavior observes the same metadata
384
+
351
385
#### Scenario: SA_RESETHAND resets a caught handler after first delivery
352
386
-**WHEN** a process delivers a caught signal whose registered handler includes `SA_RESETHAND`
353
387
-**THEN** the kernel MUST invoke that handler once and reset the disposition to `SIG_DFL` before any subsequent delivery of the same signal
@@ -390,6 +424,74 @@ The kernel socket table SHALL reserve listener ports deterministically for loopb
390
424
-**WHEN** a loopback `connect()` targets a listening socket whose pending backlog already reached the configured `listen(backlog)` capacity
391
425
-**THEN** the connection MUST fail with `ECONNREFUSED` instead of growing the backlog without bound
392
426
427
+
#### Scenario: listening socket becomes readable while accept backlog is non-empty
428
+
-**WHEN** one or more pending connections are queued for a listening socket
429
+
-**THEN**`socketTable.poll()` for that listener MUST report `readable: true` until `accept()` drains the backlog
430
+
431
+
#### Scenario: closing a listener tears down queued unaccepted connections
432
+
-**WHEN** a listening socket is closed while its accept backlog still contains pending server-side sockets
433
+
-**THEN** the kernel MUST close those queued sockets as part of listener teardown so detached connections do not remain reachable without a listener owner
434
+
435
+
### Requirement: Socket Options And Per-call Flags Preserve Kernel And Host Semantics
436
+
The kernel socket table SHALL track socket options per socket, apply kernel-enforced options during bind/send paths, and preserve per-call read flag semantics across supported socket types.
437
+
438
+
#### Scenario: getsockopt returns values previously stored by setsockopt
439
+
-**WHEN** a caller sets `SO_REUSEADDR`, `SO_KEEPALIVE`, `SO_RCVBUF`, `SO_SNDBUF`, or `TCP_NODELAY` on a kernel socket
440
+
-**THEN**`getsockopt` MUST return the last value written for that `(level, optname)` pair on that socket
-**WHEN** a caller binds an internet-domain socket to an already-used local port after setting `SO_REUSEADDR` on the binding socket
444
+
-**THEN** the kernel MUST allow that bind instead of rejecting it with `EADDRINUSE`
445
+
446
+
#### Scenario: host-backed TCP sockets replay stored options after connect
447
+
-**WHEN** a socket with previously stored `TCP_NODELAY` or `SO_KEEPALIVE` becomes backed by a host TCP connection
448
+
-**THEN** the kernel MUST replay those options onto the host socket
449
+
-**AND** later `setsockopt` updates on that connected host-backed socket MUST be forwarded immediately
450
+
451
+
#### Scenario: MSG_PEEK returns data without consuming it
452
+
-**WHEN**`recv()` or `recvFrom()` is called with `MSG_PEEK` and data is queued
453
+
-**THEN** the kernel MUST return the readable bytes without removing them from the socket buffer or datagram queue
454
+
455
+
#### Scenario: MSG_DONTWAIT returns EAGAIN only for empty non-EOF reads
456
+
-**WHEN**`recv()` or `recvFrom()` is called with `MSG_DONTWAIT` and no readable data is available yet
457
+
-**THEN** the kernel MUST fail immediately with `EAGAIN`
458
+
-**AND** if EOF is already known for that read path it MUST still return `null` instead of `EAGAIN`
459
+
460
+
### Requirement: UDP Datagram Transport Preserves Message Boundaries And Source Addresses
461
+
The kernel socket table SHALL model UDP as connectionless datagram delivery, preserving one-send-to-one-recv boundaries and reporting the sender address for each datagram.
462
+
463
+
#### Scenario: sendTo delivers one datagram to recvFrom with source address metadata
464
+
-**WHEN** a bound UDP socket calls `sendTo()` to another kernel-bound UDP socket
465
+
-**THEN** the destination socket MUST queue exactly one datagram for `recvFrom()`
466
+
-**AND**`recvFrom()` MUST return the sender's address in `srcAddr`
467
+
468
+
#### Scenario: recvFrom truncates oversized datagrams without leaking the remainder
469
+
-**WHEN** a queued UDP datagram exceeds the caller's `maxBytes`
470
+
-**THEN**`recvFrom()` MUST return only the leading `maxBytes`
471
+
-**AND** the excess bytes MUST be discarded instead of surfacing as a second datagram
472
+
473
+
#### Scenario: unbound UDP destinations drop silently
474
+
-**WHEN**`sendTo()` targets an address with no kernel-bound UDP socket and no host-backed UDP route
475
+
-**THEN** the kernel MUST report the datagram length as written
476
+
-**AND** the datagram MUST be dropped silently instead of raising `ECONNREFUSED`
477
+
478
+
#### Scenario: host-backed UDP sockets route through the host adapter
479
+
-**WHEN** a bound UDP socket is attached to an external host-backed transport and sends or receives external datagrams
480
+
-**THEN** the kernel MUST delegate outbound sends through the configured host adapter
481
+
-**AND** inbound host datagrams MUST be surfaced via `recvFrom()` with the host sender address preserved
482
+
483
+
### Requirement: Kernel Socket Ownership Matches the Process Table
484
+
The kernel socket table SHALL only allocate process-owned sockets for PIDs that are currently registered in the kernel process table when the table is kernel-mediated.
485
+
486
+
#### Scenario: create rejects unknown owner PID in kernel mode
487
+
-**WHEN**`createKernel()` provisions the shared `SocketTable` and a caller attempts `socketTable.create(..., pid)` for a PID that is not present in the process table
488
+
-**THEN** socket creation MUST fail with `ESRCH`
489
+
490
+
#### Scenario: process exit cleanup closes only that PID's sockets
491
+
-**WHEN** a registered process exits and the kernel runs process-exit cleanup
492
+
-**THEN** the socket table MUST close all sockets owned by that PID
493
+
-**AND** sockets owned by other still-registered PIDs MUST remain available
494
+
393
495
### Requirement: Command Registry Resolution and /bin Population
394
496
The kernel command registry SHALL map command names to runtime drivers and populate `/bin` stubs for shell PATH-based resolution.
395
497
@@ -440,6 +542,17 @@ The kernel permission system SHALL wrap VFS and environment access with deny-by-
440
542
-**WHEN** network or child-process permission checks are configured
441
543
-**THEN** operations without explicit allowance MUST be denied, consistent with the fs permission model
0 commit comments