Skip to content

feat(tmux-status): sync v3 conversation recovery mappings - #20

Merged
CubePlus1 merged 48 commits into
mainfrom
codex/tmux-status-contract-v3-sync
Aug 4, 2026
Merged

feat(tmux-status): sync v3 conversation recovery mappings#20
CubePlus1 merged 48 commits into
mainfrom
codex/tmux-status-contract-v3-sync

Conversation

@CubePlus1

@CubePlus1 CubePlus1 commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • consume strict tmux-status schema v3 while preserving v1/v2 compatibility
  • mirror the producer-owned schema/fixtures with SHA-256 integrity and a private-repository drift workflow skeleton
  • append immutable plugin migration 002 and reuse the existing scheduled job for idempotent pane/conversation recovery persistence
  • add deterministic ordinary CI; Codex review uses the repository-bound GitHub integration

Privacy and safety

  • unknown or conflicting identity evidence remains null/unknown
  • no PID, cwd, pane title, or recent-session heuristic becomes a conversation ID
  • no prompt, response, reasoning, terminal transcript, pane content, command text, or manual note is persisted
  • plugin failures remain isolated as degraded and do not block Core

Validation

  • pnpm test: 36 passed
  • pnpm typecheck: passed
  • pnpm build: passed
  • canonical schema/SHA checks: passed
  • official Skill validators (2) and Plugin validator: passed
  • CI / verify: passed and required

Review and blockers

  • Codex review is requested with @codex review through the existing GitHub integration; no OPENAI_API_KEY repository secret is needed.
  • TMUX_STATUS_CONTRACT_READ_TOKEN is not configured, so remote private-repository drift comparison remains non-required.
  • Producer PR must land before the remote drift copy can match tmux-status main.

Depends on CubePlus1/tmux-status#1.
Closes #19

Do not merge without user confirmation.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6e8e0f0c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +238 to +240
!Array.isArray(parsed.recovery) ||
parsed.recovery.length !== conversations.length ||
!parsed.recovery.every(validateRecoveryEntry)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cross-check recovery entries against pane conversations

Reject recovery arrays that are not the actual projection of panes[].agent_conversations. A payload containing conversation A in the pane and an independently valid conversation B in recovery passes because only the array length and each entry's shape are checked; /api/plugins/tmux-status/status then exposes a resume command and pane mapping that disagree with what TmuxObservationStore persists, potentially directing recovery tooling to the wrong thread or pane.

Useful? React with 👍 / 👎.

Comment thread plugins/tmux-status/src/store.ts Outdated
Comment on lines +33 to +38
return [
"unknown",
pane.pane_instance_id ?? paneIdentity(pane),
conversation.tool,
conversation.conversation_id_kind,
].join(":");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Distinguish separate unknown process observations

Include an observation-specific discriminator for unknown conversations. If an unknown Codex/Grok process exits and another starts in the same long-lived pane—or two unknown processes of the same tool coexist—both receive this identical key; later snapshots overwrite the first row, while two entries in one snapshot cause the second upsert to be skipped because their timestamps are equal. This merges unrelated process lifetimes and loses recovery evidence even though no conversation ID needs to be inferred.

Useful? React with 👍 / 👎.

Comment thread plugins/tmux-status/src/adapter.ts Outdated
Comment on lines +133 to +134
!Number.isInteger(value.pane_pid) ||
value.pane_pid !== value.pid ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject nonpositive v3 pane PIDs

Enforce the v3 contract's minimum: 1 for both pid and pane_pid. A pane with both values set to 0 or a negative integer currently passes this equality check (and can pass the rest of validation when it has no conversations), after which the invalid identity is returned and persisted; the controlled schema explicitly disallows these values.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85cb90c0b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread README.md
| `database` | PostgreSQL 连接(与 docker-compose 默认值对应) |
| `plugins.screen-time` | 屏幕采样开关、频率与空闲阈值(默认启用) |
| `plugins.tmux-status` | 外部 executable、超时、采样频率与异常阈值(默认禁用) |
| `plugins.tmux-status` | 外部 executable、超时、采样频率、异常阈值,以及 v3 Agent conversation↔pane 恢复映射(默认禁用) |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Synchronize the roadmap with the v3 contract

Update the roadmap in this same change: this row announces v3 recovery mappings, but README.md:164-165 still says the observation layer depends on JSON v2 and links only the v2 producer issue. That leaves the repository's roadmap and public issue trail pointing at the superseded contract instead of the feature delivered here.

AGENTS.md reference: AGENTS.md:L100-L106

Useful? React with 👍 / 👎.

Comment on lines +165 to +166
version >= 3 &&
(!Number.isInteger(value.pid) || Number(value.pid) < 1 ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject invalid v3 resource metrics

Extend the v3 validation to enforce the controlled schema's resource constraints. A producer response with negative cpu_percent/memory_mb or a fractional or negative process_count currently passes because the shared check only requires finite numbers and this v3 block adds a constraint only for pid; TmuxObservationStore.observe then persists the invalid CPU and memory values into its minute aggregates.

Useful? React with 👍 / 👎.

Comment on lines +198 to +199
!Array.isArray(value.agent_conversations) ||
!value.agent_conversations.every(validateConversation))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject additional properties in v3 payloads

Enforce the v3 schema's additionalProperties: false rules instead of returning the original object after shape checks. If the external producer includes an undeclared top-level or conversation field such as prompt or terminal_transcript, validateConversation ignores it and parseStatusPayload accepts it, after which the status route returns that field verbatim despite the controlled contract and plugin privacy boundary.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff70738e5a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/store.ts Outdated
conversation.conversation_id_status === "confirmed" &&
conversation.stable_mapping_key
) {
return conversation.stable_mapping_key;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the pane in confirmed recovery keys

When the same confirmed conversation is resumed concurrently in two panes, both schema-valid entries share the same stable_mapping_key, so this function assigns them the same primary key. In TmuxObservationStore.observe, the first insert wins and the second is skipped because both entries have the same generated_at and the conflict update requires an older timestamp; subsequent snapshots likewise retain only the first pane, losing one of the persisted conversation-to-pane recovery mappings.

Useful? React with 👍 / 👎.

Comment on lines +24 to +26
if [ -z "$CONTRACT_TOKEN" ]; then
echo "TMUX_STATUS_CONTRACT_READ_TOKEN is missing; remote drift enforcement is not enabled." >&2
exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip private drift checks for fork pull requests

When a fork pull request changes the controlled contract or this workflow, GitHub does not provide repository secrets to the pull_request run, so CONTRACT_TOKEN is necessarily empty and this step always fails. Consequently, external contributors cannot obtain a passing Contract Drift check even when the repository secret is configured; the workflow should skip the credentialed comparison for forks or use a safe event/design that can access the private contract without running untrusted PR code.

Useful? React with 👍 / 👎.

throw invalidOutput("tmux-status v2 producer metadata is invalid");
throw invalidOutput(`tmux-status v${version} producer metadata is invalid`);
}
if (version === 3) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate v3 timestamps as RFC 3339 date-times

For v3 payloads, this branch never tightens the earlier Date.parse check to match the controlled schema's format: date-time. Inputs such as "2026-08-03", a timezone-less timestamp, or even "2026-02-30T12:00:00Z" are accepted by JavaScript despite being outside the v3 contract; TmuxObservationStore.observe then interprets or normalizes them and persists observations under the wrong instant. Apply an RFC 3339/date-time validation for v3 before returning the payload.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7355a404fe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/store.ts Outdated
Comment on lines +38 to +45
return [
"unknown",
pane.pane_instance_id ?? paneIdentity(pane),
conversation.tool,
conversation.conversation_id_kind,
conversation.working_directory,
[...conversation.process_pids].sort((left, right) => left - right).join(","),
].join(":");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Key unknown observations by process incarnation

When an unknown agent process exits and the OS later reuses its PID for the same tool and working directory in this long-lived pane, every component of this key is identical, so the later observation updates the earlier row instead of preserving a separate process lifetime. Fresh evidence after the earlier review is that the new discriminator uses only process_pids, but PIDs are reusable; include a process-start or producer-provided observation identifier that remains stable only for one incarnation.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b7d782359

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/adapter.ts Outdated
Comment on lines +123 to +126
value.process_instance_keys.length !== value.process_pids.length ||
!value.process_instance_keys.every((key, index) =>
key.startsWith(`${value.process_pids[index]}:`)
) ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align process-instance validation with the v3 schema

When a conforming producer uses opaque process-instance identifiers, or reports a key array whose ordering/count differs from process_pids, this rejects the entire status snapshot. The controlled schema at contracts/tmux-status/v3/tmux-status.schema.json:80-84 only requires unique, nonempty strings and does not require PID prefixes or positional alignment, so such payloads pass the repository's contract check but fail status, scheduled collection, and doctor; either encode these additional invariants in the canonical contract or stop imposing them here.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9bf6637874

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/store.ts Outdated
conversation.tool,
conversation.conversation_id_kind,
conversation.working_directory,
[...conversation.process_instance_keys].sort().join(","),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Encode process-instance arrays without delimiter collisions

Use an unambiguous serialization for the opaque process-instance keys. The v3 contract permits any unique nonempty strings, so ['a,b', 'c'] and ['a', 'b,c'] are distinct valid arrays but both become a,b,c here; when such unknown conversations occur in the same pane/tool/cwd, they receive the same primary key and the second upsert is skipped at the shared generated_at, losing one recovery observation.

Useful? React with 👍 / 👎.

Comment thread plugins/tmux-status/src/adapter.ts Outdated
Comment on lines +270 to +277
value.pane_instance_id !== [
value.server_instance_id,
value.session_id,
value.session_created,
value.window_id,
value.pane_id,
value.pane_pid,
].join(":") ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept opaque pane-instance identities allowed by v3

Do not require pane_instance_id to equal this locally reconstructed string unless that invariant is added to the controlled contract. The canonical schema at contracts/tmux-status/v3/tmux-status.schema.json:216 defines this field only as a nonempty string, so a conforming producer can use an opaque identifier while supplying all other valid pane fields; this check then rejects the whole status response even though the store already treats the identifier as opaque.

Useful? React with 👍 / 👎.

parsed.report_type !== "snapshot" &&
parsed.report_type !== "recovery") ||
typeof parsed.pre_restart !== "boolean" ||
parsed.pre_restart !== (parsed.report_type === "recovery") ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep pre-restart validation aligned with the v3 contract

Remove this undocumented equivalence or encode it in the controlled schema. The v3 schema independently permits every boolean pre_restart value and each report_type, so a schema-valid pre-restart snapshot (or non-pre-restart recovery) passes the repository's contract validation but is rejected by status, scheduled collection, and doctor here.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 41ca6c7f0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +243 to +245
if (
version >= 3 &&
(!Number.isInteger(value.pid) || Number(value.pid) < 1 ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject empty v3 pane instance IDs

For a v3 pane with pane_instance_id: "", the earlier guard accepts the value because it only checks the type, and this v3-specific validation never enforces the canonical schema's minLength: 1 requirement (contracts/tmux-status/v3/tmux-status.schema.json:226). The payload therefore passes parsing, but paneIdentity() treats the empty string as missing and persists a synthesized identity while the status endpoint returns the empty identity, making the returned and stored pane mappings disagree.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75e6c93712

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/adapter.ts Outdated

function isRfc3339DateTime(value: string): boolean {
const match = value.match(
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-](\d{2}):(\d{2}))$/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept lowercase RFC 3339 separators

Fresh evidence beyond the earlier timestamp review is that a conforming v3 producer can emit generated_at with lowercase t or z, which RFC 3339 permits and the controlled schema's format: date-time accepts, but this case-sensitive regex rejects it. Such snapshots therefore fail the status endpoint, scheduled collection, and doctor despite satisfying the canonical contract; make the separator matching case-insensitive or use a complete RFC 3339 validator.

Useful? React with 👍 / 👎.

Comment thread plugins/tmux-status/src/store.ts Outdated
Comment on lines +156 to +157
WHERE tmux_agent_conversations.last_generated_at
< EXCLUDED.last_generated_at

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the earliest conversation observation

When the scheduled collector and /status overlap, a snapshot with a later generated_at can insert the row before the earlier snapshot reaches this conflict handler. This WHERE then suppresses the older update entirely, leaving first_observed_at set to the later instant and corrupting the conversation's recorded lifetime; preserve the minimum first-observed timestamp while still preventing older snapshots from replacing current metadata.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22349656ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +165 to +166
session_key = CASE WHEN tmux_agent_conversations.last_generated_at
< EXCLUDED.last_generated_at THEN EXCLUDED.session_key

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve sub-millisecond snapshot ordering

When two valid v3 snapshots for the same confirmed mapping have generated_at values that differ only beyond millisecond precision (for example, .000001Z and .000002Z, both permitted by the contract), new Date(snapshot.generated_at) collapses them to the same instant. The strict < comparison here then prevents the later snapshot from replacing process_instances, identity source, recovery command, and other current metadata, making persisted recovery data depend on arrival order; retain the original timestamp precision or otherwise distinguish these snapshots before applying the update.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6a7a3de8a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/adapter.ts Outdated
return month >= 1 && month <= 12 &&
day >= 1 && day <= daysInMonth[month - 1]! &&
hour <= 23 && minute <= 59 && second <= 59 &&
offsetHour <= 23 && offsetMinute <= 59;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject timestamp offsets PostgreSQL cannot persist

When a v3 producer emits a contract-valid timestamp such as 2026-08-03T12:00:00+23:59, this validator accepts it (and Node parses it), but PostgreSQL rejects timezone displacements beyond ±15:59 when the unchanged string is inserted into the TIMESTAMPTZ observation columns. The resulting transaction failure breaks /status and scheduled collection for an otherwise schema-valid snapshot; either constrain the canonical/runtime offset range to PostgreSQL's representation or normalize the timestamp without losing its permitted microsecond precision.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7fd72d25a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/tmux-status/src/store.ts Outdated
async observe(snapshot: TmuxStatusPayload): Promise<void> {
const generatedAt = new Date(snapshot.generated_at);
const bucket = minuteBucket(generatedAt);
const generatedAt = snapshot.generated_at;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize legacy timestamps before persistence

Fresh evidence after adding the v3 offset guard is that v1/v2 timestamps still require only Date.parse success. An accepted legacy timestamp such as 2026-08-03T12:00:00+23:59 is now passed as raw text into the TIMESTAMPTZ columns, whose PostgreSQL offset range ends at ±15:59, so both /status and scheduled collection roll back; before this change, constructing a Date normalized it to UTC. Normalize legacy timestamps while preserving the precise v3 representation, or enforce storage-safe bounds for every schema version.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: e004e8b410

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1217eb964

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +58 to +60
const match = value.match(
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2}):(\d{2}))$/i
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject year-zero timestamps before persistence

When a v3 payload uses generated_at: "0000-01-01T00:00:00Z", this regex and Date.parse() accept it, but PostgreSQL has no year zero and rejects the unchanged value when observe() inserts it into the TIMESTAMPTZ columns. The status route and scheduled collection therefore fail at persistence instead of rejecting the malformed timestamp at the adapter boundary; require a year of at least 0001.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3d793b6af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"attached": { "type": "boolean" },
"selected": { "type": "boolean" },
"dead": { "type": "boolean" },
"cpu_percent": { "type": "number", "minimum": 0 },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent CPU-average overflow for valid samples

When successive v3 snapshots report a schema-valid value such as cpu_percent: 1e308 (with the CPU anomaly label), both the adapter and semantic validator accept them, but the tmux_pane_minutes upsert computes old_average * sample_count + new_average; on the second sample that exceeds PostgreSQL DOUBLE PRECISION and rolls back the entire /status or scheduled-collection transaction. Add a realistic contract/runtime upper bound or calculate the running average without the overflowing intermediate value.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6fe080b123

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"attached": { "type": "boolean" },
"selected": { "type": "boolean" },
"dead": { "type": "boolean" },
"cpu_percent": { "type": "number", "minimum": 0 },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound resource numbers to finite runtime values

Fresh evidence after switching to the overflow-safe running-average formula is that this contract still permits JSON numbers outside JavaScript/PostgreSQL's finite double range. For example, cpu_percent: 1e400 with the CPU anomaly satisfies this schema and the Python semantic comparisons, but JSON.parse produces Infinity and parseStatusPayload() rejects it via isFiniteNumber, so /status, scheduled collection, and doctor remain incompatible with a contract-valid snapshot; add a compatible maximum here and to the other persisted resource-number fields.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 33b9e94476

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"cpuPercent": {
"type": "number",
"minimum": 0,
"maximum": 1000000

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound plugin thresholds to the v3 contract range

When plugins.tmux-status.cpu_threshold is configured above 1,000,000 (or memory_threshold_mb above 1,000,000,000), both config.schema.json and validateConfig() still accept it and the adapter passes it to the producer, but a v3 response containing that configured threshold is rejected by these new maxima. This leaves the plugin degraded under configuration EchoLog considers valid; apply the same maxima to the plugin configuration schema and runtime validation.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 958fba8dd4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"generated_at": {
"type": "string",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:\\.[0-9]{1,6})?(?:[Zz]|[+-](?:0[0-9]|1[0-5]):[0-5][0-9])$"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude year zero from canonical timestamps

Fresh evidence in the current revision is that isRfc3339DateTime() now explicitly requires year >= 1, while this canonical pattern still admits 0000-01-01T00:00:00Z and the configured schema validator treats it as a valid date-time. A producer can therefore pass the controlled contract and drift CI but still be rejected by /status, scheduled collection, and doctor; encode the same minimum year in the schema.

Useful? React with 👍 / 👎.

@CubePlus1

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 66d1aeec71

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@CubePlus1
CubePlus1 marked this pull request as ready for review August 4, 2026 02:48
@CubePlus1
CubePlus1 merged commit 2fdc001 into main Aug 4, 2026
1 of 2 checks passed
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.

P1: 同步 tmux-status v3 对话恢复契约

1 participant