Repository navigation
Conversation
Fodesu
force-pushed
the
feat/agent-runtime
branch
2 times, most recently
from
August 29, 2026 06:37
8000
6dc5728 to
ffe9493
Compare
Fodesu
force-pushed
the
feat/agent-runtime
branch
from
September 9, 2026 06:40
c30f579 to
258b850
Compare
…e at Dispatch
executor.Backend (Validate/Prepare/Start/Attach/Status/Outcome/Cancel,
addressed by Ref) replaces the Port+BindingPort pair the Worker drove.
Dispatch evaluates the Route table once, prepares the Ref and persists
ExecutionRef{Provider, Ref} with the record before Start; every later
operation resolves record -> provider -> backend. The eight checkBinding
branches and the bound/unbound double path are gone; a record naming an
unknown provider is ErrUnknownProvider and is left untouched. The store
field is ExecutionRef (legacy alias dropped); PortBackend adapts
existing Port-shaped executors until they implement Backend directly.
… runs through Worker loop.LocalExecutor now implements the Backend contract -- Prepare derives the Ref from the AssignmentKey, Start/Attach/Status/Outcome/ Cancel address the Ref -- and no longer implements effect.Port. It stays in loop because loop's tests drive it and executor/local imports loop; executor/local exposes it as a Backend with Provider "local" and a Route helper. app.Build's local mode composes executor.NewWorker over Config.Executions (in-memory by default), so colocated and remote deployments share one record lifecycle (RUN-EXE-8). MemoryStore bounds its terminal records (RetainTerminal, default 1024). runtest, the loop test helper and the authority/compact tests wrap the backend in a Worker.
spawn.Executor implements executor.Backend: Prepare derives the child SessionID as Ref, Start drives the child, Attach adopts a child that exists while no drive of it runs here, and Status/Outcome/Cancel address the Ref. spawn.Intercept and its twelve forwarding methods are gone; app.Build routes the spawn tool's Assignments to it beside the default backend (local, a supplied Port, or the remote client). The Worker stamps the record's key on every Outcome, since backends know Refs only. Adoption after an owner dies is now the control plane's takeover of an orphaned record; the restart test shares a file record store and runs the second process's clocks ahead so the first lease reads as expired, and the spawn drive waits through waiting_for_recovery while the recovery lifetime delivers the adopted Outcome and drives the Run on.
The physical binding of an attempt is the Worker's ExecutionRef, persisted in its record and handed to Backends as a Ref; nothing in Agent Core's effect protocol names it any more. effect.Port keeps its six AssignmentKey-addressed methods.
…rged agent-run.md §6 lists the Backend contract, Route and ExecutionRef in place of BindingPort; RUN-EXE-1/3/6/8 carry the record -> provider -> backend lifecycle, and RUN-EXE-9 (ExecutionRef) and RUN-EXE-10 (backend chosen once, record is the only source of execution identity) are new. agent-runtime.md SPN-1/2/4 describe spawn as a routed Backend and adoption as control-plane takeover of an orphaned record; workspace and test-cloud-agent wording follows. The revision draft is deleted.
Fork spans two consistency domains (Session store, artifact ledger). It now activates the prefix retention claim first and creates the child root second, releasing the claim on a definite Create failure; a crash between the two leaks a claim instead of a child whose inherited bodies can be collected. Delete treats a missing root as already done so a call that failed after the root was dropped can be repeated to release the remaining claims. EXT-WRT-8/9 revised; EXT-PRJ-8 (projection inheritance policy) is specified here and implemented in the next commit.
A child's ancestry still reads the parent's whole commit prefix, but the streams in it mean different things: the session stream is inherited, run streams belong to the segment that wrote them. ReadStream returns only the child's own events for non-session streams; projections declare an InheritPolicy (default: session batches only from inherited commits; chatlog and turn surfaces opt into InheritAll because their content is projected from run facts). Authority.Fork refuses a point where the parent has an active Turn (History.ActiveAt). An inherited attempt reads as finished from the surface; its Run is ErrRunNotFound. History no longer uses CommitSeq 0 as a not-found sentinel. SES-FRK-5, EXT-PRJ-8, AUTH-FRK-1; the SPN-4 Close sentence lands with the Worker commit that follows.
Worker owns its goroutines: a cancellable lifecycle and a WaitGroup cover the reconcile loop, heartbeats and watchers; Close stops and waits, leaving records leased for the next incarnation. Application.Close closes the Worker Build composed. Backend.Prepare stays idempotent by AssignmentKey; the new Backend.Restart(previous, a) allocates the next generation's Ref when a takeover finds the previous execution missing. The superseded ExecutionRef is kept on the record (Superseded) instead of overwritten. LocalExecutor derives a #generation suffix; spawn keeps the child Ref. RUN-EXE-3/8/9 revised.
runmod.Config.Attachers lets another module add its session-stream
facts to the group that records a command's Run facts, from the
Writer's view (RUN-CMT-9). turn.AttemptEnder writes
twilight/turn/attempt_ended{TurnID, RunID, Attempt, End} after
run_ended and before the caller's Attach. The turn surface now folds
the session stream only: run_ended leaves its Consumes and Requires,
and its Inherits returns to the default. run streams are execution
history that neither a fork nor the surface depends on. This revises
the 2026-09-17 rule that attempt outcomes are projected from run facts
without a Turn-side fact. TRN-EVT-1/3, TRN-PRJ-1, TRN-SCP-1 revised.
…h run_ended" This reverts commit c903ca9.
…one unit of work agent/run speaks only Run types: RunStore is the port bound to the caller's write capability (Bind), Scope replaces SessionID, RunPosition is its own type, the envelope names no store, and Protocol splits into Schema = Machine + WireSchema + Canonical + SnapshotCodec with one variant registry. agent/session/unit is the single cross-module transaction coordinator: Turn, chatlog and Run each contribute a Part; CommitRequest.Attach is gone. agent/run/reconcile owns takeover: it compares Executing targets with the execution store and produces Run commands; Loop/Driver/store no longer interpret executor observations. The machine projection drops Ended (creation is guarded by the kernel's stream index via View.StreamHead), turn RunOwner is bounded to active Runs, FrozenValues registers Bindings itself, effect.Port -> ExecutionPort, executor.Backend -> ExecutionBackend.
…end with the Run A fold stamps every DecodedEvent with its session.Position (commit seq and event index in batch order), so the chatlog projections record the position of the event that produced an entry instead of keeping a counter that a restored snapshot had to rescan for. CheckpointCreatedPayload.CoveredThrough is that Position (pre-release wire change; chatlog golden updated). Both chatlog projections consume run_ended and forget the Run's Turn there, so Surface.Runs and Context.Runs are bounded by the Runs active now, like the turn surface's RunOwner.
…untime -> agent/environment The Writer keeps only the kernel handle, the head, the fence and the CommitID/stream index. Encoding and stream affinity (encode.go), artifact admission and retention claims (admission.go), transactional projection folding and the projection cache (projector.go), observer fan-out (observers.go) and the replay fingerprint (fingerprint.go) are stages composed onto Commit, each holding its own state. Behaviour is unchanged. agent/runtime, the physical environment materialization boundary used by workspace, is renamed agent/environment so 'runtime' no longer names four different things.
…sitions agent-run.md: section 5 describes run.RunStore / Scope / RunPosition, the Schema aggregate with its four contracts and the single variant registry, SessionRunStore.Bind and the Run Parts, unit.Commit as the only cross-module coordinator, the machine projection without Ended (creation guarded by View.StreamHead), RUN-CMT-3 as a Part, and reconcile.Reconciler in place of Reattacher/RecoveryDisposition. agent-turn.md, agent-runtime.md and README follow; agent-session-chatlog.md describes ledger Positions in place of the projection counter; agent-session-extension.md adds View.StreamHead.
…hema Schema gains Identity (every RunID-scoped derivation) and Bodies (the frozen-body envelope codec); Canonical gains DigestToolCallBinding. The package-level Derive* functions and EncodeFrozen* are gone, so nothing persisted is derived outside the Run's own schema version: the run store freezes bodies under the command envelope's SchemaVersion instead of a hard-coded V1, decoding reads the version from the stored envelope, and the chatlog remembers each Run's schema (RunOwner) so materialization derives CallIDs under it. DeriveTakeoverClaim stays owner-level.
AgentInput is {ID, Digest}: InputAccepted and PendingInputs no longer copy
the input content that input_submitted already holds (RUN-WIR-4), so an
input body exists once in the ledger and edit/fork never touch a second
copy. chatlog.Commands.Submit returns the digest, DeliverInputs compares
digests inside the unit, Retry replays digests from the surface. Decide and
CreateGroup reject an input without a digest. Pre-release wire change to
input_accepted; the schema golden is updated.
…ce per stream A projection commands plan against (run machine, turn surface, chatlog surface and context) is Authoritative: its fold refuses a commit it cannot fold. Every other projection is a derived read model: a fold failure marks it unhealthy for the Writer's lifetime (reads report ErrProjectionUnhealthy, the cache is not refreshed for it) and never blocks the facts, so one extension cannot brick a Session (EXT-PRJ-9). Write-time invariants belong to unit-of-work Parts. InheritPolicy is now a per-stream predicate (InheritSemantic, InheritAll, InheritStreams) instead of a two-valued enum keyed on the physical stream kind.
…ifacts, DriveResult, drive budgets
reconcile: an Outcome read that the executor answers definitively
(ErrExecutionNotFound, the new effect.ErrOutcomeUnavailable, which
executor.ErrUnknownProvider wraps) stops the watcher and reports through
Fail; transport failures retry up to ReadRetries; only not-ready waits
without limit. Driver reports through Ports.Fail.
writer.Fork: an event type the registry does not know, or a binding-bearing
payload it cannot decode, refuses the fork instead of assuming it references
nothing (EXT-WRT-8 fail closed).
authority: a durable Store or Content Store with in-memory Bindings/Ledger is
refused unless Artifacts.Ephemeral opts in.
driver: Drive returns DriveResult{TurnResponse, AlreadyDriving}; the
already_driving disposition no longer extends the Turn vocabulary.
app: RouteRetries and DrainBudget replace the literal 4 and 64; exhausting
the drain budget is ErrDrainBudget with the Results so far.
Assignment carries one Body (ModelAssignment | ToolAssignment); Kind is
derived, and the JSON shape the execution store persists and the HTTP
protocol carries is unchanged, with decoding refusing a kind that does not
match its body. Outcome carries one Result: ModelSucceeded, ModelFailed
{Code, Message} with wire-stable codes, ToolExecutionSucceeded/Failed/
Unknown, Cancelled or Unknown; there is no Go error and no flag pair that
can disagree. Outcome.Status derives the ExecutionStatus in one place; the
protocol envelope maps to and from the variants.
…fork fail-closed, durability and drive vocabulary
…ck reopen; durability is one bundle session.Commit gains Intent, the digest of the operation that produced it, covered by the commit digest (SES-APP-4). writer and unit judge a replayed CommitID by intent when both sides declare one -- same is already applied, different is a conflict -- without preparing a Part, so a second settlement of the same attempt with another result is ErrCommandConflict as RUN-CMT-5 promised; Turn commands declare their intents too. projector.rebuild folds a derived projection to its last good commit and marks it unhealthy instead of refusing OpenWriter (EXT-PRJ-9 across reopen). authority requires the whole durable bundle (content, bindings, ledger) next to a durable Store unless Artifacts.Ephemeral. wireV1 speaks through its own variant registry; Authoritative is reserved to twilight modules.
…en, authoritative capability, durability bundle
Wrap both errors with %w, check type assertions on projection states, rename shadowed builtins, drop the always-nil error of encode, convert NewRun to RunCreated directly, and guard the binding cardinality compare.
… intent, per-wire fact naming authority.Durability: stores declare Durable(); memory implementations say false, filestore says true, silence counts as durable, so an explicit memory binding store or ledger cannot slip into a durable bundle. extension.BuildRegistryWithExtensions: trust is how a module reaches the registry; extensions may not declare Authoritative nor use SourceTwilight. unit.Work.Intent is required; a replay of a commit sealed without an intent is a conflict, never a silent replay. factCodec validates through its own WireSchema, FoldRun names facts through the Run's schema, and FactTypes is the union over every schema's registry.
Watch replaced the callbacks of a key already registered, so when two callers awaited the same effect -- a caller's settlement and the background step reaching the same compaction, which derives its key from the context it replaces -- only the later one was ever answered and the first waited for good. Each key now holds every registration and the probe state they share: one read, one probe, and the answer reaches all of them; cancel drops one.
…; Loop.Run is gone The Loop steps a Run: Advance commits the next transitions and dispatches, Deliver settles an Outcome; it waits on nothing. The Engine awaits every dispatched key on the shared Watcher under the Session's lifetime, settles the Outcome through the Loop off the Watcher's goroutine and reports it as Notify; a takeover's kept targets join the same table, Detach cancels what is still awaited, and a fenced settlement refuses every later step. Drive returns one step's DriveResult (Dispatched, InFlight, Waiting, Finished, AlreadyDriving); an answered wait continues in the same step. A tool step entered again honours its scheduling window. The Controller's Advance is one step. Session.Send, Settle, Resume and Wait keep the settled contract at the product edge by waiting on the Session's event stream between steps; Owned.Drive does the same for a bare Handle.
… mechanics in the Controller's answers The Controller reported InFlight and AlreadyDriving -- the engine's await count and the Loop's lock state -- and the host rebuilt from them whether to keep waiting, with a timer for the lock case. TurnProgress now carries a Standing: Ended, Carried (this process awaits its effects; a notice follows) or Blocked (it waits on something not here). Submit's absorbed answer is Absorbed. A Run takes one step at a time: Loop.Advance waits for a step in progress instead of refusing with ErrRunAlreadyRunning, so a concurrent step is no longer a state anyone reports. ResumeWaitingForRecovery is ResumeExecuting: it describes the Run, and who carries the wait is the reader's knowledge.
…es progress itself The Loop emitted committed observations (agent_committed, tool_started, tool_completed, run_finished) on an EventSink that every host discarded: the committed stream already carries them from the Writer. The sink, the Event vocabulary and the serialization behind them are gone; Advance and Deliver take no sink. The executor's progress frames, the one provisional observation, are published by the engine to the transient stream as it awaits each effect, under the frame's own kind. LoopResult loses ExecutionRecovery and Reason: Executing lists the effects a waiting Run has in flight, and whether this process awaits them is the host's knowledge.
effectalias.go re-exported effect's assignment, outcome, status and error vocabulary under the loop package, so every user of the Loop imported two spellings of one type. The aliases are deleted: loop and its callers name effect.AssignmentKey, effect.Outcome, effect.ToolExecutionOutcome and the rest directly, and loop.Executor is effect.ExecutionPort. Loop keeps only its own API: Settings, TargetResolver, EffectContext, DispatchPolicy, LoopResult and ErrModelUnavailable, which moves to contract.go. The Loop's duplicate Executor field is dropped; Ports.Execution is the single port. Deliver no longer carries step and call IDs out of the switch that reads them.
… adapter SessionRunStore.RecoverInterrupted iterated the active Runs and called back into a sessionstore.Reconciler interface, so the storage adapter carried the takeover policy's loop and an interface only execution implemented. The adapter now offers one read, ActiveRuns: the snapshot of every active Run of the Session from the Writer's projection. execution.recovery.Recover walks those snapshots itself and reconciles each under the Session's lifetime; the sessionstore.Reconciler interface is gone. reconcile gains ReconcileAll, Reconcile over many snapshots, which the conformance suites and the loop tests use through a harness helper in place of the removed method.
…e only decides effect is the port vocabulary; the Watcher is a client over it, so it moves to effect/watch (watch.Watcher, DefaultPoll/Reconnect/Probe). Its implicit port discovery through PortsOf on first Watch is gone: whoever builds a Watcher names its Settlements and Recover ports. reconcile.Reconciler loses Deliver, Fail, Watcher and Lifetime: a kept or deferred target stays Executing and waiting on its Outcome is the caller's, which execution's recovery already does under the Session's lifetime. The four Watcher tests that lived in reconcile become watch's own; the loop takeover tests wait through a Watcher directly.
…pe, not a store PrepareHook received the Loop's bound RunStore so that execution could pull the Session's Writer back out of it through an anonymous interface on sessionstore's bound store. The hook now receives the Run's Scope an BD0 d the input; execution finds the Writer of that Session among the lifetimes it owns (recovery.writerOf) and hands it to the Planner. bound.Writer() and the type assertion are gone.
The Writer already reports a superseded owner as a ledger.Error with CodeOwnershipLost; above it, sessionstore wrapped that into store.ErrOwnershipLost, turn.Coordinator wrapped it again, and execution and loop each kept a predicate over two or three spellings. ledger.IsOwnershipLost is now the single predicate: store.ErrOwnershipLost, sessionstore.ownershipError, the Coordinator's remap, responders' lostOwnership and loop's ownershipLost are deleted, and the lifetime's fence is a ledger.Error itself.
plan.Next built decision.Input, so the Run core's plan imported the decision layer above it for one struct of Run facts. The struct is now run.PromptInput; decision.Builder, loop's PrepareHook, execution's Planner and the prompt builder take it, and plan imports run alone.
run.CanonicalJSON was an alias of jsonstable.Value with three wrappers over jsonstable's constructors, so the same value had two names and packages that needed only the JSON type imported the Run core for it. The alias and wrappers are deleted: every field, parameter and test names jsonstable.Value, Parse, MustParse and FromValue directly, and seven packages drop their run import.
…n/lifecycle session/lifecycle imported turn and chatlog for History, the fork guard that refused a point inside an active Turn, and the ForkBeforeTurn and ForkBeforeInputs variants. Lifecycle now knows no module's facts: Fork takes a commit and forks there. History is turn.History, with BeforeStart and BeforeInputs as the fork points and RequireNoActiveTurnAt as the precondition; the Application composes them with Lifecycle.Fork, so app.Fork guards every fork and the two Turn-relative forks are app-level compositions.
…umer turn.Commands and turn.Reader existed only to be embedded by conversation.Turns. The Controller now declares the four methods it needs itself and turn keeps the Coordinator alone.
…es them GetOutcomeEnvelope handed the HTTP binding the stored wire envelope so the Worker carried a method shaped for one transport. The server now reads the Outcome through GetOutcome and renders it with protocol.EncodeOutcome, the same codec that stored it.
Consumers told a committed Event from a progress frame or a background failure by which fields were set. Event carries Kind (committed, progress, failed), the producers set it, and the HTTP wire and the Session's wait read it instead of probing Err.
… its own Engine.Presets and Engine.Progress handed the host the preset registry and the transient stream the Engine had created, so the application registered presets and published failures through its Engine. Both are now the application's: it creates them, keeps them as Presets and Progress, and passes them in Config; Config.Presets is required and Config.Progress is where the Engine publishes.
Nothing in agentcore reads or writes a checkpoint.Store; only the agent's SQLite and Postgres adapters implement it and the component stores expose it. The package moves to agent/checkpoint with its conformance suite.
Application carried twelve flat fields for the services composeSessions builds over one Store. They are now SessionServices, built once and embedded, so the Application reads as its three parts: the Session services, the Owner with the Engine, and the registry and stream it hands the Engine.
…knows Runs, not Turns A model step's scheduling and malformed-result retries came from the preset through the Loop at settlement time, so settling a Run needed its preset, and the Engine found the preset by reading the Turn surface: the execution layer imported turn for one lookup. run.StepPolicy is frozen onto the step at Prepare (model_step_prepared writes version 2 and keeps the version 1 codec; an absent policy reads as zero). SubmitModelResult drops Scheduling, RejectModelResult drops Disposition: Decide reads both from the step. The Loop is one per deployment: Advance takes the Run's Builder, Deliver and Redispatch need no preset. Engine.Drive takes (RunID, PresetRef); the Controller and Owned read both from the Turn they drive. execution no longer imports turn, and the per-preset loops table is a builders table.
Nothing has shipped, so the step policy joins the fact's one and only wire shape; the version 1 codec kept for a policy-less shape, and the superseded codec type that served it, are removed. Every fact type is at version 1 with one codec again.
Whether the wire shapes the registry writes are committed is a property of the whole ledger format, not of any one event type's version number, and nothing has shipped yet. module.Prerelease says so in one place: while it is true a shape changes in place at version 1 and no event type carries a codec history. module.NoHistory checks a descriptor for that, and the sessionstore and app tests hold every first-party module to it until the constant is turned off at the release.
PayloadVersion was a bare integer, so nothing said whether a shape was still being iterated or was a release's commitment. It is now a two-track value written as `v` in its wire form: "pre.N" is a prerelease version, where a shape changes in place and the number moves so an earlier build's payload reads as Unknown rather than misread, and a type has one prerelease codec at a time (the registry refuses a prerelease version beside any other codec); "N" is a stable version, which keeps a codec for every stable version before it. Every prerelease version orders before every stable one. The run, chatlog, turn and workspace modules write pre.1. The module.Prerelease constant and its guards are replaced by this.
… is explicit Three structured error types shared one idiom but not one meaning: ledger.Error carried the Writer's conditions (ownership_lost, unknown_outcome, projection_unhealthy) beside the registry's, the Writer rewrote session codes into ledger codes, turn built session.Error values for its fork guards, and callers matched by constructing a target value, with session's Is also comparing the Operation. Now each layer owns what it alone can report and translates at its edge: ledger keeps invalid/unknown_event/codec with constructors and Is predicates; writer declares ErrOwnershipLost, ErrUnknownOutcome, ErrProjectionUnhealthy and ErrClosed as its own and wraps the kernel's report; sessionstore maps writer.ErrOwnershipLost to the Run port's store.ErrOwnershipLost, which loop and execution match; turn reports ErrNoForkPoint. session.Error and artifact.Error keep their types and codes, gain named predicates (IsNotFound, IsOwned, ...) over errors.As, and lose their Is methods; every match goes through a predicate.
…g alone A Port beside a Sandbox left the Worker with the sandbox route alone: model effects had no route and the Turn failed. The Port is the Worker's default route again (executor.Default over PortBackend), as Config.Port promised. Compose refuses a prefilled Execution.Executor instead of silently skipping the Worker, and refuses Config.Executions when no Worker is composed, so a store nothing reads is not mistaken for one in use. The sandbox backend joins a copy of the caller's WorkspaceConfig rather than being written into it, so a Config composed twice yields two agents with their own backends. Agent documents that its Close, not the inner application's, releases the Worker and the sandbox backend. Tests cover the Port+Sandbox route, the refusals, the untouched Config and the close of both backends; two app comments stop naming the deployments above them.
SessionServices was embedded and exported, so every service the application composed -- Lifecycle, Writers, Turns, Chatlog, Runs -- was reachable beside the methods that guard them: app.Lifecycle.Fork went around app.Fork's quiescence check, app.Lifecycle.Delete around DeleteSession's close-and-acquire, Writers around the Owner, and Session.Handle() handed any holder of a Session the Writer to commit Turn protocol beside the Controller. Owner, Execution, Presets and Progress were exported the same way. Every one of them is now unexported; what the application admits is its method set. Reads the services alone provided gain methods: TurnStatus, RunRecord and Materialize on the Application, Queue and Withdraw on the Session. Owned keeps its Handle: driving through the Handle is what Acquire is for.
The tests reached the Writer through Session.Handle and committed Turn protocol beside the Controller; they now submit, stop and withdraw through the Session and read Runs, Turn status and entries through the Application's read methods. The stores a test inspects directly are the ones it built.
DriveForTest and the Driven wrapper reproduced a host loop in test code: their own outcome polling, read-error classification and cancel handling. The production primitives already cover it: Loop.Advance, Loop.Deliver and watch.Watcher.Await. Single-step tests now call the step they assert on. End-to-end tests go through one small helper that composes only those three, and the feature harness inlines the same loop. The mid-execution cancel test does what a host would: Cancel the effect, then await and Deliver its Outcome under a context of its own. Co-Authored-By: Claude <noreply@anthropic.com>
agentcore/decision was named for a layer that no longer exists: the policy catalog it once held became data on AgentPreset, and only the prompt builder seam remained. The name was wider than the contents and collided with reconcile.Decision and the commit verdicts. agentcore/decision -> agentcore/prompt (Builder, Prompt, Catalog, Sources, BuilderFactory, ErrUnknownBuilder); agent/prompt -> agent/contextprompt (Builder, New, V1). Engine Config.Decisions is Config.PromptBuilders. The V1 ref is "twilight/contextprompt/v1", so the preset digest changes; the golden records the new digest. Comments that said "decision identity" now say preset. Co-Authored-By: Claude <noreply@anthropic.com>
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
see spec