@ai-ecoverse/slicc-kernel 1.100.3 → 1.100.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,7 +76,7 @@ Starts `argv` as the session leader on a new terminal and resolves once it is ru
76
76
  | `pid` | the session leader's pid |
77
77
  | `onData` | the output listener; output that arrives while it is `null` is kept and delivered when one is set |
78
78
  | `write(data)` | types a string or bytes into the terminal; with `ISIG` on, `^C`, `^Z` and `^\` signal the foreground process group. A key typed while a child of that group is still setting up is held until the child has finished, then sent to the group in the foreground at that point; this applies only to children of a job-control shell (a process that ignores `SIGTTOU`, as interactive shells do) and to the programs those children exec, so a program that starts a child without job control (Python's `subprocess`) gets the key at once. Setting up means the child's calls before its first other one: `setpgid`, `tcsetpgrp`, signal masks, and starting the program it execs (which then sets itself up too). The hold ends 2 s after the child's first call at the latest. A key typed while the foreground group is busy, not reading the terminal (a shell between reading a command line and starting it), goes to that group and also to the job the group starts next, once that job has taken the terminal; the second copy is dropped when the group reads the terminal again. So `^C` or `^Z` right after a command line reaches the new job, as it does on Linux, where starting a job takes microseconds rather than a worker start. For the same reason, a child that is still setting up cannot give the terminal to its own group once its parent has already given the terminal to that group and taken it back: on Linux the child's `tcsetpgrp` would have landed first, so the parent's later choice stands. Otherwise `tcsetpgrp` behaves as before. A `^C`, `^\` or `^Z` that a program with a handler for it takes between two system calls, rather than while waiting, ends the program's next wait in the kernel that would block (reading nothing yet, `select` or `poll` with a timeout, a blocking write, `waitpid`) with `EINTR`, once, as if the key had come during that wait. A zero-timeout `select` or `poll` does not use it up. Without this, an interactive shell whose `^C` landed while it was taking in the key before it would wait for the next key before showing a new prompt: readline acts on `^C` only when a read ends with `EINTR`. On Linux that window is the microseconds between two reads; here it is a few kernel calls per key. A signal sent with `kill` does not do this. |
79
- | `resize(cols, rows)` | sets the window size (`TIOCGWINSZ`) and sends `SIGWINCH` to the foreground process group |
79
+ | `resize(cols, rows)` | sets the window size (`TIOCGWINSZ`) and sends `SIGWINCH` to the foreground process group. As on Linux, setting the size the terminal already has, here or with a program's `TIOCSWINSZ`, sends no `SIGWINCH`. A program's `TIOCSWINSZ` that writes back the size it last read with `TIOCGWINSZ` is left out, so it can't undo a resize that came in between. Readline does that write-back every time it starts reading a line; on Linux the gap between the two calls is microseconds, here it's two kernel calls, wide enough for a resize to land in it and the shell to keep the old size (#740). |
80
80
  | `signal(name)` | sends a signal (`'SIGINT'`, `'SIGTSTP'`, `'SIGQUIT'`, `'SIGHUP'`, …) to the foreground process group, regardless of termios |
81
81
  | `exited` | resolves with the session leader's exit status (`128 + n` if killed by signal `n`) |
82
82
  | `ended` | resolves with `{ status, signal }` at the same time: `status` as `exited`, and `signal` named (`'SIGKILL'`) only when a signal ended it |
@@ -899,13 +899,14 @@ Releases are cut by semantic-release on every push to `main`, in two jobs, and o
899
899
  - **plan:** works out the version, the previous tag, the commit and the base (`base.mjs`). The base is the newest earlier release whose `cert-review` commit status is `success`, or, until there is one, the release `base.json` names (the cert lane's last line). CI never reads the npm `certified` dist-tag.
900
900
  - **delta** (`delta.mjs`): lists the pull requests merged between the two tags (their merge commits, plus `pr` for a planted branch). Each gets its conventional-commit kind (`fix`, `feat`, `perf` and `revert` are behaviour changes) and the integration test files and titles it adds or changes. The titles are read from the pull request's patch: the added `test(…)` lines and the hunk headers git puts above changed lines. Escapes are decoded as JavaScript does, and a title git cut short, or a template literal, matches as a prefix.
901
901
  - **suite** (`suite.mjs`, `reporter.mjs`) runs on the bench pool, without secrets. It takes the tag's tree with its own dependencies and Chromium, and replaces `dist/` with the **published npm tarball** (for a planted branch, its own `npm pack`). The test command runs in a session of its own (`detached`), and `suite.mjs` notes a `SIGINT` (`ignored` in its summary) instead of dying of it. That way a stray signal to the step's process group can't cut the run short, while a `SIGTERM` (a real cancel) still ends it.
902
- - The release job runs the release's whole `test/integration/` suite, then the delta's test files again on the **previous release's dist** (the NEGATIVE).
902
+ - The release job runs the release's whole `test/integration/` suite, then each fix's test files again on the dist of **the newest published release before the fix was merged** (the NEGATIVE). `delta.mjs` groups the files by that baseline: for most fixes it is the previous release, but a fix for a bug that shipped inside the delta (a regression in v1.99.1 fixed for v1.99.2) is checked against the release that had the bug.
903
903
  - The base job runs the base release's own suite on its own published dist.
904
904
  - Each run uses the tree's own `npm test` command, with a reporter that records every test and subtest with its status and error.
905
905
  - **kernel-compat** (`compat.mjs`) supplies the base-set and catalog evidence: homescoop's kernel-compat run for the release.
906
906
  - Release runs share one group and intermediate ones are cancelled. When there is no finished run for the release commit, it dispatches `kernel-compat.yml` for that version (whose run is named `Kernel compat v<version>`) and waits up to 150 minutes.
907
907
  - It reads the run's report artifact, and **re-runs every regressing package once** (a dispatch with that `set`).
908
908
  - A regression that doesn't reproduce is a `compat-flake`; one that does is a `compat-regression`. A crash that reproduces and doesn't happen on the reference kernel is a `compat-crash`, which record FAILs in code.
909
+ - A run that failed with no regression in its report is a `compat-incomplete`, missing evidence and not a regression. It names the shards that left no report (for example, a shard that lost its bench runner), and those shards' failed jobs are re-run once first.
909
910
  - **review:** `findings.mjs` decides in code, per pull request:
910
911
  - `negative` (a fix's test fails on the previous dist and passes on the release) or `passes` (a feature's test passes);
911
912
  - otherwise a finding: `no-test`, `no-negative`, `fails-on-release`, `not-run`, `prev-not-run` or `no-titles`.
@@ -12114,7 +12114,7 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
12114
12114
  var EARLY_WHOLE_FILE = 64 * 1024;
12115
12115
 
12116
12116
  // src/version.ts
12117
- var KERNEL_VERSION = true ? "1.100.3" : "0.0.0-dev";
12117
+ var KERNEL_VERSION = true ? "1.100.4" : "0.0.0-dev";
12118
12118
  var OS_RELEASE = "6.0.0-slicc";
12119
12119
  function procVersion() {
12120
12120
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -14017,6 +14017,7 @@ var KernelTty = class {
14017
14017
  this.wake();
14018
14018
  }
14019
14019
  resize(cols, rows) {
14020
+ if (cols === this.cols && rows === this.rows) return;
14020
14021
  this.setSize(cols, rows);
14021
14022
  this.signal(SIG.WINCH);
14022
14023
  }
@@ -14391,6 +14392,9 @@ function terminalOf(ctx, fd) {
14391
14392
  }
14392
14393
  var json4 = (value) => ({ ok: true, kind: "json", json: value });
14393
14394
  var done3 = { ok: true, kind: "void" };
14395
+ function sizeKey(rows, cols) {
14396
+ return `${rows}x${cols}`;
14397
+ }
14394
14398
  function ptySyscall(req, ctx) {
14395
14399
  switch (req.op) {
14396
14400
  case "pty-open": {
@@ -14423,9 +14427,11 @@ function ptySyscall(req, ctx) {
14423
14427
  case "pty-packet":
14424
14428
  masterOf(ctx, req.fd).packet = req.on;
14425
14429
  return done3;
14426
- case "pty-winsz-set":
14427
- terminalOf(ctx, req.fd).resize(req.cols, req.rows);
14430
+ case "pty-winsz-set": {
14431
+ const tty = terminalOf(ctx, req.fd);
14432
+ if (ctx.sizesRead?.get(tty) !== sizeKey(req.rows, req.cols)) tty.resize(req.cols, req.rows);
14428
14433
  return done3;
14434
+ }
14429
14435
  }
14430
14436
  }
14431
14437
 
@@ -15969,6 +15975,7 @@ var WasmProcess = class {
15969
15975
  for (const listener of this.stateListeners) listener("continued", SIG.CONT);
15970
15976
  }
15971
15977
  blocks = /* @__PURE__ */ new WeakMap();
15978
+ sizesRead = /* @__PURE__ */ new WeakMap();
15972
15979
  async syscall(req, cancelled, block) {
15973
15980
  this.options.onSyscall?.(req);
15974
15981
  const started = performance.now();
@@ -16039,7 +16046,17 @@ var WasmProcess = class {
16039
16046
  const owner = this.options.owners ? this.ttyOwner() : void 0;
16040
16047
  const guard2 = this.guarded();
16041
16048
  const { outputFilter } = this.options;
16042
- const ctx = { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner, outputFilter };
16049
+ const sizesRead = this.sizesRead;
16050
+ const ctx = {
16051
+ pid: this.pid,
16052
+ fds: this.fds,
16053
+ ptys,
16054
+ jobs,
16055
+ guard: guard2,
16056
+ owner,
16057
+ outputFilter,
16058
+ sizesRead
16059
+ };
16043
16060
  return ptySyscall(req, ctx);
16044
16061
  }
16045
16062
  return await this.procSyscall(req, cancelled);
@@ -16675,8 +16692,11 @@ var WasmProcess = class {
16675
16692
  case "tty-set":
16676
16693
  tty.tcsets(req.termios, req.flush === true);
16677
16694
  return { ok: true, kind: "void" };
16678
- case "tty-winsz":
16679
- return { ok: true, kind: "json", json: tty.winsize() };
16695
+ case "tty-winsz": {
16696
+ const size = tty.winsize();
16697
+ this.sizesRead.set(tty, sizeKey(...size));
16698
+ return { ok: true, kind: "json", json: size };
16699
+ }
16680
16700
  case "tty-pgrp-get":
16681
16701
  return { ok: true, kind: "json", json: jobs ? jobs.tcgetpgrp(tty, this.sid()) : this.pid };
16682
16702
  case "tty-pgrp-set":