Commit Graph
18 Commits
Author SHA1 Message Date
ZiyaandMagolor 341ea6eea4 feat(schedule): integrate standalone tasks with the existing WebUI (#6189)
* feat(schedule): manage Host tasks with typed timing and delivery targets

* fix(schedule): align task creation button halves

* refactor(schedule): remove obsolete Session reminder runtime

* refactor(schedule): simplify task UI and preserve keyboard navigation

* fix(schedule): address task delivery and interface review findings

* test(schedule): normalize bundle module paths on Windows

* fix(schedule): cover reserved targets and trim unrelated changes

* refactor(schedule): minimize task management changes after rebase

* test(schedule): align rebased fixtures and documentation records

* test(schedule): refresh SDK scenarios added on master

---------

Co-authored-by: Magolor <magolor@qq.com>
2026-10-29 18:11:48 +08:00
Chinesezjc adc27809f7 fix: map every zone rejection exhaustively and document the signed span
- timeZoneError and browserTimeZone switch over TimeZoneRejection instead of
  a ternary: each reason that shares a diagnostic is its own case, and the
  default arm assigns the reason to never so adding a reason fails the build
  (assertNever where the package already imports it). The unsupported cause
  is still forwarded.
- the request-zone suite now exercises the blank refusal, so every case the
  switch lists is covered rather than sharing one ternary branch.
- Duration documents that a span is signed: a negative count builds and
  decompose() refuses it, so the caller states its own sign policy.
2026-10-19 15:12:50 +08:00
Chinesezjc c949deb1ca refactor(util-time): publish only the span surface its consumers call
The package API carried members and result types ahead of any caller. The
span now publishes fromMilliseconds and decompose, the two entries
dsh-time-context calls; the seconds constructor, the zero identity, the
arithmetic and ordering operations, the millisecond getter, and the four
fractional conversions land with the caller that needs them, recorded in
the Agent Note and the README limitation.

The package entry names its exports instead of re-exporting both modules,
so the three result types and DurationParts, which no consumer names, are
no longer part of the published surface. Every remaining new name has a
named consumer: schedule imports the nine parser and bound names plus
four rejection types, and canonicalizeTimeZone has seven consumer files.
2026-10-14 15:27:15 +08:00
Chinesezjc 8987e6c45a docs: drop references to the removed invariant mechanism
origin/master removed the runtime invariant plugins and the package rule
that asked a README to justify the absence, so the text that cited that
mechanism no longer refers to anything:

- the Agent Note states the elapsed-rendering change without the reading
  invariant it used to cite
- the same note no longer says the durable reading format is one an
  invariant validates
- the util/time README no longer explains why no invariant companion is
  published, and its module JSDoc no longer claims the library formats
  nothing while listing a canonical instant renderer
2026-10-08 16:20:08 +08:00
Chinesezjc 830f66006e fix(util-time): enforce the span bound in arithmetic, and correct the record
- plus and minus construct through fromMilliseconds, so the documented
  bound has one enforcement point; the negative control reddens the new
  assertion
- the class and README say Duration overrides no coercion hook rather
  than having none, and decompose says which parts are floored
- the note no longer calls the differential a review probe, records that
  Schedule imports the bound constants, that both strict parsers refuse
  year 0, that Schedule's suites do assert a few message substrings, and
  that the util charter bans harness dependencies rather than external
  packages
2026-09-25 16:33:11 +08:00
Chinesezjc 0b5803cf0c fix(util-time): bound a span, and state the conversions as they are
- Duration rejects a count outside the exactly representable millisecond
  range, which is what makes decompose's whole-part identity exact; the
  postcondition is asserted over a sweep and a random sample
- the to* JSDoc no longer claims a round trip restores the count: each is
  one division, so it answers the nearest double
- a test rules out a Symbol.toPrimitive coercion hook, the README names
  both implementation modules, and the note records that the value type
  ships its full operation set before its second consumer exists
2026-09-25 15:14:50 +08:00
Chinesezjc 0939392e71 feat(util-time): add a millisecond Duration span
Duration holds one finite millisecond count behind a frozen class: a
class rather than a branded number because TypeScript erases a brand
through arithmetic, so only an instance can stop seconds and
milliseconds from being added. It adds, subtracts, orders, converts to
larger units fractionally, and splits a non-negative span into whole
days, hours, minutes, and seconds. There is no valueOf and no toString,
so a reader always states its unit.

dsh-time-context reads its elapsed line through it and keeps the
wording: a backward clock reading still clamps to zero there. The
rendered text is byte-identical for every finite sample, verified by a
differential over more than eight thousand inputs. A non-finite sample
now throws from the span constructor instead of rendering 'NaNs', which
the package's own reading invariant already refused.
2026-09-25 14:48:01 +08:00
Chinesezjc bbdac8febe docs(time): state the module contract and the zone mapper as they are
- the constants name one bound each
- resolveLocalInstant reuses an instance a caller already holds instead of
  copying it per candidate date
- the README entry-point paragraph drops its duplicate sentence
- the note replaces an invalid reason for the zone mapper and a
  review-vantage sentence with the facts
2026-09-25 01:01:26 +08:00
Chinesezjc 7edd3efe85 refactor(time): give the four-digit bound one owner
- isFourDigitYearInstant is the shared predicate; Schedule's five
  representability guards delegate to it instead of re-deriving the range
- the reason for a field outside its calendar range is out_of_range in
  both strict parsers, so year 0 no longer reads as a wall-clock problem
- LocalCalendarTime.year states which entries reject year 0 and which
  accept it at the UTC edges
- the note counts the five removed expressions and records that the zone
  mapper is a silent catch-all; the Chinese side mirrors the English
  paragraph order
2026-09-25 00:53:09 +08:00
Chinesezjc 92ee4e98f0 docs(time): state each entry's return precisely
- the README no longer claims resolveLocalInstant answers a string
- the accepted-input table records the widened plain date-time input
- canonicalClientTimeZone is named as the wire-boundary form rather than
  left outside a blanket claim about discriminated results
- the non-canonical scheduledAt diagnostic has one source
2026-09-25 00:41:31 +08:00
Chinesezjc 51a7572852 refactor(time): answer the shared resolver from one place
- resolveLocalInstant accepts an already-built plain date-time, so the
  recurrence walkers drop their private copy of the disambiguation and
  round-trip decision
- decodeInstant narrows its field explicitly and drops the assertion
- the model-input exhaustiveness fallbacks throw a plain Error, matching
  the timing-change fallback, while durable decoding keeps
  ScheduleLogError
- the library module and README state which entries answer a
  discriminated result
2026-09-25 00:31:56 +08:00
Chinesezjc 22f8be30a1 refactor(time-context): consume the shared zone vocabulary
time-context kept a third copy of the IANA profile: its own regular
expression and its own Intl canonicalization in request-zone.ts. It now
reads a request's reported zone through canonicalizeTimeZone and keeps
its stricter policy — an alias whose canonical answer differs from the
reported value is still refused, with the same three diagnostics.

The shared rejection now carries the platform error it caught, so the
unsupported refusal keeps its cause in both time-context and Schedule.
2026-09-24 21:54:34 +08:00
Chinesezjc 6c9c7cb69e docs(time): state the throwing preconditions and exact contracts
- Instant entries that take already-validated values throw on violated
  preconditions; the module header said every entry answers a result.
- formatFourDigitYearInstant also refuses a non-integral epoch.
- Schedule's reason mappers switch over the closed unions with a never
  default, so a new library reason fails the build instead of falling
  through to a catch-all.
- The Agent Note claimed the schedule suites pin these diagnostics; they
  assert codes only, and the note now records the added message assertion.
2026-09-24 13:08:06 +08:00
Chinesezjc c96d48d491 refactor(schedule): extract time vocabulary into dsh-util-time
Move Schedule's strict RFC 3339 instant, local-calendar, and IANA zone
parsing into @deepseek-ai/dsh-util-time, and have Schedule consume it.

The shared entries answer discriminated results and own no failure
vocabulary; Schedule keeps its error codes, diagnostics, durable record
shapes, and all recurrence arithmetic.
2026-09-24 12:55:36 +08:00
Turtle b8e3b32fcf Merge master into codex/omit-unneeded-invariants 2026-08-31 14:38:55 +08:00
imccyu 674a1e95a3 fix(api): rename the failure marker, harden cross-realm discrimination, and mark the packed-record violation
- protocol: isDSHRemoteGatewayError -> isDSHRemoteError (the class is
  protocol-wide, not Gateway-specific); remoteErrorOf drops its
  instanceof Error precondition and tests the marker plus a string code
  structurally, so a marked failure from another realm no longer reads
  as a local defect.
- session-controller: the live-follow packed-record protocol violation
  now throws a marked RemoteError('gateway/internal'), landing the
  session in openState=error instead of an unhandled rejection;
  pinned at the transport and session levels.
- util-time: correct the invariant companion's @module name.
- regenerate the tool-cordis catalog for the marker rename.
2026-08-29 03:12:43 +08:00
imccyu 5af9eec51c fix(api): address review findings on the gateway client failure face
- classify a carrier throw under a caller-aborted signal as
  gateway/cancelled instead of gateway/internal, matching the code the
  Host produces when the abort wins the wire round-trip.
- read $host facts from the construction-time Connection handle,
  matching $stream; the service cannot be replaced without restarting
  this plugin, so the live re-lookup was dead complexity.
- state rebuiltFailure's actual contract in its comment: codes pass
  through verbatim without runtime validation.
- correct the @module name in dsh-util-time.
2026-08-28 22:37:36 +08:00
imccyu 804b1ffbfc refactor(api): converge the Remote failure vocabulary and client surface
Single RemoteError with a merge-extensible, domain-prefixed code map;
owners throw at the failure point; streams surface marked failures;
clients consume ctx.remote directly with isRemoteFailure as the only
discrimination point and construct no failure instances.
2026-08-28 22:37:36 +08:00