Repository navigation
Conversation
* docs: add playground course tech design * docs: remove tutorial v2 design * docs: refine playground course tech design * docs: simplify playground course interfaces * docs: refine playground course component contracts * docs: refine tutorial assets and copilot APIs * docs: derive tutorial JSON schemas from structs * docs: update playground course module diagram * docs: name course playground entry * docs: correct playground module ownership * docs: rename tutorial v2 tech design * docs: align tutorial v2 module boundaries * docs: correct course storage indexes * docs: refine tutorial v2 contracts
showPrelude(preludeMessage) displays the Course opening guide, mirroring the existing course-prelude concept from the current course system. It blocks until the learner dismisses it, like showMessage; how the host renders the opening guide is up to the Tutorial implementation. The example course now opens with showPrelude instead of showMessage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs: amend Tutorial v2 presentation and Spotlight contracts
- Capitalize SpotlightOptions fields (XGo auto-lowercasing applies to functions only, not struct fields) - Replace persist with duration: the auto-conceal delay in seconds, where 0 keeps the spotlight until the learner clicks anywhere - Unify the options type name across the Go and TS contracts - Drop the pointer-events behavior assertion; interaction details follow the UI design - Note in the host contract that reveal's defaults are materialized by createTutorialFramework before spotlight_reveal is invoked - Align the product docs with the persist-by-default behavior (dismissed by the learner's click; no delay-based auto-conceal in the default path) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: add browser XGo executor * refactor: reorganize XGo executor modules * refactor: flatten XGo executor frontend files * docs: document frontend XGo executor * refactor: move Tutorial binding into executor bundle * docs: add Tutorial XGo project config * refactor: flatten Tutorial framework package * fix: harden XGo executor lifecycle * refactor: rename frontend XGo executor module * fix: use current XGo package marker * feat: add XGo executor debug page * feat: validate Tutorial capabilities and events * chore: mark XGo debug page as temporary * refactor: simplify Tutorial event handling * fix: avoid deadlock in Tutorial events
* docs(tutorial): define video resources by name * docs(tutorial): address video resource review * docs(tutorial): clarify video name contract * docs(tutorial): keep module overview focused
* docs: formalize Tutorial events and remaining contract semantics - Add the TutorialEvent contract: editor.runtime.start / editor.runtime.exit / editor.runtime.log / copilot.roundFinish, dispatched by Tutorial, with per-entry, in-order, log-kind-only semantics for runtime logs - Specify Course completion semantics: complete/completeWith end the program after the current callback returns; later presentation calls are ignored and repeated completions are idempotent; document how executor exit reasons map to Course outcomes - Activate editor.project with session-project-model reading: getCode(file) and listCodeFiles(), mirrored as editor_project_* host capabilities; document codeEditor.getCode's attached-UI semantics - Annotate resolve timing for Promise-returning host capabilities (completion accepted, formatting finished, spotlight shown) - Publish the initial stable spotlight target ID list (append-only, owned by the SPX Project Editor) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply #3439 review feedback - Mirror the spotlight target-ID list into the author-facing Go contract - Reword course_completeWith to avoid contradicting course_complete's "without feedback" phrasing - Align the runtime-log channel wording with the Go contract instead of the undefined "judging channel" term - Confine editor_project_getCode resolution to the listCodeFiles set and reject path traversal and absolute paths - Document the runtime-log adaptation against the real Runtime: diff by the per-entry monotonic id (outputs is a bounded ring buffer whose indices shift once full) and fan out batched didChangeOutput notifications in order; add the missing id field to RuntimeOutput Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: define the API identifier vocabulary and spotlight target grammar - Pin filterAPIs entries to the editor's definition-identifier scheme: author shorthand "name" / "name#overloadId" resolved in the Course project's API context, or a full "xgo:<package>?<name>#<overloadId>" string; an identifier without "#overloadId" addresses all overloads - Extend spotlight targets with a parameterized family: "apiReference.<apiId>" addresses API Reference entries using the same identifiers as filterAPIs; a bare name highlights the whole overload group together - Specify failure semantics: unknown IDs (name outside the vocabulary, nonexistent overload, unpublished static ID) fail the capability call so mistakes surface during Preview; known IDs that cannot currently be resolved (filtered out, not mounted yet) retry briefly, then skip the highlight with a warning Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply #3439 review feedback on scope and contract shape - Drop the RuntimeOutput id field again: retrieval by output id has no concrete requirement yet, and may belong to the runtime module rather than being collected through Tutorial - Keep index.md at module positioning: remove the didChangeOutput adaptation detail and replace the interface enumeration with a responsibility-level description; the executor exit-reason mapping moves to the Tutorial module contract, which owns that interpretation - Use full definition identifiers for API identification: a shorthand would need mapping logic that cannot safely assume the package or receiver; overload selection by index stays - Give codeEditor.getCode a file path and add getCurrentActiveDocument, which fails when no editor is attached, so "nothing is open" is never confused with "the open file is empty"; editor.project.getCode is therefore dropped, while listCodeFiles stays for Courses whose goal is for the learner to create a sprite - Address spotlight targets with Radar selectors instead of a separate stable-ID registry; a selector matching several elements reveals them as one group, and failure is split into malformed (fails) versus currently unmatched (retries, then skips with a warning) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: align the contract with the merged executor and review feedback - Capitalize the author-facing namespace fields (Course.Editor, .Copilot, .Spotlight and Editor.Project, .Runtime, .CodeEditor, .Ruler) to match the framework package merged in #3424: XGo auto-capitalizes method calls but not struct field access. Method names stay lowercase, and the example Course is updated accordingly - Replace getCurrentActiveDocument with getActiveDocuments, returning a list: one Code Editor may have several UIs attached, each with at most one active document, so an empty list expresses "nothing is open" without introducing an error Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: read Course code through editor.project Provide editor.project.getCode(file) alongside listCodeFiles, and defer "the code the learner is currently editing" until the Code Editor's attached UIs and their active documents are settled. Reading project content and controlling the editor UI stay in separate namespaces, and no capability carries the ambiguous "current" semantics for now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address the project by sprite name SpxProject models its contents as business concepts identified by name, so the Course-facing project capabilities follow suit: listSprites returns sprite names and getCode takes one, instead of enumerating and addressing code files by path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: describe project.getCode as reading the project The project reads the sprite's code from the session project, not from a Code Editor UI buffer, so "unsaved edits" described neither of the two things it could mean: edits still held by the editor are not visible here, and Course changes are never saved to a server in the first place. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
feat(tutorial): add project domain models
* chore: restore standard staging API endpoints * chore: remove temporary Tutorial course debug runner * docs: remove stale Tutorial debug runner instructions * fix: use stable Radar names for admin and preprocessing * fix: keep Radar selector identities independent of locale * fix: preserve localized accessible labels in Radar metadata
Integrate Tutorial v2 into dev
* chore(deps): bump spx to 4.0.1 * chore(deps): pin xgolsw spx list alias fix * chore(deps): sync xgolsw review follow-up * chore(deps): use merged upstream xgolsw fix
Separate stable first-party app identities from OAuth client configurations so shared services can use consistent app references. Define product boundaries for delegated user access, app-only access with app-level scope approval, directory queries, and user profiles. Specify persistence, API and frontend changes, transaction and audit boundaries, token revocation, and an atomic migration that removes legacy OAuth storage while preserving existing client IDs, credentials, tokens, and sessions. Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
* refactor: rename spx-gui directory to gui * refactor: align GUI naming across CI and documentation
* fix(copilot): isolate global and docked panel expansion * refactor(copilot): restore preview state after docked UI unmounts * docs(copilot): explain docked panel reset on mount
Separate app registration from OAuth client configuration in the Account admin console. Approve app-only scopes per app, manage client credentials, and bind administrator-issued user tokens to the selected client. Extend the OpenAPI contract for app directory and user profile queries, and preserve public client identifiers throughout hosted sign-in. BREAKING CHANGE: app registration no longer accepts OAuth client settings. Manage clients and their secrets under the app's `oauth-clients` resources. Administrator token creation requires `oauthClientID`. Updates #3651 Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
#3727) * Polish read-only feedback and prevent blocked completion requests * Match API reference item corners to the design reference * Simplify read-only completion handling and align feedback with caret * Match latest read-only bubble shape and caret offset * Suppress API reference hover effects while read-only * Skip API reference pressed feedback while disabled * Prevent text selection in API reference items
* fix(editor): capture Simple Mode thumbnails without a transformer * fix(code-editor): hide completed empty API references * fix(editor): remove API Reference changes from thumbnail PR
* feat(spx-gui): add feedback replies and the notification panel * fix(spx-gui): follow Radar naming conventions for feedback replies and notifications * docs(product): name the feedback action "Mark as no reply needed" * refactor(spx-gui): let UITab and NotificationLink style the notification panel * fix(spx-gui): render reply images with useRenderableImageUrl * docs(spx-gui): document and test useInfiniteQueryWithCache * docs(openapi): require reply attachments in the upload bucket * docs(product): simplify the handled status description * fix(gui): keep full notification text and reply drafts - Render notification bodies and previews as complete Markdown, so the text after `<` is no longer dropped - Reload the feedback only after a reply is sent or conflicts, so a failed send keeps the draft - Preview only images in Kodo, and keep native clicks with modifier keys - Share unread counts from the notification store, accept a `null` page token, require the notification time, and rename the Radar name of the no-reply-needed button * fix(gui): always upload reply images to Kodo The backend accepts only Kodo URLs for reply attachments. Pass inlineable: false to saveFile, instead of relying on its current rule that only text files become data URLs. Tested by the admin feedback page test, which now checks the saveFile options. * refactor(gui): compose feedback replies as Markdown Use one Markdown content field for replies and notifications instead of maintaining separate attachment state, validation and rendering. Keep the normal textarea and insert uploaded images at the selection. Reuse sanitized notification rendering, preserve native linked-image behavior, and scope draft/detail state to the feedback and signed-in user. Validated with 1713 tests, type-check, changed-file ESLint and Prettier, OpenAPI references, Chromium upload/submit/preview, and scoped complexity, duplication and mutation checks. * refactor(gui): drop optional notification link changes Restore the previous modifier-click handling and remove the added Radar metadata and corresponding assertions at the user's request. Keep Markdown replies, inline image handling, and feedback/account state isolation. Validated with 1713 tests, type-check, ESLint and Prettier. * fix(gui): open notification links and preview images by element Whether a click previews an image now depends on what is clicked, not on the URL: text links always open their targets, even image URLs, and images open the preview wherever they are stored, unless they are inside a link. `custom` is meant for custom elements, so MarkdownView gets `link` and `image` entries beside `codeBlock` instead of notifications overriding native `a` and `img`. Kodo URLs are kept only for the matching entry. URLs other than Kodo URLs, such as `mailto:` and relative URLs, are kept as they are. Validated with 1713 tests, type-check, ESLint and Prettier. Targeted mutations of the new branches are all caught by the tests. * test(gui): cover MarkdownView code blocks No test reached the `codeBlock` branch of MarkdownView. Pin the current behavior: the language comes from the `language-*` class, is empty without it, and the code is passed as children. Disabling the entry, keeping the class prefix, dropping the language or dropping the code now fails the test. Validated with 1714 tests, ESLint and Prettier. * refactor(gui): let MarkdownView callers allow custom URL protocols
…ry click (#3738) * fix(ui): preserve dialogs after cross-boundary text selection * refactor(ui): share dialog mask component and clarify content element * docs(ui): explain dialog mask gesture semantics * fix(ui): preserve dropdowns after cross-boundary text selection
* Hide API Reference after filtering leaves no APIs * Clarify API Reference configuration and visibility names * Cover API item shadows with sticky headings and clarify loading comments
…e height (#3742) * feat(course-editor): expand the Copilot context field to the available height The field fills the space left in the course settings document instead of a fixed 10 rows. Six rows remain as its minimum height; below that the page scrolls. Fixes #3735 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(course-editor): keep the Copilot context field between 10 and 30 rows Restore the previous 10-row height as the minimum, and stop the field at 30 rows on tall viewports so the button and any content after it stay next to the field instead of being pushed to the bottom of the card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix: upgrade xgolsw to prevent sprite completion panic * test: remove upstream-covered completion regression
* Save management editing state and live course panel follow-up * Keep Tutorial course data consistent across management and learning Refs #3720 * Simplify Tutorial snapshots and course return navigation * Unify query modes and keep series course views consistent * test: cover nested composed queries * fix: share course page size and validate stored tutorial IDs * docs: document infinite query options
* fix(tutorial): put next course first in completion dialogs * docs: revert completion action ordering note * fix(tutorial): align guided completion button metadata and style
* fix: retain runtime call sites across source files * chore: sync ixgo execution stack dependency * chore: use upstream ixgo stack tracking version * refactor: clarify execution location variable names
* feat(tutorial): show course series title in navigation panel * docs(tutorial): record series heading decision * test(tutorial): cover course series heading updates * docs(tutorial): remove design note from issue scope
* fix(code-editor): focus input helpers after popup positioning * fix(ui): coordinate input autofocus with popup visibility * fix(ui): wait for popup readiness before autofocus * docs(ui): explain autofocus timing trade-off * test(ui): remove redundant input helper focus case
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3767 +/- ##
==========================================
+ Coverage 51.24% 59.95% +8.70%
==========================================
Files 666 772 +106
Lines 23070 27728 +4658
Branches 4122 5231 +1109
==========================================
+ Hits 11823 16625 +4802
+ Misses 10192 9590 -602
- Partials 1055 1513 +458
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
* fix: exit snippet interaction after insertion in Simple Mode * docs: explain disabling snippet stops in Simple Mode * docs: clarify snippet cancellation selection behavior
…3766) * fix(tutorial): report a run's start before the project's code runs The editor emitted didStart only after the runner's run() resolved, that is after startGame and file hashing, while the project's top-level code already runs and prints inside startGame. Courses therefore received editor.runtime.start after the first logs of the same run. ProjectRunner now emits start right before calling startGame, and the editor preview forwards it as didStart. Logs are still forwarded as they are printed. Fixes #3744 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(tutorial): check that the runner emits start before starting the game ProjectRunner had no tests, and the editor preview's tests use a stubbed runner, so nothing guarded where start is emitted. The new test runs the runner against a fake runner page whose startGame prints a line, and expects start, then startGame, then that line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(tutorial): say that a run stopped after its start keeps it The didStart documentation now states both sides: a run that fails or is stopped before the project's code starts emits no start, and one that fails or is stopped after it keeps the start it emitted. The comment on emit('start') now reads as a full sentence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Use the latest language-server fixes and register server disposal for in-process Worker tests so completed tests release project data and host callbacks. Verify that disposed instances reject subsequent messages. Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
nighca
marked this pull request as ready for review
November 13, 2026 03:42
This branch was successfully deployed
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.
[skip review]
Deployment Notes
#3650 — Progressive Course video playback
Keep the existing COEP/COOP headers. Content endpoints must allow anonymous CORS, including Range responses, and retain byte-range support. Production/CN CDN configuration was not verified by the child PR.
#3722 — Tutorial v2 backend coordination
Ensure the target backend includes goplus/builder-backend#418 and exposes the Tutorial v2 Course/Series APIs before enabling learning and authoring flows. Collaboration previews and local development now use standard staging defaults.
#3728 — Frontend directory rename
Coordinate the Vercel
xgo-team/builderRoot Directory change fromspx-guitogui, then retry deployment. This project-wide setting also affects older branches. Update repository ruleset 324471's required check fromspx-gui-linttogui-lint. The child PR did not change these external settings; verify their current state before rollout.#3706 — Feedback replies
Deploy goplus/builder-backend#416 before enabling feedback replies. The notification panel also depends on the existing endpoints from goplus/builder-backend#355.
#3690 — Account API compatibility
Deploy the matching Account admin console together with the backend cutover in goplus/builder-backend#426. Pause Account writes and stop all old backend instances before migration
023_account_oauth_clientsruns; old backends cannot use the migrated schema. Follow the backend release PR for migration order and recovery constraints. App registration no longer accepts OAuth client settings; clients and secrets use the app'soauth-clientsresources, and administrator-issued user tokens requireoauthClientID.