Skip to content

showcase: fix #3002 — keep corrupt-state warnings off TUI stderr - #10

Closed
innocarpe wants to merge 95 commits into
mainfrom
fix/issue-3002-state-stderr-tui-safe
Closed

showcase: fix #3002 — keep corrupt-state warnings off TUI stderr#10
innocarpe wants to merge 95 commits into
mainfrom
fix/issue-3002-state-stderr-tui-safe

Conversation

@innocarpe

Copy link
Copy Markdown
Owner

Showcase dual PR (portfolio only)

Upstream: open against Yeachan-Heo/gajae-code base dev.

Fixes Yeachan-Heo#3002 — workflow-state corrupt/out-of-band warnings no longer paint process.stderr during interactive TUI; routed via TUI-safe file logger.

changeroa and others added 30 commits July 22, 2026 18:36
…2896)

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
Co-authored-by: victor <victor@victors-MacBook-Pro-2.local>
- carry authoritative recommendation metadata through ask, gate, and Rust action frames
- mark only the recommended Telegram body option without changing callback or answer identity
- reload older daemons and document the additive action metadata

Tests:
- focused ask, gate, Telegram, native replay, and Rust recommendation suites
- bun --cwd=packages/coding-agent run check; bun run check:rs; bun run ci:check:full
- clean upstream/dev full-suite baseline confirms remaining environment failures pre-exist
* fix(python-sdk): correlate protocol responses

* fix(python-sdk): preserve nested frame payloads
…-Heo#2499)

* fix(ultragoal): fail closed on fuzzy objective path sniffing

isKnownUltragoalObjective previously treated any objective mentioning both
goals.json and ledger.jsonl as Ultragoal-owned. That can mis-arm completion
and drop guards. Accept only the exact default aggregate objective.

* style: biome format for ultragoal objective fail-closed tests
…val (Yeachan-Heo#2503)

If the user already named ultragoal or team in the current turn, that is
execution consent. Skip the redundant final approval re-ask and hand off
to the named execution skill.

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…chan-Heo#2908)

* fix(telegram): make session close terminal outcome authoritative

- Route compiled managed owners through exact supervisor and pidfd-backed child shutdown.
- Publish terminal evidence and session_closed before blocking teardown.
- Preserve fail-closed generation, dispatch, lease, and replacement guards.

Tests:
- Focused lifecycle, tmux integration, generation guard, compiled live close.

* fix(ci): refresh Telegram native authority digest

- Update the generated native authority digest after the notification server type surface changed.

Tests:
- bun scripts/telegram-daemon-generation-guard.ts --validate-current-tree
- bun test scripts/telegram-daemon-generation-guard.test.ts

* fix(ci): bump daemon generations for native authority refresh

The session-close terminal outcome change refreshes the protected native
authority declaration surface (packages/natives/native/index.d.ts adds
bounded frame-delivery acknowledgement), which the daemon generation
guard fences for every family behind strictly higher generations. Raise
DAEMON_GENERATION from 19 to 20 and CHAT_DAEMON_GENERATIONS discord/slack
from 8 to 9, record the history entries, and regenerate the authority
manifest digests with the repository generator so the committed manifest
byte-matches the tree.

* fix(daemon): advance shared authority generations

- Advance Telegram, Discord, and Slack daemon generations for the shared native notification authority change.
- Refresh generation attestations and the Telegram generation regression assertion.

Tests:
- bun scripts/telegram-daemon-generation-guard.ts --validate-current-tree
- bun test scripts/telegram-daemon-generation-guard.test.ts packages/coding-agent/test/notifications-telegram-daemon.test.ts
- bun --cwd=packages/coding-agent run check

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…#2509)

* fix(coding-agent): keep model selector open for role assignments

* fix(test): widen getApiKey mock return type to string | undefined

---------

Co-authored-by: GJC Bot <gjc-bot@gajae-code.local>
Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…-style autocomplete) (Yeachan-Heo#2519)

Port Claude Code's prompt-suggestion autocomplete as a native GJC
feature. After each agent turn, when the promptSuggestions setting is
enabled and the composer is empty, a smol-model prediction of the
user's likely next prompt renders as dim ghost text in the composer;
Tab accepts it, typing dismisses it, and a new turn clears it.

- utils/prompt-suggestion: transcript builder, wrapper/label
  sanitizer, and heuristic suppression gate (silence on evaluative,
  meta, agent-voice, prose-shaped, or overlong output) around a
  completeSimple call with disableReasoning and a small token budget
- modes/prompt-suggestion-controller: lifecycle owner with a
  generation token so stale predictions, mid-flight turns, and
  composer edits invalidate in-flight results
- editor integration: inline-hint ghost text through the existing
  autocomplete provider (empty composer only), Tab acceptance via the
  editor onTab hook that never consumes Tab when the composer has text
- settings: promptSuggestions boolean, default off (each turn costs a
  smol-model call); JSON schema regenerated
…n test mocks (Yeachan-Heo#2921)

Yeachan-Heo#2521 renamed the WorkflowGateEmitter capability but its older merge-base missed emitter mocks that landed on dev via Yeachan-Heo#2908, breaking check:types and shard-6/shard-8 runtime tests on post-merge dev.

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…an-Heo#2922)

- Revalidate one append-only candidate change against the managed scope.
- Omit unstable or replaced candidates without discarding stable rows.
- Preserve scope-level and unexpected metadata failures as request errors.

Tests:
- bun test packages/coding-agent/test/notifications-recent-activity.test.ts packages/coding-agent/test/notifications-lifecycle-command-routing.test.ts
- bunx biome check packages/coding-agent/src/sdk/bus/recent-activity.ts packages/coding-agent/test/notifications-recent-activity.test.ts
- git diff --check
* fix(notifications): hand off v0.10 live daemon owners

* fix(notifications): complete legacy attestation during startup

* fix(notifications): attest exact v0.10 owner locks

* fix(notifications): preserve legacy lock narrowing

* fix(notifications): keep legacy handoff retryable

* fix(notifications): fence v0.10 daemon handoff

* test(notifications): await topic compensation

* test(notifications): preserve recommended ask coverage

* fix(notifications): default controller incarnation lookup

* fix(notifications): fence legacy daemon ownership

* fix(notifications): reclaim dead Windows v0.10 owners

* test(notifications): pin legacy fence platform

* fix(notifications): fence Windows legacy parent

* fix(notifications): reclaim stopped v0.10 locks

* fix(notifications): complete attested legacy reload

* fix(notifications): allow attested macOS handoff

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
* fix(session): recover atomic managed publish on Linux

* fix(natives): gate retained publish to Linux

* fix(session): fail closed on uncertain publish outcomes

* chore(sdk): bump daemon generation for native authority

* fix(session): preserve committed fork publication evidence

* fix(natives): validate atomic publish outcomes

* fix(natives): classify direct rename outcomes

* fix(ci): validate native publish contract gates

* fix(session): validate retained publish outcomes

* fix(session): preserve invalid publish diagnostics

* fix(session): preserve managed publish diagnostics

* fix(natives): satisfy retained diagnostic lint gates

* fix(session): harden managed publish recovery

* fix(natives): enforce trusted publish fallback

* fix(session): fail closed on unproven managed scope recovery

* fix(session): preserve managed migration authority fences

* fix(session): fence strict fork cleanup to exact tree

* fix(session): retain authority-fenced fork cleanup

* fix(session): rebind strict fork resident cache

* fix(session): retain verified cleanup authority

* fix(natives): preserve baseline and fork durability

* fix(natives): type selected embedded variant

* fix(natives): preserve committed retained tree outcomes

* fix(session): accept validated artifact detach replay

* fix(session): bind artifact replay to receipt identity

* test(session): tolerate retained artifact namespace replay

* fix(session): fence replay completion roots

* fix(natives): complete descriptor-bound tree cleanup

* fix(natives): fence final descriptor unlink

* test(natives): isolate tree exchange hooks

* fix(session): preserve replay and unlink authority

* fix(natives): retain unprovable terminal cleanup

* fix(session): retain unprovable cleanup authority

* fix(natives): report retained recovery cleanup

* fix(session): preserve strict fork causal errors

* fix(session): retain exact cleanup authority

* chore(daemon): refresh recovery authority digest

* style(daemon): format lifecycle comment

* chore(daemon): fence native authority changes

* fix(sdk): retain pending session cleanup

* fix(local): retain pending legacy migration cleanup

* chore(daemon): refresh generation 23 authority manifest

* test(natives): cover retained POSIX cleanup

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…ts and replay (Yeachan-Heo#2933)

* fix(session): advance typed retained cleanup authority through receipts and replay

Post-Yeachan-Heo#2818 on POSIX, native exact file removal always returns typed
cleanup_pending with verified detached identity/path evidence (quarantine
retained; descriptor-bound final unlink deliberately unavailable). Callers
that still treated the result as a hard failure or a permanently pending
state stalled every delete/consume/reclaim flow: post-merge dev CI run
29952649477 (shards 2/4/6/7) and the 16-failure local repro at the merge
SHA, plus 27 daemon/telegram failures.

- broker saved-session delete + lifecycle reconcile: accept typed retained
  authority only when the detached evidence matches the authorized
  quarantine plan, persist it in durable receipts/ledger, and advance the
  state machine. Genuine pending (io_error, identity_mismatch, or evidence
  outside the plan) still returns typed cleanup_pending; crash hooks and
  terminal_uncertain fencing are unchanged.
- lifecycle replay/absent checks: a completed file's recorded retained
  quarantine is accepted only at its receipt-bound path and identity.
- managed storage consume/remove: accept typed retained results carrying
  concrete recovery/detached evidence; every other code still throws.
- daemon ownership/recovery (telegram, chat, notification service): accept
  exactUnlink cleanup_pending only with a nonempty detachedPath and proven
  canonical absence; recovery sweep records retained detached evidence
  without counting recovery failures.
- tests: contract-driven updates (canonical lifecycle names absent while
  only .gjc-delete- quarantine evidence may remain; DAEMON_GENERATION 23
  per the merged contract) plus retained-authority regressions proving
  completion + exact replay and refusal of forged retained evidence.

Co-Authored-By: Yeachan-Heo <yeachan-heo@gajae.dev>

* fix(notifications): bump daemon generations for typed retained cleanup authority

The retained-authority head commit changed guarded Telegram and Discord/Slack
lifecycle declarations (detachTransitionMarker, reclaimDeadDaemonOwner,
unlinkOwnershipLockExactly, unlinkExactChatDaemonOwnerLock) without a
generation bump, so the daemon generation guard correctly rejected the tree.
Base already speaks Telegram generation 23 and chat generations 10; bump to
Telegram 24 and chat 11 with contract comments, refresh the literal
generation assertion, and regenerate the semantic manifest.

Co-Authored-By: Yeachan-Heo <yeachan-heo@gajae.dev>

* test(session): assert retained-authority delete success contract in shard-1 topology

The independently-reviewed retained-cleanup behavior completes typed retained
deletions instead of stalling on terminal cleanup_pending. Replace the stale
pending expectations with the success contract: broker_response carrying the
exact target sessionId, canonical transcript and artifact-directory absence,
idempotent replay compared on stable broker semantics (frame ids are
per-invocation), and unchanged foreign-workspace, loser-candidate, and
idempotency-conflict isolation assertions. Tests only; no production changes.

Co-Authored-By: Yeachan-Heo <yeachan-heo@gajae.dev>

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…eachan-Heo#2936)

shortenPath used a bare filePath.startsWith(home) with no path-separator
boundary, so a sibling directory that merely shares a string prefix with $HOME
was rewritten to a corrupt ~-path: shortenPath("/home/woodyx/notes.txt",
"/home/woody") returned "~x/notes.txt", and "/home/woody-backup/x" became
"~-backup/x". This value feeds the model-facing system-prompt cwd and
contribution redaction, not just TUI cosmetics.

Require an exact match or a real separator boundary after home before
abbreviating. Fixed in both copies (tools/render-utils.ts and
tools/browser/screenshot-format.ts) and added regression tests for
prefix-sharing siblings, exact-home, and paths outside home.
…eachan-Heo#2938)

BlobStore.put() (async) violated the module's owner-only creation contract
that putSync/putImmutableSync honor: it relied on Bun.write to implicitly
create the parent directory with the process umask (e.g. 0755) and wrote the
blob file at the umask default before a follow-up chmod to 0600, leaving a
group/other-readable creation window (and a persistently non-owner-only
directory). A managed session scope's owner-only tree snapshot fails closed on
any group/other-readable descendant.

Create the directory 0700 and the file 0600 at creation via fsp.mkdir +
fsp.writeFile, mirroring putSync/putImmutableSync. Add the async put() case to
the owner-only permission test (it fails on the old code, passes now).
# Conflicts:
#	packages/natives/native/index.js
#	scripts/telegram-daemon-generation-manifest.json
…han-Heo#2943)

Following Yeachan-Heo#2827 (GJC_{SMOL,SLOW,PLAN}_MODEL), 13 more environment variables are
documented and advertised in `gjc --help` but were read only under the legacy
PI_* name, so setting the documented GJC_* variable was a silent no-op:

  GJC_NO_PTY, GJC_NO_TITLE, GJC_TIMING, GJC_EDIT_VARIANT,
  GJC_FORCE_IMAGE_PROTOCOL, GJC_ALLOW_SIXEL_PASSTHROUGH, GJC_TUI_WRITE_LOG,
  GJC_HARDWARE_CURSOR, GJC_BLOCKED_AGENT, GJC_SUBPROCESS_CMD,
  GJC_TASK_MAX_OUTPUT_BYTES, GJC_TASK_MAX_OUTPUT_LINES, GJC_MAX_AST_FILES

Resolve GJC_* first with PI_* fallback (repo-wide convention). String reads use
$pickenv; add $pickflag/$pickenvpos (GJC-first analogs of $flag/$envpos,
mirroring $pickenv/$pickCredentialEnv) for the flag and positive-int sites.

Preserve CLI authority: --no-pty / --no-title (and --acp) set the canonical
GJC_NO_PTY / GJC_NO_TITLE name (plus PI_* for back-compat) via the extracted,
unit-tested applyTerminalControlFlagsToEnv, so an explicit flag wins over a
user's GJC_NO_PTY=0 under GJC-first resolution.

Keep the foundational logger off the env module's dependency graph: logger.ts
resolves GJC_TIMING inline instead of importing ./env, preserving the
tab-worker native-free runtime contract (issue-2598-repro).

launch-tmux keeps its injected-env DI contract by resolving GJC-first against
its local env param. Add $pickflag/$pickenvpos and
applyTerminalControlFlagsToEnv unit tests (incl. the GJC=0/PI=1 precedence and
the --no-pty-beats-GJC_NO_PTY=0 CLI-authority invariant).
…#2933 retained cleanup authority contract (Yeachan-Heo#2941)

* test(session-manager): align session-directory tests with Yeachan-Heo#2933 retained cleanup authority contract

Update 12 session-directory tests to match the reviewed Yeachan-Heo#2933 contract:
- Successful retained-authority paths now return {kind:"deleted", tombstonePath}
  instead of stalling on {kind:"cleanup_pending", phase:"artifacts"|"transcript"}
- .removing retention cases advance to genuine {kind:"cleanup_pending",
  phase:"transcript", tombstonePath, message} with exact descriptor-bound message
- Forged chain, append-only quarantine, fresh-process replay, and dangling
  replacement tests engineer genuine transcript-phase pending via exactUnlink
  io_error while preserving all forged/dangling/append-only/replay assertions
- Stale tombstone test verifies replacement gets its own new tombstone (not reusing
  the stale one), confirming the stale tombstone does not authorize replacement deletion

Closes Yeachan-Heo#2939

* test(session-manager): guarantee exactUnlink mock restoration via outer try/finally

PR Yeachan-Heo#2941 red-team (exact-head REQUEST_CHANGES) flagged that the
exactUnlink mock in the forged-cleanup-chain test was restored outside
guaranteed cleanup. Wrap the entire post-first-delete sequence (forged
receipt write + second deleteManagedSessionCandidate call) in an outer
try/finally so unlink.mockRestore() runs even on assertion failure.
The inner finally { remove.mockRestore(); } is preserved unchanged.

No production changes; test-only.

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…eachan-Heo#2948)

Missing resident image blobs materialize as human-readable placeholders.
Replaying those strings as OpenAI Responses input_image.image_url makes
Codex reject every turn with invalid_value. Sanitize replay content so only
http(s) and data:image URLs are kept; retain file_id-only parts when present
and drop otherwise.

Fixes Yeachan-Heo#2924
…end (Yeachan-Heo#2946)

On macOS, the first write-append open of a managed transcript can change only
ctime (APFS write-provenance) while leaving dev/ino/size/mtime/content intact.
appendSync now allows one bounded re-capture + retry for that case and still
fail-closes on real races or a second ctime transition.

Fixes Yeachan-Heo#2944
Alibaba Token Plan models (token-plan.ap-southeast-1.maas.aliyuncs.com)
routinely exceed the 120s first-event watchdog on cold starts and heavy
reasoning (qwen3.8-max-preview, deepseek-v4-pro). Pass a 300s fallback
to getStreamFirstEventTimeoutMs when model.provider is alibaba-token-plan
in both openai-completions and openai-responses transports.

Caller option (streamFirstEventTimeoutMs) and env var
(PI_STREAM_FIRST_EVENT_TIMEOUT_MS) still take precedence. Global default
and inter-event idle timeout are unchanged.
…#2950)

createAgentSession already awaited initializeLocalRoot for cold start (Yeachan-Heo#2797),
but switchSession only swapped SessionManager identity. Wire
getManagedLegacyLocalMigrationSource into AgentSession local-protocol options
and await initializeLocalRoot after a durable different-session switch so
local:// resolution is safe immediately after /resume.

Fixes Yeachan-Heo#2925
…eachan-Heo#2959)

* fix(notify): make /settings Telegram pairing match `notify setup`

The /settings Notifications tab built its Telegram setup preflight in
selector-controller.ts using only a PID-liveness check (process.kill),
never verifying the process incarnation. The `gjc notify setup` CLI path
additionally compared the persisted daemon incarnation against the current
incarnation for that PID.

As a result, a stale daemon-state file whose PID had been recycled by an
unrelated live process made the /settings preflight falsely report a live
daemon owning the token. resolveTelegramSetupPollingPolicy then returned
requires_explicit_chat / cancel_foreign_or_unknown_owner / reuse_stored_chat
instead of `discover`, blocking discovery pairing — while `notify setup`
worked because its incarnation check treated the stale state as no daemon.

Consolidate both call sites onto a single incarnation-aware
resolveTelegramSetupPreflight in telegram-daemon.ts (with injectable
readDaemonState/pidAlive/pidIncarnation), so /settings pairing behaves
identically to the CLI. Remove the now-duplicated logic, the unused
daemonPidAlive helper, and dead imports.

Adds test/telegram-setup-preflight.test.ts covering the stale-recycled-PID
discover-policy case, dead PID, read failure, and genuine-live reuse.

* fix(notify): fence post-setup identity by incarnation

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
* fix(edit): serialize concurrent same-path mutations (Yeachan-Heo#2900)

Add a path-scoped mutation coordinator (in-process mutex always; durable
cross-process file lock on the real filesystem) and use it for applyPatch and
replace so disjoint concurrent edits cannot silently overwrite each other.
Commit-time content check rejects mid-flight external mutations.

Fixes Yeachan-Heo#2900

* fix(edit): enable cross-process lock on LspFileSystem patch path

executePatchSingle uses a disk-backed LspFileSystem that is not
defaultFileSystem by identity, so durable locking was silently skipped.
Opt in explicitly and add a two-process regression for that adapter shape.

* fix(edit): keep previewPatch read-only and use Promise.withResolvers

Skip durable path locks on dryRun so preview does not mkdir .lock under
read-only parents, and use Promise.withResolvers for the path mutex waiters.
Oreochococukie and others added 28 commits July 23, 2026 18:04
…3000)

Rustdoc JSON can exceed the response ceiling through legacy cache reads, transport decompression, or gzip expansion. Bound every pre-parse source, disable automatic transport decoding, and reject encoded responses so no hidden decompression step bypasses MAX_BYTES.

Constraint: Preserve the existing docs.rs handler, cache format, rendering, and caller-abort behavior

Rejected: Streaming rustdoc parser | broader redesign unrelated to the bounded payload defect

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep cached, transported, and expanded rustdoc bodies within MAX_BYTES before parsing

Tested: Docs.rs 6 tests; coding-agent check; coding-agent binary build; live docs.rs identity-encoding smoke; git diff --check
…es (Yeachan-Heo#2930, Yeachan-Heo#2931) (Yeachan-Heo#2987)

* feat(coding-agent): add prompt reconciliation SDK query

* feat(coding-agent): add model profile SDK capability

* fix(coding-agent): harden SDK capability reconciliation

* fix(coding-agent): preserve prompt failure outcomes

* chore(coding-agent): regenerate docs index after rebase

* fix(coding-agent): reload model profiles before lifecycle validation

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…vider to generate_image (Yeachan-Heo#2998)

* feat(coding-agent): add Alibaba Bailian (Token Plan) wan2.7-image provider to generate_image

The alibaba-token-plan chat provider ships with built-in presets, but image
generation had no Bailian backend. Add 'alibaba' as an image provider:

- generate_image dispatches to the Bailian sync multimodal-generation
  endpoint (wan2.7-image by default, model overridable via
  providers.imageModel), downloads the short-lived OSS result URLs
  immediately, and supports image editing via input images as data URLs
- credentials resolve from ALIBABA_TOKEN_PLAN_API_KEY or the registered
  alibaba-token-plan provider key; auto-detect tries it last so existing
  priority is unchanged
- providers.image settings enum, session wiring, and the selector prompt
  accept 'alibaba'

Tested: bun test packages/coding-agent/test/image-gen-alibaba.test.ts (8 pass),
plus image-input/block-images/model-profiles-catalog/provider-onboarding suites.

* chore: regenerate config schema and add changelog entry for alibaba image provider
… test

After Yeachan-Heo#2988, the retained-root traversal rejects a swapped-in junction with
'plain-diff path changed entry kind' before reaching the per-entry open
error. Both messages prove the secret is not readable; assert either.
…-Heo#3007)

Serialized global-freeze repair exception after exact-head Dev CI run 29998834389 completed successfully.\n\ngaebal-gajae
…ntity check

On Windows, a directory's parent-index size/timestamps can lag the open
handle right after its contents were written, making walk_directory's
DirectoryEntry::matches fail spuriously ('plain-diff entry changed while
it was being captured') during index_tree. For plain directories, the
64-bit file id + kind bits are the stable identity; keep strict
size/timestamp equality for files and reparse points.
Serialized recovery exception after exact-head Dev CI run 30000966428 completed successfully.\n\ngaebal-gajae
…Heo#2987/Yeachan-Heo#3007 merges

- model-profiles: import the assignment-target id type from
  models-config-schema instead of model-registry, so the coordinator MCP
  model-preset chain no longer reaches the session-host import graph
  (verify:sdk-canonicalization).
- input-controller-escape + prompt-action-skill-autocomplete: stub
  keybindings.getDisplayString required by platform shortcut labels (Yeachan-Heo#2999).
- notifications-session-switch: expect the sanitized prompt failure
  message emitted by prompt reconciliation (Yeachan-Heo#2987).
- telegram-baseline-manifest: update parity row counts 546->558 (91->93
  rows per adapter).
# Conflicts:
#	scripts/telegram-daemon-generation-manifest.json
Route runtime and CLI endpoint rendering through one fail-closed formatter that removes user information, opaque paths, query values, and fragments while leaving outbound request URLs unchanged. Recursively redact sensitive request parameters and omit parse-failure response bodies that can echo those values.

Constraint: Replacement for Yeachan-Heo#2709 must retain request behavior and the previously approved diagnostic contract while closing the two demonstrated alternate leak fields.

Rejected: Scrub only known response values | an invalid remote response is attacker-controlled and cannot be safely enumerated.

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep raw MCP endpoints and response bodies confined to network processing; diagnostic metadata must remain fail-closed.

Tested: 10 focused runtime MCP and CLI tests; coding-agent Biome and type check; root workspace build; staged diff check.

Not-tested: Hosted CI matrix and live remote MCP interoperability.

Related: Yeachan-Heo#2709
…Yeachan-Heo#3010)

The semantic guard stopped hashing restricted platform implementations and the core pi-shell Process implementation when it replaced whole-file hashes. Include those existing authority boundaries while keeping unrelated shared-file edits outside the receipt.

Constraint: Preserve the semantic declaration guard and avoid restoring brittle whole-file coupling

Rejected: Restore whole-file native hashes | unrelated shared-file edits would again force daemon generation bumps

Confidence: high

Scope-risk: narrow

Directive: Treat restricted path-security implementations and core Process methods as daemon ownership authority

Tested: 39 telegram daemon guard tests; current-tree manifest validation; root check:tools; git diff --check

Not-tested: Hosted exact-head CI pending push
…an-Heo#3022)

* fix(notifications): fence malformed topic success

* chore(notifications): keep topic fence identity stable
Route workflow-state corrupt/out-of-band warnings through the file logger
instead of process.stderr so interactive prompts are not painted over.
CLI gjc state still surfaces structured warnings via StateCommandResult.stderr.

Fixes Yeachan-Heo#3002.
Import logger via @gajae-code/utils/logger subpath so the package barrel
(procmgr/ptree → natives) is not loaded by state-runtime gate tests.
@innocarpe innocarpe closed this Jul 29, 2026
@innocarpe
innocarpe deleted the fix/issue-3002-state-stderr-tui-safe branch July 29, 2026 14:54
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.

TUI prompt is visually corrupted by raw ultragoal/state warnings written to stderr