Skip to content

0.14 --- a keystroke the environment keeps for itself, and the sense in which zero is the weaker claim - #38

Merged
Sunrisepeak merged 4 commits into
mainfrom
openkal-0.14
Sep 20, 2026
Merged

Sunrisepeak merged 4 commits into
mainfrom
openkal-0.14

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

openkal.terminal 的模式字加第三个位,条款 6.2 加一条决定「位怎么拼」的规则。起因是消费者报告 mcpplibs/openkal-musl#36:程序无法让每个按键以字节到达,因而被中断键结束。

本 PR 取代 #37 的方案(#37 的设计稿作为第一个提交保留在历史里),差异在于位的极性

方案

  • KAL_TERM_PASS_CONTROL(模式字位 2):1 = 环境不为自己保留任何按键,每个键以字节到达;0 = 环境可保留一组由自己定义的按键。1 方向是保证,0 方向是许可;保留哪些键属于环境,规范不列举(条款 7.1)。
  • 位的覆盖面是「环境保留按键的全部机制」,不是中断键一个。否则同一个模式字在 Linux 上 ^S 冻终端而 Windows 不冻。
  • 极性取「放行」而不是「消费」:旧实现读回 0 是真话(它确实不放行),于是不需要条款 6.2 的例外、不需要强制 props 位、没有语义债。条款 6.2 因此新增一句一般规则:a position is assigned the sense in which zero is the weaker claim
  • set_mode 旁两条规则:请求值与当前值相同的位不写(多机制的位上,这条决定了「只改回显的程序不会恢复用户已释放的按键」);模式不是结束输入的方式(关行组装不得让读返回 0,条款 7.4)。要「会放弃的读」用 openkal.timeout
  • KAL_VERSION_MINOR 从 11 校正到 14:每个实现的 kal_version 就是 return KAL_VERSION;,所以停滞的数字是整个生态对外的自述,条款 6.2 给 load 期绑定消费者的那个比较一直是两个相等的数。新增 tools/check-version.sh,CI 同时证明它会拒绝漂移。
  • §11 条目 20 记录准入依据(同条目 10 文件锁)、缺失时的代价、被否决的反向极性、以及一个位无法记录的混合态。

验证

  • tools/check-version.shcheck-declarations.sh(104 names)、check-types.sh(175 declarations)、gen-macros.sh 重生成无 diff、mcpp build 全绿。
  • 一致性套件对 openkal-linux(本分支):199 held, 0 did not hold(在带尺寸的 pty 中运行,终端段全部执行),kal_version = 0xe0000
  • 端到端(^C 以 0x03 到达)在 openkal-musl 侧以 pty 探针与宿主 C 库对照,见该仓库同名分支。

生态

规范先行,随后 mcpp-index 注册;四个实现(linux / macos / windows / emscripten)并行适配;openkal-uefi、openkal-opensbi 跟随;openkal-musl 与 openkal-llvm-runtime 收尾。分支名在各仓库一致:openkal-0.14

设计稿、执行计划与对 #37 的 review 在 .agents/docs/2026-09-20-*

… keystrokes, with the cross-repo plan

A design proposal, no implementation. Full design and task graph in
.agents/docs/2026-09-18-kal-term-control-design.md; arising from consumer
report mcpplibs/openkal-musl#36 (a program cannot enter raw mode or keep
Ctrl+C from killing it).

* The position pair. KAL_TERM_CONTROL (mode word bit 2): 1 = the environment
  consumes reserved control keystrokes, 0 = every keystroke is a byte,
  including 0x03. KAL_TERM_PROP_CONTROL (props word bit 2): the
  implementation distinguishes the position.

* Why a third bit and not a fold into LINE_EDIT. readline turns line
  editing off and keeps control-key interruption on every platform (ICANON
  off + ISIG on; ENABLE_LINE_INPUT off + ENABLE_PROCESSED_INPUT on); the
  orthogonal bit is the native shape and the only 7.1-conformant one.

* Why the props bit is not optional. For this position alone, clause 6.2's
  unassigned-reads-zero does not match released behaviour (openkal-linux
  preserves ISIG): a program that needs the keystrokes-are-data guarantee
  shall enquire kal_terminal_props first. Recorded as the normative
  exception, closed by the claim-is-a-claim principle of clause 7.11.

* The dependency graph. openkal 0.14 (hard first) -> mcpp-index
  registration -> openkal-linux/windows/macos in parallel -> openkal-musl
  last (largest change: the ioctl dispatcher routes to kal_terminal_* and
  cfmakeraw becomes correct for free).

Documents and comments carry no emoji.
…in which zero is the weaker claim

openkal.terminal gains a third position in the mode word, and clause 6.2
gains the rule that decides how a position is spelled.

* KAL_TERM_PASS_CONTROL. Set, every keystroke reaches the program as the
  bytes it produces, including the ones an environment reserves for itself;
  clear, the environment may reserve a set of its own choosing. Which
  keystrokes those are belongs to the environment: an interface enumerating
  them would require of every environment what one of them spells. The
  position covers every mechanism by which the environment keeps a keystroke
  and not the interrupt alone, so that one mode word does not mean two things
  on two environments.

* The position is spelled so that ZERO IS THE WEAKER CLAIM, and clause 6.2
  now states that as a rule rather than leaving it to each assignment. An
  implementation released before 0.14 reads as zero and thereby says
  something true about itself. The arrangement in which zero would have been
  the guarantee needed an exception to clause 6.2 and a property position
  beside the mode position, to repair a hazard the spelling itself removes;
  it is recorded in SPEC.md entry 20 as considered and not adopted.

* Two rules beside set_mode, both of which a multi-mechanism position makes
  visible. A position whose requested value is the one in effect is not
  written, so a program turning the echo off does not restore keystrokes its
  user had released. And a mode is not a way to end the input: an
  implementation that turns line assembly off shall not make a read report
  zero while input has not ended, which clause 7.4 says denotes the end of
  it. A bound upon waiting is stated by openkal.timeout.

* KAL_VERSION_MINOR was 11 against a package at 0.13, and every
  implementation answers kal_version with that constant --- so the
  comparison clause 6.2 gives a consumer bound at load was between two
  equal numbers on every implementation there is. Corrected to 0.14.0 and
  checked by tools/check-version.sh, which CI also proves rejects a drift.

* The suite observes the position in the only terms it has: asking for it is
  not an error, what is read back is either the position or zero, and the
  terminal is left as it was found. Whether the keystroke then arrives as a
  byte is measured above a C environment, upon a pseudo-terminal.

Arising from consumer report mcpplibs/openkal-musl#36. Design, execution plan
and the review of the earlier proposal are in .agents/docs/2026-09-20-*.

Documents and comments carry no emoji.
…ms reads differently

`sed -i` takes the next argument as a backup suffix there, so the probe
edited a file named by the expression and the check it was proving reported
success. Written beside and moved over instead.
…his wave

The Web target produces openkal-conformance.js beside a .wasm, and the
selection named only the extensionless and the .exe forms --- so a build that
had just succeeded was reported as 'expected exactly one suite to have been
produced, found 0', which names neither the cause nor anything a reader can
act upon. Measured on mcpp 2026.9.18.3, where the engine's Web output has
that shape.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant