Merge branch 'codex/invariant-package-registration-gate' into codex/package-invariant-checks

# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-19-package-invariant-runtime-contracts.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-19-package-invariant-runtime-contracts.md
#	.agents/notes/implemented/architecture/2026-07-19-package-invariant-runtime-contracts.zh.md
#	.agents/notes/implemented/architecture/2026-07-19-package-owned-invariant-service.i18n.yaml
#	docs/rfc/INDEX.md
#	packages/AGENTS.md
This commit is contained in:
Tianyi Cui
2026-07-20 00:54:28 +08:00
683 changed files with 7058 additions and 2430 deletions

View File

@@ -2,7 +2,7 @@
The interactive terminal front door for DeepSeek Harness agents, built on [`@earendil-works/pi-tui`](https://www.npmjs.com/package/@earendil-works/pi-tui). It requires stdin and stdout TTYs; scripts and Loader pipes should compose [`@deepseek-ai/dsh-stdio`](../stdio/README.md) instead.
The implemented [TUI feature RFC](../../../docs/rfc/implemented/feature/2026-07-17-dedicated-full-screen-tui-front-door.md) owns the front-door decision; the [terminal-state snapshot RFC](../../../docs/rfc/implemented/testing/2026-07-18-tui-terminal-state-snapshots.md) owns its verification strategy.
The implemented [TUI feature Agent Note](../../../.agents/notes/implemented/feature/2026-07-17-dedicated-full-screen-tui-front-door.md) owns the front-door decision; the [terminal-state snapshot Agent Note](../../../.agents/notes/implemented/testing/2026-07-18-tui-terminal-state-snapshots.md) owns its verification strategy.
This package owns interactive terminal presentation and input only. It injects `agents`, `tools`, and `userInteraction`, then drives an agent created or resumed by app or developer code. Agent lifecycle, persistence, and the model-facing [`ask_user_question`](../tool-ask-user/README.md) tool remain separate composition entries.
@@ -47,15 +47,31 @@ The palette uses the standard 16-color ANSI foregrounds and SGR attributes, whic
### Interactive prompt input
**What the model sees**: Each non-empty editor submission becomes one text block, sent with `agent.send()` while the target agent is idle and `agent.steer()` while it is running. Slash commands and keybindings are TUI-only.
#### What the model sees
**Token effect**: Submitted text is retained under the agent loop's normal session-history and compaction rules. Headers, cards, Markdown rendering, status lines, plans, and help text add no tokens.
Each non-empty editor submission becomes one text block, sent with `agent.send()` while the target agent is idle and `agent.steer()` while it is running. Slash commands and keybindings are TUI-only.
#### Token effect
Submitted text is retained under the agent loop's normal session-history and compaction rules. Headers, cards, Markdown rendering, status lines, plans, and help text add no tokens.
#### KV Cache effect
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
### Interactive user-question answers
**What the model sees**: When a consumer calls `ctx.userInteraction.ask()`, this provider presents each question in order and returns selected option labels or `custom` text. Abort, cancellation, or UI disposal becomes `Error: ask_user_question was interrupted before the user answered` through `dsh-tool-ask-user`.
#### What the model sees
**Token effect**: Waiting and terminal overlays add no tokens; the resolved answer or error is model-visible only through the calling tool or plugin's result.
When a consumer calls `ctx.userInteraction.ask()`, this provider presents each question in order and returns selected option labels or `custom` text. Abort, cancellation, or UI disposal becomes `Error: ask_user_question was interrupted before the user answered` through `dsh-tool-ask-user`.
#### Token effect
Waiting and terminal overlays add no tokens; the resolved answer or error is model-visible only through the calling tool or plugin's result.
#### KV Cache effect
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
## Known Limitations and Deferred Work

View File

@@ -286,7 +286,7 @@ export class HeadlessTerminal implements Terminal {
return violations
}
/** Serialize terminal cells and metadata into a stable, reviewable golden. */
/** Serialize terminal cells and metadata into a stable, reviewable expected output. */
async snapshot(options: TerminalSnapshotOptions = {}): Promise<string> {
await this.flush()
const buffer = this.emulator.buffer.active

View File

@@ -53,7 +53,7 @@ async function checkpoint(
observedCheckpoints.add(name)
expect(terminal.themeViolations(), `${name} must remain theme-agnostic`).toEqual([])
const snapshot = await terminal.snapshot(options)
const path = join(SNAPSHOTS_DIR, `${name}.golden.txt`)
const path = join(SNAPSHOTS_DIR, `${name}.expected.txt`)
if (REFRESHING) {
await mkdir(SNAPSHOTS_DIR, { recursive: true })
await writeFile(path, snapshot)
@@ -497,7 +497,7 @@ describe('TUI terminal-state snapshots', () => {
afterAll(async () => {
expect([...observedCheckpoints].sort()).toEqual([...CHECKPOINTS].sort())
const files = (await readdir(SNAPSHOTS_DIR))
.filter(file => file.endsWith('.golden.txt'))
.filter(file => file.endsWith('.expected.txt'))
.sort()
expect(files).toEqual(CHECKPOINTS.map(name => `${name}.golden.txt`).sort())
expect(files).toEqual(CHECKPOINTS.map(name => `${name}.expected.txt`).sort())
})