Commit 1fec851
Efficiency, robustness and Studio: fewer model calls, retries instead of dead ends, a live and linked Studio (#38)
* feat(studio): blocked tasks tell their story and offer a next step
A blocked card rendered only task.error, the last line of a longer story.
The expanded card now shows the attempts timeline (attempt_log), the
review verdict, the structured criteria checklist, and a next-step row:
Send back to Ready, Retry (POST /api/tasks/{id}/retry, falling back to
the Ready move on a server without the endpoint), Reassign team (opens
the edit form on the team control) and Steer (prefills LiveFeedback with
@task:ID, parking the request across navigation when the composer is not
mounted).
LiveTaskPanel's Blocked/Failed counters are now filters over the list,
every attention row carries Retry, and a focusTaskId prop expands,
scrolls to and flashes one task.
Also: additive Task/QuerySession/PendingChange fields, a shared
window-event contract (ui/events.ts), an ErrorState primitive, a roving
tabindex helper, a confetti layer, and Modal's focus trap extracted into
useFocusTrap so other dialogs can reuse it.
* feat(studio): a run's end is not a dead end, and the keyboard reaches everything
ResultPanel grows a What-next row: Resume interrupted run, Open blocked
on Board (/board?column=blocked), Review N pending, Run again with this
prompt. All data can be passed as props by the Live view; without props
the panel fetches the resumable list and newest prompt itself and runs
the prompt through RUN_PROMPT_EVENT, starting it directly when no
listener claims the event.
Layout reacts to run_end: a success or error toast, a flashing tab
title while the tab is hidden, a browser Notification when permission
was already granted and the tab is hidden, and a two-second confetti
layer on a green run (skipped under prefers-reduced-motion). A run_end
replayed from the server snapshot on page load is ignored.
Keyboard: g t goes to Teams; Cmd/Ctrl+Enter and Cmd/Ctrl+. dispatch
RUN_PROMPT_EVENT / STOP_RUN_EVENT while the run prompt is focused;
Cmd/Ctrl+K opens a self-contained command palette over pages, tasks,
agents, teams, recent runs and the theme. ShortcutSheet picks the new
rows up from the shortcut table.
* fix(studio): no more silent failures on the editor pages
SettingsPanel and MarkdownEditor swallowed save errors — a 409 during a
run left Save looking like a no-op. Both now report through the shared
toast, naming the active run as the reason and saying the edits are
kept. AgentManager, SkillManager and PipelineEditor render an inline
ErrorState with Retry when their list fails to load instead of an empty
state over a dead backend, and their secondary loads and reset report
through the toast. FileInspector drops its private toast for the shared
one and accepts /files?path= to open a file directly.
ReviewView refreshes on the review_pending SSE event and on a 15 s poll
while a run is writing, not only when it stops; each change shows its
provenance (task, agent, run) with links, plus Open in Files. Empty
states on Review, Agents and Skills say what the page is for and offer
the first action.
* loop: one reviewer per review, fast-reject on gates, resume timed-out workers
The review path was a speculative race: at the default max_parallel it
fanned out to a local "acceptance" probe, the reviewer and reviewer-strict
at once. The probe re-tested a subset of fastPath's conditions with none of
its guards (open criteria, scope, blocking gates, tester role), so a task
fastPath had just declined could be approved "acceptance race won" with no
reviewer; and reviewer-strict was dispatched on every review while its
answer was used only when the primary's was empty. The race is gone:
decideReview is fastPath, then a harness fast-reject (a fired hard gate, or
a worker that finalized blocked with no evidence — the reviewer could not
change either outcome), then ONE reviewer request; reviewer-strict runs
sequentially and only when the primary produced no readable verdict. Every
dispatch goes through execOne, so the runway clamp and the call budget
apply to reviews as they do everywhere else; the speculate primitive keeps
its tests but no longer sits on the review path.
A reviewer transport error no longer blocks the task and cascades to its
dependents: the gathered gate signals are judged first, the reviewer is
re-asked once when budget and runway allow, and otherwise the task goes to
the human backlog as "reviewer unavailable".
Worker failures: a timed-out worker is re-queued to resume from its ReAct
checkpoint while under the attempt ceiling and parked in to_scope only at
the ceiling; transient and rate-limited errors get one bounded retry that
honors Retry-After; the checkpoint is saved before any retry so the retry
resumes instead of cold-starting. The timeout message reports the clamped
per-call budget the request was actually dispatched with.
* prompts: corrector keeps the harness evidence; worker prompt puts the pack first
formatCorrectPrompt clipped the previous output head-first at 2.5 KB while
runGates appends the failing command's section and observation to the END
of Task.Output, so once the prose passed the budget the corrector was told
to fix a smoke failure it was never shown. It now uses the same body /
evidence split the reviewer prompt uses (clipForReview): the prose is
budgeted and the evidence kept whole. It also carries the HARD SCOPE focus
list (via the new shared agents.FocusFilesSection, which BuildWorkerPrompt
uses too), the acceptance and the project language hint, so the corrector
is shown the same scope the gate grades it against. The self-critique
dispatch is clamped to the runway like every other call.
BuildWorkerPrompt opened with "ID / Title / Column / Role" BEFORE the
scoped context pack, so two tasks sharing one pack shared a prefix of a few
dozen bytes and the whole pack was re-prefilled per task. When the
description starts with a pack, the pack (and the project-wide language
line) now come first and the task header sits immediately before
"## Task instructions"; the Column line, which changed between attempts at
the same task, is dropped. Descriptions without a pack keep their shape.
* backends: an explicitly set temperature of 0 is emitted, not treated as unset
reviewer-strict pins Temperature 0.0, and buildBody emitted the key only
when the value was > 0 — so the one temperature that was set on purpose was
dropped and the server sampled at its default. RoleSpec gains
TemperatureSet, set for reviewer-strict and carried on the provider
Directives; the structured request always emits `temperature` for a role
that set one, while roles that never set it keep the unset behavior. The
delegated (non-structured) path is built inside GoLangGraph and still
applies its default to a zero; docs/decoding.md says so.
* feat(studio): run history that reads at a glance, dialogs that trap focus, tabs that roam
RunHistory list rows show the archive's numbers when the server sends
them — duration, tasks done/total, failed count, tokens, cost and team
chips — and stay as they were for older archives. Every run gets a
Replay on the floor button (navigates to /?run=ID&replay=1; harmless
while Live ignores the parameters), /runs?run=ID preselects a run, and
the empty state distinguishes no runs from no filter match with a CTA.
HITLPopup reuses Modal's focus trap: Tab stays inside the gate and Esc
returns focus to the first action with a note on why the gate stays,
since a gate cannot be dismissed. The Artifacts tabs on Runs and the
kind tabs on Blocks use a roving tabindex with aria-controls. Blocks'
empty state explains what a block is and offers the first one.
TopBar's model search waits 200 ms and drops superseded answers via an
AbortController instead of firing per keystroke. docs/studio.md gains
the stuck-task story, the run-end actions, the keyboard table and the
cross-component event/URL contract.
* backends: elide old tool results on live ReAct requests
Live ReAct compaction, deterministic half only. A ReAct iteration is one
provider completion and every role is bound to its own registration, so a
provider wrapper is the one place that sees iteration N of a 16-iteration
worker with its full transcript — the same route live token streaming took.
BindRole now stacks liveElideProvider outermost (above the structured
wrapper, so the delegate and the direct constrained-decoding call send the
same transcript) for any role whose Directives carry a LiveElide policy.
Once the estimated transcript passes AtPercent of the model's context window
the content of every tool RESULT but the last five is replaced with a
placeholder. Every tool call, every tool_call_id pair, the leading system
message and every user/assistant turn stay; nothing is summarized — on a
live request the head is the role's tool contract. The rewrite is per
request and never mutates the agent's conversation, so it is repeatable and
the elided prefix is byte-identical between iterations until the keep
window slides.
The factory sizes the policy per tool-using role from the model profile's
context_limit; the orchestrator sets it from react_compact and
react_compact_at_percent. Tool-less roles, an unset policy and a model with
no known window install nothing. The config docstring, schema description,
readiness comment and docs/context.md describe both paths.
* loop: resume steer reaches the model behind pending tool calls; live compaction is wired
A checkpoint is saved when tool calls are still pending, so the restored
transcript ends on an assistant tool_calls message and the finalize steer
could not be appended as a user turn there. It was left to req.Input — and
the agent library adds Input as a user turn on a cold start only, keeping
it out of a seeded conversation. So the one resume that most needed the
turn-budget warning never saw it. The steer is now injected as a system
message right after the leading system message on that path, the technique
CompactChatMessagesWithDigest uses for its digest.
LiveReactCompactionWired flips to true: pkg/backends now elides old tool
results on live requests for tool-using roles (deterministic elision only;
summarization stays at checkpoint and resume). ReactCompactionStatus says
so, and the readiness and config consumers read it as before.
* fix(workspace,hitl,review): close the dangling-symlink jail gap, apply review entries by kind, per-ask shell approvals
Workspace:
- checkSymlinkEscape returned nil when EvalSymlinks failed, so a symlink whose
target did not exist yet passed the jail and os.WriteFile followed it,
creating the target anywhere on the host. Dangling links are now resolved
with Readlink and judged lexically against the real root (re-checked for a
chained link); anything that cannot be judged is refused.
- ws_edit/ws_write/ws_patch accept the argument spellings small models mix in
(old_string/search/old, new_string/replace/new, contents/text/body,
diff/hunk); the canonical key always wins.
- ws_write refuses an empty body on a new file (it used to write 0 bytes and
report success) and names the accepted keys; emptying an existing file needs
allow_shrink.
- A ws_read gutter on EVERY line of old_str/patch is stripped and the edit
proceeds, with a note appended so evolve still sees the drift; a partial
gutter is still refused by name.
- replace_all is honored on the tolerant ladder too: all spans of the first
matching strategy are replaced instead of reporting ambiguity.
- ws_patch: pure-insertion hunks (-N,0) insert AFTER line N as unified diff
semantics require; the marker-less SEARCH/REPLACE form is reachable; trailing
prose and Markdown fences no longer become unmatched context lines.
- The syntax guard memoizes the before-verdict per path by content hash, so
consecutive edits spawn one checker each after the first instead of two.
Review queue:
- Entries are stamped with from (ws_mv source), task_id, agent and query_id
at record time; a shell ask is no longer mirrored into the queue.
- Both appliers (Studio POST /api/review/apply and slmcode apply) switch on
kind: delete removes, mv moves the source, shell is hidden and refused.
Applying every kind as a write truncated deleted files, left moved sources
behind and wrote shell.sh at the project root.
- review_pending {pending: N} is emitted after apply/reject and whenever a
running agent records a proposal.
HITL:
- Shell asks live in per-ask files (shell/asks/<id>.json, answers/<id>.json).
The single ask.json slot let a second parallel worker overwrite the first
ask and delete the winner's answer. GET /api/shell/pending returns asks[]
alongside the first ask's fields for compatibility.
- plan.AddBoardHook / workspace.AddPendingHook are the change feeds Studio
turns into task_update / review_pending events.
* loop, agents: comments no longer describe the removed review race
* feat(studio): one vocabulary and one chip for every identifier
Column labels, ticket-state labels and seat/role glyphs move to
components/shared/labels.ts; the flat and 3D floors and the dossier
read them from there instead of each carrying a copy. API field names
are untouched — only what a person reads is unified (Team, Manager,
Task; the floor keeps "ticket" for what lies on a table).
EntityLink renders a task, agent, team, run or file as one consistent
chip that goes somewhere: task/agent -> Live ?task=/?agent= (the
dossier), team -> Teams ?team=, run -> Runs ?run=, file -> Files ?file=.
Outside a router it degrades to a plain anchor to the same path.
Types: QuerySession gains the per-run totals the server is adding
(duration_ms, tokens, cost_usd, tasks_total, tasks_done, failed_tasks,
teams); RunEvent.data may carry a task (task_update) or a pending
count (review_pending). Client: retryTask(id) for POST /api/tasks/{id}/retry.
* feat(studio): the floor keeps its state, renders on demand and can be walked by keyboard
State: the selection is now controlled by the page (LiveView keeps it
in the URL) with the wrapper's own state as the fallback; the pulse
feed, the last floor it was diffed against, the camera, follow and spin
live in a module-level store mirrored to sessionStorage, so leaving for
the Board and coming back finds the scene where it was left and what
happened in between still pulses. "reset view" restores OrbitControls'
saved state instead of remounting the Canvas.
Rendering: frameloop is 'always' only while something moves (a run,
live tickets, fresh pulses, follow, spin), 'demand' when the floor is
still — camera glides and hover eases ask for their own frames — and
'never' while the tab is hidden. Per-frame allocations are gone: scratch
vectors for the lerps and camera maths, precomputed emissive colours,
curve.getPoint(u, target), and one wall-clock read per frame shared by
everything that ages a pulse; per-table pulse filtering is memoised.
Robustness: the body cursor is reset when the pointer leaves the canvas;
webglcontextlost drops the page to the flat map with a toast, and picking
3D again retries.
Mobile: below sm the 3D/map toggle sits in a strip under the floor and
the feed opens from it as a bottom sheet; a coarse pointer with no stored
preference defaults to the map.
Keyboard: every person and ticket is also a visually hidden button that
opens the same dossier; the dossier moves focus to its close button on
open and restores it on close, and its Esc handler ignores typing
targets.
* feat(studio): one live board fed by the stream, a per-event run derivation, and URL-backed selection
Board store (hooks/useBoardStore): seeded from GET /api/tasks and
GET /api/squads, updated by the stream's task_update events (data.task
replaced by id), re-read every 30 s as a safety net, on both edges of a
run, on reconnect, and — until the server pushes its first task_update —
shortly after a structural log line, so an older server still feels
live. task_update and review_pending are board events: folded into the
store and the review badge, never rows in the log. The Board, the Live
floor, the ticker and the Teams page read it; their own pollers (3 s,
5 s, 5 s) are gone, as is the Sidebar's second health poll — the review
count comes from the stream's health poll and the review_pending event.
useBoardStore() is exported so the task rail can switch to it.
Run derivation (hooks/runDerived): phases seen, active phase and agent,
task ids, files written, token/cost totals and the newest composition
are folded once per event in the stream hook and published per flush;
LiveView, NowBar and ActivityRail consume it instead of scanning the
whole log. EventLog caches describeEvent/level/signature by event
identity, folds its insight summary incrementally, windows its rows to
the viewport plus a margin while keeping stick-to-bottom, and its agent,
task and file chips are EntityLinks.
URL state: the floor's selection lives in ?task= / ?agent= (&team=), so
a dossier survives navigation and reload and can be linked to; the Board
keeps ?team= and ?column= (a new per-column filter). focusTicket now
passes the id through as focusTaskId to the Tasks rail (LiveTaskPanel
accepts the prop; acting on it is left to its owner).
NowBar derives who is working from the floor model's working set
(readActivity/nowFor, now exported), so the clock stops after agent_end,
and its agent, task and team are links.
* docs(studio): the board store, its events, entity links and what the floor remembers
* feat(squads): a seam task is handed the whole contract
An unassigned task whose files fall in two or more squads' territory used to get no brief at all — BriefFor returned "" for every task without a squad — so the one worker building both sides of the seam was the one building without the interface spec.
BriefFor now resolves the task's files to their owners and, when two or more squads own them, returns a bounded seam brief: the squads spanned and what each owns, then every interface of the frozen contract with its provider, consumers and a clipped spec. Interfaces only, no charters; capped at twelve interfaces and 320 chars of spec each. An unassigned task inside one territory, or outside every territory, still gets nothing.
* feat(loop): measured per-role budgets and latency samples for loop requests
Runner gains two optional hooks: RoleTimeout(ctx, role) returns the measured budget for one request of a role, and OnRoleLatency(role, d, evidence) reports how long each request took. execOne and dispatchWave dispatch on min(callTimeout, RoleTimeout(base role)) — the measured value can only tighten the flat Timeout — and report every request's duration under its base role (an escalation rung shares its base role's series) with the orchestrator's evidence rule: a success or a timeout counts, any other failure does not. reviewSlots sizes the reviewer slot from the same budget.
Workers, reviewers and correctors own most of a run's wall clock and used to run on the flat task_timeout while contributing no latency samples at all; with the hooks unset nothing changes.
* fix(orchestrator): one run-wide concurrency gate, smoke memo, per-run team state, early team gate, fewer idle model calls
One concurrency limit. max_parallel was enforced only in the execute wave; context ran beside explore, architect beside clarify, speculative digs and review races added slots. Every model request now takes a slot of one run-wide weighted semaphore sized max_parallel, acquired in the executor adapter handed to the loop, in runRoleTracked and around the multipass cycle; the phase pairs run sequentially at max_parallel=1. llm_requests counts every assistant turn of a result's transcript instead of one per result, and the multipass passes are counted too.
Measured role timeouts in the loop. buildRunner wires Runner.RoleTimeout to roleTimeoutWithin and Runner.OnRoleLatency to recordRoleLatency, so loop roles are dispatched on their measured budget and finally feed latency memory.
Smoke memo. runSmokeIn remembers each command's result per (command, tree fingerprint) for the run and reuses it until something is written; the fingerprint now carries a write sequence so a rewrite of an already-changed file counts, and the formatter and a dependency install advance it. The pre-test result is handed to runQAGate for round 1; team acceptance and integration check gateRoundAffordable before running. The QA bootstrap is applied once per tree state.
Stale per-run state. Team gates, the squad plan, the single team and the team selection memo are reset at the top of both runSLM and Resume; the squad plan write is locked; restoreSquadPlan restores a one-squad squads.json as the single staffing team. Correction attempts for team tickets are now counted under the key the ticket is stamped with (they were looked up under a key nothing matched, so every ticket was attempt 1).
Model calls with nothing to do. The memory distillation runs single-shot and only when the run left a notable lesson, a changed file or a failed task; the per-wave distillation and after-wave coordinator run only on a wave that failed, escalated or produced a notable lesson; the splitter is skipped for a one-step plan over one or two known files. Every skip is announced as an info event with its reason.
Early team gate. AfterWave proves a team's half as soon as its lane is complete and has changed since it was last proved, so a red half's ticket rides the next wave; a defect is ticketed at most twice per run, then handed to a human.
Team selection is memoized per run so the composer and the charter phase do not both rescan the workspace and reload the block library.
* backends: make the slow-endpoint probe test independent of machine load
The test slept 100ms on every request against a 150ms probe budget, so a
busy test run could make the very first request miss the window and fail
the guard for the wrong reason. The first request now answers at once and
only the later ones sleep past the deadline, which is the shape the test
describes.
* fix(server,session): run lifecycle races, lock-free latest-run snapshot, buffered event log; Studio task/review/history API
Server lifecycle:
- POST /api/runs/stop no longer flips running to false while the run goroutine
is still unwinding. It sets stopping, cancels the run's own context and lets
finishRun clear running when the goroutine exits, so a following POST
/api/runs is a 409 until then. finishRun only touches shared state when its
run generation is still current, so a stale goroutine can never clear the
live run's flag, restore its options or publish over its result.
- hitl.ClearAll runs after the running check: a second click on Run (a 409)
no longer deletes the in-flight run's open shell ask.
- The SSE ring is not cleared per run (subscribers were mid-stream on it);
/api/runs/latest and the current-run activity view scope by runStartSeq.
- handleLatestRun copies under s.mu and encodes after release: the engine
emits synchronously into Server.emit, so a stalled browser fetch used to
block a worker mid tool-call.
- /api/runs/latest and /api/status report stopping.
Studio API:
- task_update events: every board task change (plan.AddBoardHook) is
published with phase = current run phase or "board", task_id, message
"<id> -> <column>" and data {"task": <task as GET /api/tasks renders it>}.
- POST /api/tasks/{id}/retry: ready_to_dev, retries reset, error cleared,
"retried from Studio" appended to attempt_log, persisted, task_update
emitted; 409 without a board, 404 for an unknown id.
- GET /api/queries items carry duration_ms, tokens, cost_usd, tasks_total,
tasks_done, failed_tasks and teams; token/cost totals are cached per
(id, size, mtime) of the event log.
- GET /api/teams/activity?query= caches the derived timeline per
(query, size, mtime) instead of re-parsing the log on every visit.
Session event log:
- One buffered appender per run instead of open/write/close per event under a
global mutex. Token deltas are not persisted; structural kinds flush on
write; chatty kinds flush on a 500ms timer; run_end/run_stop and the turn's
end (WriteTurnSummary) flush, fsync and close. ReadEvents flushes first so a
live run's tail is always visible.
* fix(backends,cli,workspace): retry streamed calls before the first delta, restore the gate terminal on cancel, keep evolve informed of in-tool repairs; docs
- retryProvider.CompleteStream / CompleteStreamWithMode now go through
retryDo. The ReAct loop takes the streaming path whenever a token sink is
attached (TUI, Studio), so a 429 or a connection refused by a model server
that was still loading got zero attempts exactly when someone was watching.
A callback wrapper tracks whether a delta was delivered: a failure before
any delta is retried like a failed Complete (fresh deadline per attempt,
the caller's callback only sees the successful attempt's deltas); once a
delta reached the callback the error is surfaced as-is, since a partial
stream cannot be replayed.
- TerminalGateHost.AskGate restores the terminal on the ctx.Done branch. The
read goroutine owned raw mode and stayed blocked in ReadKey, so a gate
abandoned by a stop or shutdown left the shell without echo. The
goroutine's own release skips the restore when a newer gate has since taken
the terminal.
- A ws_edit/ws_patch call whose ws_read gutter was stripped in-tool is still
presented to the tool observer as the refusal it would have been, followed
by a repaired retry that landed, without a second edit — so the failure is
fingerprinted, the memory rule credited and the metrics row moves.
- docs: tools.md, troubleshooting.md (aliases, empty-content refusal, gutter
stripping, ws_patch insertion/bare-form/prose semantics), studio.md (review
kinds and stamps, task_update / review_pending events, retry endpoint,
queries fields, shell pending list, stopping), permissions.md (kind-aware
apply, per-ask shell files).
* docs: changelog for the efficiency, robustness and Studio round; board store also refreshes on agent_end
The engine emits no task_start/task_done kinds of its own, so on a server
without task_update events the store's structural cue is the end of the
role that worked the task.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011RfCkcsbJZgHoQLzwkqFUL
* review applier refuses paths outside the project; annotate sanitized-id stats for the newer gosec
CI's golangci-lint 2.13.1 carries gosec's taint analysis (G703). The
review applier now checks every pending path against the project root
before touching it, which is a real guarantee rather than a comment; the
two os.Stat calls in the team-activity cache are annotated, since
session.TurnDir already reduces the id to [A-Za-z0-9_-].
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011RfCkcsbJZgHoQLzwkqFUL
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent aef8eba commit 1fec851
152 files changed
Lines changed: 13970 additions & 1593 deletions
File tree
- cmd/slmcode
- docs
- pkg
- agents
- backends
- cli
- config
- hitl
- loop
- orchestrator
- plan
- readiness
- server
- session
- squads
- workspace
- web/src
- api
- components
- Agents
- Blocks
- Board
- Docs
- Files
- Live
- floor
- Pipeline
- Review
- Runs
- Settings
- Skills
- Teams
- ui
- hooks
- styles
- types
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
33 | 39 | | |
34 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
35 | 48 | | |
36 | 49 | | |
37 | 50 | | |
38 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
39 | 54 | | |
40 | | - | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
41 | 60 | | |
42 | 61 | | |
43 | 62 | | |
44 | 63 | | |
45 | 64 | | |
46 | 65 | | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
47 | 74 | | |
48 | 75 | | |
49 | | - | |
| 76 | + | |
50 | 77 | | |
51 | 78 | | |
52 | 79 | | |
| |||
87 | 114 | | |
88 | 115 | | |
89 | 116 | | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
90 | 122 | | |
91 | 123 | | |
92 | 124 | | |
93 | 125 | | |
94 | 126 | | |
95 | 127 | | |
96 | 128 | | |
97 | | - | |
98 | | - | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
99 | 136 | | |
100 | 137 | | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
101 | 187 | | |
102 | 188 | | |
103 | 189 | | |
| |||
788 | 874 | | |
789 | 875 | | |
790 | 876 | | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
| 37 | + | |
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
170 | 170 | | |
171 | 171 | | |
172 | 172 | | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
173 | 194 | | |
174 | 195 | | |
175 | 196 | | |
| |||
0 commit comments