Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
200 commits
Select commit Hold shift + click to select a range
a494287
docs(CLAUDE.md): correct draft_admin_integrity gotcha — flag is OFF, …
jung-thomas Nov 3, 2026
4443d91
Merge pull request #3005 from sap-tutorials/worktree-doc-fix-claude-m…
jung-thomas Nov 3, 2026
5ce27f5
fix(script): prime CDS model before cds.entities() in fix-archcenter-…
jung-thomas Nov 3, 2026
f3afcd8
Merge pull request #3006 from sap-tutorials/worktree-fix-cds-load-arc…
jung-thomas Nov 3, 2026
11580bb
fix(concepts): observe HelpDocs in concept-input-digest; retire URL-f…
jung-thomas Nov 3, 2026
d66c22f
Merge pull request #3008 from sap-tutorials/fix/2998-concept-digest-h…
jung-thomas Nov 3, 2026
18c8349
fix(app-space): average branching-path time instead of summing all tu…
jung-thomas Nov 3, 2026
8a61bd8
refactor(app-space): drop unused index signature on TimeItem; add com…
jung-thomas Nov 3, 2026
ee09a5e
Merge pull request #3010 from sap-tutorials/worktree-avg-time-branchi…
jung-thomas Nov 3, 2026
77205ae
feat(community): make RSS transport an admin-toggleable DB feature fl…
jung-thomas Nov 3, 2026
952f52e
Merge pull request #3012 from sap-tutorials/worktree-community-rss-tr…
jung-thomas Nov 3, 2026
d7f258b
docs: design for Kasimir Arcade attract-mode App-Space game (#3009)
jung-thomas Nov 3, 2026
bfe3655
docs: fold builder-check decisions into Kasimir Arcade design (#3009)
jung-thomas Nov 3, 2026
f477191
docs: implementation plan for Kasimir Arcade App-Space game (#3009)
jung-thomas Nov 3, 2026
b01aa9a
feat(app-space-game): island scaffold + build wiring (#3009)
jung-thomas Nov 3, 2026
36af9b5
feat(app-space-game): level model from app-space payload (#3009)
jung-thomas Nov 3, 2026
d495d75
feat(app-space-game): feature gate (flag + webgl + data load) (#3009)
jung-thomas Nov 3, 2026
8b1eeed
feat(app-space-game): three.js renderer + attract loop (#3009)
jung-thomas Nov 3, 2026
f376db0
fix(app-space-game): onPickTrack passes goal.trackId not zone.id (#3009)
jung-thomas Nov 3, 2026
9f45047
feat(app-space-game): attract loop, demo trigger, track handoff (#3009)
jung-thomas Nov 3, 2026
c882b80
docs,build(app-space-game): verify code-split build + document island…
jung-thomas Nov 3, 2026
0fbe75c
chore(app-space-game): ASCII-normalize comments, drop dead code, add …
jung-thomas Nov 3, 2026
e10646a
fix(app-space-game): player movement + exit, real default-OFF flag, g…
jung-thomas Nov 3, 2026
252c9d8
fix(app-space-game): register APP_SPACE_GAME_ENABLED feature flag (#3…
jung-thomas Nov 3, 2026
2331ea9
Merge pull request #3013 from sap-tutorials/worktree-kasimir-arcade-d…
jung-thomas Nov 3, 2026
1984738
fix(docs): register draft-integrity-reenable runbook in sidebar
jung-thomas Nov 3, 2026
ee0e0da
Merge pull request #3014 from sap-tutorials/worktree-fix-docs-sidebar
jung-thomas Nov 3, 2026
caf4a25
fix(app-space-game): render Kasimir arcade on-screen (canvas was ~174…
jung-thomas Nov 3, 2026
86d2814
Merge pull request #3015 from sap-tutorials/fix/app-space-game-offscr…
jung-thomas Nov 4, 2026
a0488ef
docs: design for Kasimir Arcade game-feel enhancement round (#3009)
jung-thomas Nov 4, 2026
3d263ba
docs: fold animated sprite sheets into Kasimir Arcade game-feel desig…
jung-thomas Nov 4, 2026
7678200
docs: implementation plan for Kasimir Arcade game-feel round (#3009)
jung-thomas Nov 4, 2026
dce69e5
feat(app-space-game): per-machine nogame disable gate (#3009)
jung-thomas Nov 4, 2026
e589613
fix(app-space-game): readable, non-overlapping labels (#3009)
jung-thomas Nov 4, 2026
22071e7
feat(app-space-game): ephemeral ring tally state (#3009)
jung-thomas Nov 4, 2026
30c163c
fix(app-space-game): stub isGameDisabled in AppSpaceGame test mock (#…
jung-thomas Nov 4, 2026
1b93243
feat(app-space-game): deterministic completable obstacle/pit placemen…
jung-thomas Nov 4, 2026
1746c5a
feat(app-space-game): autopilot hazard navigation + never-wedge watch…
jung-thomas Nov 4, 2026
63dd148
fix(app-space-game): guarantee edge-to-edge landing clearance between…
jung-thomas Nov 4, 2026
5357523
feat(app-space-game): Kasimir sprite atlas + frame-map from new art (…
jung-thomas Nov 4, 2026
d1cee22
feat(app-space-game): animated Kasimir sprite state machine + atlas r…
jung-thomas Nov 4, 2026
5d9d15d
feat(app-space-game): wire physics/rings/anim into loop with HUD, inp…
jung-thomas Nov 4, 2026
3ef0f57
feat(app-space-game): richer parallax scene + goal glow-up (#3009)
jung-thomas Nov 4, 2026
f56f86b
fix(app-space-game): obstacle collision width is world units, not coi…
jung-thomas Nov 4, 2026
5883f4b
Merge pull request #3016 from sap-tutorials/worktree-kasimir-arcade-g…
jung-thomas Nov 4, 2026
5f3952a
chore(agents): add Copilot/VS Code agent config for Windows + PowerShell
jung-thomas Nov 5, 2026
3490e6e
Merge pull request #3017 from sap-tutorials/chore/copilot-agent-config
jung-thomas Nov 5, 2026
208ca1e
docs(openspec): propose 9 tutorial markdown syntax enhancement changes
jung-thomas Nov 5, 2026
2e74608
Merge pull request #3018 from sap-tutorials/feat/tutorial-markdown-sy…
jung-thomas Nov 5, 2026
5e7ce30
feat(parser): step heading time/optional attributes (tutorial-step-pa…
jung-thomas Nov 5, 2026
09e0228
feat(backend): tutorial completion ignores optional steps
jung-thomas Nov 5, 2026
e43afe2
feat(hugo): time chip, Optional badge/Skip, remaining-time, checklists
jung-thomas Nov 5, 2026
d8c474f
feat(mcp): surface step time/optional metadata in get_tutorial_step
jung-thomas Nov 5, 2026
7fdc738
docs(tutorials): step pacing author guide + e2e spec + tasks checklist
jung-thomas Nov 5, 2026
7727c56
feat(arcade): Kasimir space-game polish — game-feel, labels, textures…
jung-thomas Nov 5, 2026
564fd09
fix(db): regenerate staged CDS artifacts for Tutorials.optionalSteps …
jung-thomas Nov 5, 2026
8711f94
Merge pull request #3020 from sap-tutorials/feat/kasimir-arcade-polis…
jung-thomas Nov 5, 2026
449b793
Merge pull request #3019 from sap-tutorials/impl/tutorial-step-pacing
jung-thomas Nov 5, 2026
666bc29
feat(directives): registry + fence-aware directive parser (openspec: …
jung-thomas Nov 5, 2026
0005256
fix(directives): enforce label.required + tighten nested-container as…
jung-thomas Nov 5, 2026
de1eac3
feat(directives): expandDirectives rendering + param escaping
jung-thomas Nov 5, 2026
93cae8f
fix(directives): C1 render contract (structured output + safe escapin…
jung-thomas Nov 5, 2026
13dff0a
fix(directives): C2 injection test + NEW-I1 real depth guard threading
jung-thomas Nov 5, 2026
36b01d5
feat(directives): renderDirectivesAsText plain-text fallback
jung-thomas Nov 5, 2026
48aaf33
feat(directives): wire expandDirectives into compose pipeline
jung-thomas Nov 5, 2026
67128a7
feat(directives): slug:line in DirectiveParseError + tut-echo fixture…
jung-thomas Nov 5, 2026
598340a
feat(directives): MCP/AI read paths use plain-text directive fallback
jung-thomas Nov 5, 2026
4a3111a
feat(directives): directive-unknown lint rule
jung-thomas Nov 5, 2026
f53e553
feat(directives): build:directive-schema registry export
jung-thomas Nov 5, 2026
72f798c
test(directives): registry conformance + empty-registry corpus regres…
jung-thomas Nov 5, 2026
32bdeef
docs(directives): author grammar reference + pipeline gotcha
jung-thomas Nov 5, 2026
f39e0a5
chore(directives): check off completed openspec tasks
jung-thomas Nov 5, 2026
86a8650
fix(directives): empty-registry unclosed-container safety + single-qu…
jung-thomas Nov 5, 2026
e4ac2a0
docs(plan): directive-grammar implementation plan
jung-thomas Nov 5, 2026
225c8c3
Merge pull request #3021 from sap-tutorials/worktree-directive-grammar
jung-thomas Nov 5, 2026
25e5515
feat(synced-tabs): unified sync-groups client runtime + OS/codetabs a…
jung-thomas Nov 5, 2026
f899e16
fix(synced-tabs): guard stored empty string in resolveChoice
jung-thomas Nov 5, 2026
bfd4698
feat(synced-tabs): sync-presets alias/canonicalisation tables
jung-thomas Nov 5, 2026
f3731f7
feat(synced-tabs): parse sync= + frontmatter sync groups, emit sync s…
jung-thomas Nov 5, 2026
740a8d6
fix(synced-tabs): validate explicit sync= before syncOverrides:none; …
jung-thomas Nov 5, 2026
91697f3
feat(synced-tabs): WAI-ARIA option tabs + sync-group binding
jung-thomas Nov 6, 2026
2310c46
fix(synced-tabs): emit canonical syncValues on option-tabs strip buttons
jung-thomas Nov 6, 2026
ba72575
feat(synced-tabs): page picker bar + missing-variant placeholder
jung-thomas Nov 6, 2026
68d663c
feat(authoring-aids): stripAuthorNotes pre-pass (task 1)
jung-thomas Nov 6, 2026
2bee799
fix(author-notes): multi-line block body + fence-delimiter test + rev…
jung-thomas Nov 6, 2026
21a60ac
test+docs(synced-tabs): regression, author docs, e2e, meta sample
jung-thomas Nov 6, 2026
3216489
feat(synced-tabs): MCP variants preference + chosen-variant analytics
jung-thomas Nov 6, 2026
732f661
feat(authoring-aids): qa-to-prod skill warns on authoring aids (task 6)
jung-thomas Nov 6, 2026
0857a3a
feat(authoring-aids): wire stripAuthorNotes + qa-only directive into …
jung-thomas Nov 6, 2026
2a2982f
test(authoring-aids): confirm renderDirectivesAsText strips qa-only (…
jung-thomas Nov 6, 2026
ffaf40d
feat(authoring-aids): deprecated-cli lint rule (task 7)
jung-thomas Nov 6, 2026
f3b251f
fix(synced-tabs): T7 review fixes — full output pinning, meta sample …
jung-thomas Nov 6, 2026
f553a3e
feat(authoring-aids): lint rules author-notes-in-prod-source + qa-onl…
jung-thomas Nov 6, 2026
ae28237
feat(authoring-aids): freshness detector imports CLI deprecation rule…
jung-thomas Nov 6, 2026
4e3c14a
docs(authoring-aids): author docs + in-PR meta-sample (task 9)
jung-thomas Nov 6, 2026
4b6eb0c
fix(synced-tabs): correct DOM selectors, in-page fan-out, deep links,…
jung-thomas Nov 6, 2026
398ee99
Merge pull request #3022 from sap-tutorials/worktree-authoring-aids
jung-thomas Nov 6, 2026
562ff44
Merge pull request #3023 from sap-tutorials/worktree-synced-option-tabs
jung-thomas Nov 6, 2026
f12cf2e
fix(freshness): bundle-fallback for renderDirectivesAsText import (un…
jung-thomas Nov 6, 2026
47608d0
Merge pull request #3029 from sap-tutorials/fix/freshness-directives-…
jung-thomas Nov 6, 2026
681a756
feat(parsers): blockquote-alerts pre-pass hook (fence-aware identity,…
jung-thomas Nov 6, 2026
71a8d70
feat(hugo): tut-alert partial + shortcode; render-blockquote delegate…
jung-thomas Nov 6, 2026
18e713d
feat(css): callout alert icons, titles, collapsible, new types, spoil…
jung-thomas Nov 6, 2026
2e00a0c
docs(authors): alert callouts reference + callout-enhancements meta-s…
jung-thomas Nov 6, 2026
e982af8
feat(directives): register callout container directives + spoiler inl…
jung-thomas Nov 6, 2026
08f1198
feat(parsers): DETAILS missing-title hard failure + corpus regression…
jung-thomas Nov 6, 2026
ae93ca3
feat(parsers,hugo,mcp): troubleshoot-index collection + per-step entr…
jung-thomas Nov 6, 2026
ec573b2
feat(js): progressive hint reveal (callout-hints.ts) — JS enhancement…
jung-thomas Nov 6, 2026
5cd81b3
Merge pull request #3024 from sap-tutorials/worktree-callout-enhancem…
jung-thomas Nov 6, 2026
83b5eee
feat(code-blocks): console prompt/output split and command-only copy …
jung-thomas Nov 6, 2026
39cb8fd
fix(code-blocks): syntax-highlight command lines in console blocks (#…
jung-thomas Nov 6, 2026
0a04a11
feat(code-blocks): diff/focus markers with copy-final semantics (#task2)
jung-thomas Nov 6, 2026
4f2a6de
fix(code-blocks): {copy=raw} reads data-raw-content for original sour…
jung-thomas Nov 6, 2026
b4095c9
feat(code-blocks): fill-in placeholder detection and sentinel wrappin…
jung-thomas Nov 6, 2026
433f0ee
fix(code-blocks): PLACEHOLDER_RE lookbehind guards both alternatives …
jung-thomas Nov 6, 2026
eee4499
feat(code-blocks): tree fence with accessible collapsible rendering (…
jung-thomas Nov 6, 2026
c72cf19
fix(code-blocks): drop redundant aria-label on tree icons; fix isFold…
jung-thomas Nov 6, 2026
a41bbbd
feat(code-blocks): walkthrough container directive with line-range no…
jung-thomas Nov 6, 2026
5be2d74
docs(code-blocks): author guide §3.6 + in-PR meta-sample (#task7)
jung-thomas Nov 6, 2026
acf5181
test(code-blocks): plain-text fallback for walkthrough MCP consumers …
jung-thomas Nov 6, 2026
069e89f
Merge pull request #3025 from sap-tutorials/worktree-code-block-enhan…
jung-thomas Nov 6, 2026
9ddd310
feat(directives): shared src resolver + registration barrel
jung-thomas Nov 6, 2026
83d8698
feat(directives): figure container and image inline directives
jung-thomas Nov 6, 2026
a4265bf
feat(directives): compare slider directive + hasCompare frontmatter flag
jung-thomas Nov 6, 2026
a5fc573
feat(directives): cast and diagram directives + hasCast flag
jung-thomas Nov 6, 2026
3fada19
feat(tables): sortable/filterable/sticky table enhancement
jung-thomas Nov 6, 2026
2a62885
feat(rich-media): compare/hotspots client scripts, CSS, render-image …
jung-thomas Nov 6, 2026
5f9b9cd
docs(rich-media): author guide and in-PR meta-sample
jung-thomas Nov 6, 2026
ed17055
fix(rich-media): guard hotspot/compare edge cases, doc accuracy (fina…
jung-thomas Nov 6, 2026
8ad33df
Merge pull request #3026 from sap-tutorials/worktree-rich-media-and-t…
jung-thomas Nov 6, 2026
9f1283e
feat(directives): register menu/kbd/icon/ui/ask directives with valid…
jung-thomas Nov 6, 2026
1df80ad
fix(directives): guard double-registration, portable icon-dist path, …
jung-thomas Nov 6, 2026
8c2028d
feat(directives): tut-menu/kbd/icon/ui/ask shortcodes + CSS (openspec…
jung-thomas Nov 6, 2026
ece7ff1
feat(directives): kbd-os.ts OS-aware key swap + Joule ask wiring (ope…
jung-thomas Nov 6, 2026
7b0df9f
fix(directives): load kbd-os.ts on single.html tutorial layout
jung-thomas Nov 6, 2026
31b7a4d
docs: UI instruction directives author guide + meta-tutorial sample (…
jung-thomas Nov 6, 2026
5c831c7
feat(directives): advisory lint rules for :ui and :kbd migration (ope…
jung-thomas Nov 6, 2026
2adeeb3
fix(directives): add initial aria-label to tut-kbd, URL false-positiv…
jung-thomas Nov 6, 2026
4bfa7e0
Merge pull request #3027 from sap-tutorials/worktree-ui-instruction-d…
jung-thomas Nov 6, 2026
e5d27b3
feat(directives): extend types, frontmatter, and ExpandDirectivesCont…
jung-thomas Nov 6, 2026
b597fc2
feat(directives): ::include expand hook with param substitution and c…
jung-thomas Nov 6, 2026
2e8d393
feat(directives): :tutorial-ref :note-ref :help-ref :api-ref :since s…
jung-thomas Nov 6, 2026
3ef647e
fix(directives): note-ref toText returns formatted string without req…
jung-thomas Nov 6, 2026
18c4b33
feat(directives): testedWith frontmatter panel and freshness-detector…
jung-thomas Nov 6, 2026
9f5ed7c
feat(directives): ::requires prerequisite cards (task 5)
jung-thomas Nov 6, 2026
c09e8d5
feat(directives): register-all, compose/fetch-tutorials wiring (task 6)
jung-thomas Nov 6, 2026
d6974dc
docs: author guide and in-PR sample for content-reuse-and-references …
jung-thomas Nov 6, 2026
1b4a4cd
feat(islands): prereq-status.ts — batched progress hydration for prer…
jung-thomas Nov 6, 2026
6c03f13
feat(rebuild): snippet dep expansion step; snippet-deps manifest rout…
jung-thomas Nov 6, 2026
970bacc
feat(directives): fetchHelpTitles with 7-day cache; wire helpTitleCac…
jung-thomas Nov 6, 2026
ef618db
fix(content-store): correct CDS entity namespace in snippetDepsHandler
jung-thomas Nov 6, 2026
2820c47
fix(content-reuse): satisfy static guards — slug-canonical sentinel m…
jung-thomas Nov 6, 2026
ae56978
Merge pull request #3028 from sap-tutorials/worktree-content-reuse-an…
jung-thomas Nov 6, 2026
e56cb96
chore(samples): remove in-repo meta-tutorial drafts now published to …
jung-thomas Nov 6, 2026
7a82eb2
Merge pull request #3030 from sap-tutorials/chore/remove-meta-tutoria…
jung-thomas Nov 6, 2026
517faf8
fix(docs): register four /authors/ pages in VitePress sidebar
jung-thomas Nov 6, 2026
b46b15b
Merge pull request #3031 from sap-tutorials/worktree-fix-docs-sidebar
jung-thomas Nov 6, 2026
de3171d
feat(code-block): {diff} fence attribute for unified-diff blocks (tas…
jung-thomas Nov 6, 2026
f46f39f
fix(rss): send x-khoros-api-access token on Khoros JSON API calls (#3…
jung-thomas Nov 6, 2026
8bbab7c
docs(writing-tutorials): correct §3.5.2 missing-OS behavior to no-sub…
jung-thomas Nov 6, 2026
5f46de5
feat(event-report): event id parse + section-1 track render
jung-thomas Nov 6, 2026
4c6558a
fix(mcp-slicer): lazy-import renderDirectivesAsText to survive CF run…
jung-thomas Nov 6, 2026
f33b8c1
test(rss): harden khoros fail-open test against KHOROS_API_TOKEN env …
jung-thomas Nov 6, 2026
ee17925
feat(event-report): CLI wiring + buildReport with not-found/no-window…
jung-thomas Nov 6, 2026
4238084
feat(lint): expand CLI-deprecation rules + quarterly-review header (s…
jung-thomas Nov 6, 2026
ba766c2
feat(snippets): implement fetchSnippets() with per-repo + shared fetc…
jung-thomas Nov 6, 2026
dfd8278
Merge pull request #3032 from sap-tutorials/fix/khoros-api-token-3011
jung-thomas Nov 6, 2026
3627994
feat(lint): add promotion-warning lint rule (C2 — separate from depre…
jung-thomas Nov 6, 2026
8e9e5c1
fix(code-block): always strip {diff} gutter even for context-only fences
jung-thomas Nov 6, 2026
a233587
feat(event-report): section 2 abandonment + step-drop histogram
jung-thomas Nov 6, 2026
f7326d4
feat(event-report): sections 3-4 domains/audience + cf-target prod gu…
jung-thomas Nov 6, 2026
ba70fa1
feat(snippets): implement buildSnippetDeps() — ::include label scan →…
jung-thomas Nov 6, 2026
a6e7d95
feat(cast): vendor asciinema-player v3.18.0 download script + REUSE e…
jung-thomas Nov 6, 2026
8cdd184
fix(event-report): reconcile domain/audience totals with section-1 he…
jung-thomas Nov 6, 2026
ff09341
feat(snippets): origin-aware image URL rewrite in snippet content (Ta…
jung-thomas Nov 6, 2026
ecac411
feat(cast): implement cast.ts — lazy-mount asciinema player via Inter…
jung-thomas Nov 6, 2026
791959c
feat(snippets): wire fetchSnippets() + buildSnippetDeps() into fetch …
jung-thomas Nov 6, 2026
4b01a20
feat(snippets): error line mapping — augment nested snippet errors wi…
jung-thomas Nov 6, 2026
f85b213
feat(cast): verify shortcode attribute contract + cast CSS; wire vend…
jung-thomas Nov 6, 2026
17ee479
test(snippets): corpus regression guard — empty snippetMap = byte-ide…
jung-thomas Nov 6, 2026
8a4376b
fix(snippets): use explicit env var for snippet auth token instead of…
jung-thomas Nov 6, 2026
31cb6dc
fix(snippets): correct shared snippet key convention + tighten ::incl…
jung-thomas Nov 6, 2026
d0a2e16
fix(event-report): resolve entities via linked model for standalone c…
jung-thomas Nov 6, 2026
f6e1bd1
Merge pull request #3033 from sap-tutorials/worktree-clidoc-mcp-polish
jung-thomas Nov 6, 2026
f38b72e
Merge pull request #3034 from sap-tutorials/worktree-diff-attribute
jung-thomas Nov 6, 2026
d6d38cd
Merge pull request #3035 from sap-tutorials/worktree-include-prefetch
jung-thomas Nov 6, 2026
7d21a76
fix(cast): mock existsSync in vendor test 1 so it reaches the fetch p…
jung-thomas Nov 6, 2026
1383e2f
fix(mcp-slicer): static-import renderDirectivesAsText so esbuild inli…
jung-thomas Nov 6, 2026
a72f0db
feat(event-report): Berlin-parity analysis — top-abandonees list, sto…
jung-thomas Nov 6, 2026
36b5d61
Merge pull request #3036 from sap-tutorials/worktree-fix-mcp-slicer-p…
jung-thomas Nov 6, 2026
03d33c6
Merge pull request #3037 from sap-tutorials/worktree-cast-player
jung-thomas Nov 6, 2026
ad0bbe5
Merge pull request #3038 from sap-tutorials/worktree-event-app-space-…
jung-thomas Nov 6, 2026
7331c28
fix(ci): repair 3 pre-existing DEV unit-test breakages
jung-thomas Nov 6, 2026
72be98d
fix(hugo): satisfy check-hugo-safe-html gate (#797)
jung-thomas Nov 6, 2026
5dd2f3b
Merge pull request #3039 from sap-tutorials/worktree-fix-dev-unit-bre…
jung-thomas Nov 6, 2026
fdb68ec
Merge pull request #3040 from sap-tutorials/fix-hugo-safe-html-gate-797
jung-thomas Nov 6, 2026
81d6757
fix(ci): inline parser JSON + copy tut-alert partial in option-tail-l…
jung-thomas Nov 6, 2026
3036312
Merge pull request #3041 from sap-tutorials/worktree-fix-parsers-json…
jung-thomas Nov 6, 2026
37f335d
chore(release): bump MTA version to 1.43.0
jung-thomas Nov 6, 2026
03c2e37
Merge pull request #3043 from sap-tutorials/worktree-release-1.43.0
jung-thomas Nov 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .claude/hooks/block-full-test-suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ is_scoped() {
if printf '%s' "$norm" | grep -Eq '(npm (run )?test|run test:[a-z:]*) +-- +[^ -]'; then return 0; fi
# vitest run <path or -t pattern>
if printf '%s' "$norm" | grep -Eq 'vitest run +(-t|--testNamePattern|[^ -])'; then return 0; fi
# vitest run --project unit <file> (project flag followed by a file/pattern)
if printf '%s' "$norm" | grep -Eq 'vitest( run)? +--project +[a-z0-9-]+ +(-t|--testNamePattern|[^ -])'; then return 0; fi
return 1
}

Expand Down
6 changes: 0 additions & 6 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
"permissions": {
"allow": [
"mcp__plugin_cds-mcp_cds-mcp__search_model",
"Bash(rm -rf d:/projects/tutorials-poc/approuter/static/*)",
"Bash(cp -r d:/projects/tutorials-poc/hugo/public/* d:/projects/tutorials-poc/approuter/static/)",
"Bash(rm -rf approuter/static/*)",
"Bash(cp -r hugo/public/* approuter/static/)",
"Bash(mkdir -p d:/projects/tutorials-poc/scripts/grammars)",
"Bash(cp \"/c/Users/I809764/.vscode/extensions/sapse.vscode-cds-9.9.0/node_modules/@sap/cds-lsp/syntaxes/cds.tmLanguage.json\" d:/projects/tutorials-poc/scripts/grammars/cds.tmLanguage.json)",
"mcp__hana-cli__hana_query_simple"
],
"additionalDirectories": [
Expand Down
92 changes: 92 additions & 0 deletions .claude/skills/event-app-space-report/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
name: event-app-space-report
description: >-
Use when asked for completion statistics / a report for an SAP event (TechEd,
ASUG Tech Connect, DSAG, etc.) on the tutorials-ims / developers.sap.com
platform, given an app-space URL (…/app-space/?eventId=NNN) or a bare eventId.
Produces the four-section report: tutorial completions by Track, abandonment +
step-drop histogram, completer email-domain breakdown, and SAP-vs-external.
Triggers on "report/statistics from the event <url|eventId>", "app-space stats
for …", "event completion numbers".
---

# Event App-Space Report

Produces a point-in-time, read-only completion report for one event, scoped by
the event's **date window** to the tutorials linked via its mission's
CompletionPaths (Tracks). Reuses the server helper `srv/lib/event-path-buckets.js`
so Track numbers match the live app-space page.

## Input

An app-space URL (`https://developers.sap.com/app-space/?eventId=10000003&theme=…`)
or a bare `eventId` (= `Events.legacyId`). The script parses either.

## Steps

1. **Parse the eventId** from the URL (or accept the bare id).
2. **Target PROD.** The report runs against PROD HANA. Confirm you are logged in
and targeted at the **prod** space first:
```bash
cf target # org/space must be prod
cf target -s prod
```
The script enforces this (`assertCfTargetProd`) and refuses to run on any
other space — it is the only env-separation safeguard (binding follows the
current `cf` login; there is no prod-vs-dev named binding).
3. **Bind PROD HANA** if not already bound in this worktree:
```bash
cds bind -2 tutorials-hana
```
**Do NOT use the `tutorials-hana:tutorials-hana-key` service-key** — per
`docs/developers/operations/gameboard-prod-data-troubleshooting.md` it maps to
a near-empty decoy HDI container, not the live app container. Use the plain
instance binding.
4. **Run the report** (read-only; SELECT/CQL only, no writes):
```bash
cds bind --exec -- node scripts/event-report.mjs <eventId> [--json]
```
`--json` additionally prints the raw event + bucket aggregates.
5. **Present** the emitted markdown to the user (the four sections).

## Verification

Cross-check the **Track** totals against the live app-space page or the admin
`getEventBuckets` OData call for that event when the user wants assurance. The
script reuses the same `computePathBuckets` helper, so a mismatch means a
binding/environment problem (wrong space, decoy container), not a logic
difference.

## Report sections

1. **Tutorial completions by track** — total + per-Track count and share
(`CompletionPaths.name`; FK-first tutorial resolution; windowed COMPLETED/
SUPERSEDED completions).
2. **Abandoned tutorials** — a "Top abandonees by count" list, a computed
stop-pattern summary (minimum steps done before stopping; % of abandoners
who'd done 3+ steps), then per-tutorial median stop-step with "% through"
framing and a per-step drop histogram (stop-step = COMPLETED STEP records at
the user's current attempt vs `Tutorials.stepCount`).
3. **Completer email domains** — distinct completers per domain (with known
multi-domain orgs like NTT Data / EY rolled up via `ORG_DOMAIN_MAP`),
completions, completions/user; a most-engaged table + a prose callout naming
the standout high-engagement companies.
4. **SAP employees vs external** — `@sap.com` vs everyone else.

## Notes

- Read-only and prod-guarded. No writes, no deploy.
- `scripts/event-report.mjs` lives in the main repo, so it's runnable outside
this skill too (`cds bind --exec -- node scripts/event-report.mjs <eventId>`).
- Scoping is by **date window**, never `TaskRecords.event_ID` (NULL on normal
completions). Track = `CompletionPaths.name`, not Mission title.
- **Sections 3–4 reconcile with the §1 total**: domain and SAP-vs-external
counts use the same all-windowed TUTORIAL completion set as the "Total
completions" headline, not only track-member tutorials. Anonymized/null-email
completers show as `(unknown)` in the domain table and are excluded from the
SAP-vs-external split.
- **Abandonment is an approximation, not an exact count.** Stop-step counts a
user's COMPLETED STEP records at their current `attemptNumber` with no
per-step date filter, so for returning/multi-attempt users (steps completed
before the event, or under a different attempt) the step-drop histogram and
median are estimates. Treat them as directional.
11 changes: 11 additions & 0 deletions .claude/skills/tutorial-qa-to-prod/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ CONTRIB_DEF=$(gh api "repos/$CONTRIB" --jq '.default_branch') # expect: main
MAIN_DEF=$(gh api "repos/$MAIN" --jq '.default_branch') # expect: master
```

### Step 0.5 — Check for authoring aids (author notes + QA-only blocks)

After fetching the QA source (below), scan the file for leftover authoring aids:

```bash
NOTE_COUNT=$(grep -c '%%' "$FILE" 2>/dev/null || echo 0)
QA_ONLY_COUNT=$(grep -c '^:::qa-only' "$FILE" 2>/dev/null || echo 0)
```

If `NOTE_COUNT > 0` or `QA_ONLY_COUNT > 0`: **report the counts and locations** to the author and ask them to remove author notes (`%% … %%`) and resolve QA-only blocks (`:::qa-only`) before the PROD PR is opened. Authoring aids in PROD source will trigger lint warnings on the PROD build. Do not block on this (the author may have a valid reason to proceed), but make the counts visible.

### Step 1 — Fetch the QA source (source of truth for the copy)

The QA file is what the author previewed and approved — it is authoritative.
Expand Down
2 changes: 1 addition & 1 deletion .deploy/mta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ID: tutorials-ims
# Bump this on each release you deploy — it's the version shown by `cf mtas`
# and in the mtar filename (tutorials-ims_<version>.mtar). Deploy is manual:
# `cd .deploy && mbt build && cf deploy mta_archives/tutorials-ims_<version>.mtar -e ../deploy/<env>.mtaext -f`.
version: 1.42.0
version: 1.43.0

# Top-level parameters (overridable per-env via deploy/<env>.mtaext).
parameters:
Expand Down
32 changes: 32 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copilot instructions

**Read [CLAUDE.md](../CLAUDE.md) first.** It's the canonical project guide (commands, architecture, gotchas). [AGENTS.md](../AGENTS.md) has the short version. This file only covers what's specific to Copilot and to Windows/PowerShell.

## Shell (Windows / PowerShell)

- Most maintainers run PowerShell on Windows. Commands in CLAUDE.md are written in bash. Translate them, don't paste them as-is:
- `export VAR=x` becomes `$env:VAR = 'x'`.
- `&&` only chains native commands. Use `;` before PowerShell statements.
- Use `git --no-pager`.
- Wrap noisy commands (`npm run build:all`, `mbt build`, `cf deploy`, `cf logs`, test runs) in **`scripts/quiet-run.ps1 <cmd…>`**. It's the PowerShell port of `scripts/quiet-run.sh`, with the same env knobs and log dir (`.quiet-logs/`). Open the full log only when the summary isn't enough.

## Tests

- Run only **scoped** unit tests locally: `npm test -- <file-or-pattern>` or `npx vitest run <path>`. A shared `preToolUse` hook ([.github/hooks/block-full-test-suite.json](hooks/block-full-test-suite.json)) denies the full suite. That suite runs in CI.
- Admin UI e2e (`npm run test:e2e`) runs only after a deploy and skips itself when `SMOKE_BASE_URL` is unset.

## Hard rules (summary, see CLAUDE.md for the details)

- Never edit generated output: `hugo/content/tutorials/`, `gen/`, `hugo/public/`, `approuter/static/`, `mta_archives/`.
- Never run `publish-content` from a workstation. Use `gh workflow run rebuild-content.yml`.
- Default to a feature branch and a PR (`.github/pull_request_template.md`). Confirm the deploy scope with the maintainer before you deploy.
- Don't stage unrelated working-tree changes. Hugo data files (`hugo/data/*.json`) are often regenerated locally.

## Tools

- **CDS/CAP:** Use the CAP MCP server (`search_model`, `search_docs`) before you edit `.cds` or CAP code.
- **UI5/Fiori:** Use the UI5 MCP server (`get_api_reference`, `run_ui5_linter`) for `app/admin*/**`.
- **Browser checks:** Use the `playwright-test` MCP server.
- **SAP / BTP / CF lookups:** Use the `sap-devs` MCP server. The `sap-devs` CLI must be on PATH.
- **MCP setup:** `.mcp.json` is personal and git-ignored because it can hold PATs. Start from `Copy-Item .mcp.json.example .mcp.json`. On Windows, if `npx` won't start, use `"command": "cmd", "args": ["/c", "npx", ...]`. The CAP and UI5 servers come from their VS Code extensions.
- Repo skills live in `.claude/skills/`, for example `tutorial-qa-to-prod`, `provision-tutorial-repo` and `whats-new`. Use one when it matches the task.
81 changes: 81 additions & 0 deletions .github/hooks/block-full-test-suite.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env node
// Copilot preToolUse hook — port of .claude/hooks/block-full-test-suite.sh.
//
// BLOCK the full, in-process vitest suites locally — they peg the machine (concurrent
// worker pools) and take >10 min. The full suite runs in CI; locally, run a SCOPED test.
//
// BLOCKED (full in-process suites):
// npm test / npm run test / npm run test:all / npm run test:a11y / npm run test:watch
// npx vitest run --project unit|a11y (and bare `vitest run` with no file arg)
// ALLOWED (pass through):
// scoped runs: npm test -- <pattern|path> / vitest run <path/to/file>
// HTTP/remote: test:smoke, test:e2e, test:hybrid, test:smoke:personalization, etc.
//
// Contract: JSON event on stdin; prints `{}` (no decision) or a deny decision on stdout.
// Keep the regexes in sync with the bash version.
'use strict';

const fs = require('node:fs');

const SHELL_TOOLS = /^(bash|powershell|shell|run_in_terminal|runInTerminal)$/i;

function readEvent() {
try {
return JSON.parse(fs.readFileSync(0, 'utf8') || '{}');
} catch {
return {};
}
}

function extractCommand(event) {
const toolName = event.toolName ?? event.tool_name ?? '';
if (toolName && !SHELL_TOOLS.test(toolName)) return '';
let args = event.toolArgs ?? event.tool_input ?? {};
if (typeof args === 'string') {
try {
args = JSON.parse(args);
} catch {
return args;
}
}
return typeof args?.command === 'string' ? args.command : '';
}

function isScoped(norm) {
if (/(npm (run )?test|run test:[a-z:]*) +-- +[^ -]/.test(norm)) return true;
if (/vitest run +(-t|--testNamePattern|[^ -])/.test(norm)) return true;
// `vitest run --project unit <file>` — project flag followed by a file/pattern.
if (/vitest( run)? +--project +[a-z0-9-]+ +(-t|--testNamePattern|[^ -])/.test(norm)) return true;
return false;
}

function isFullSuite(norm) {
if (/(^|[;&|] *)(npm (run )?test( +--project +(unit|a11y))?|npm run test:all|npm run test:a11y|npm run test:watch)( |$)/.test(norm)) return true;
if (/vitest( run)? +--project +(unit|a11y)( |$)/.test(norm)) return true;
if (/(^|[;&|] *)(npx )?vitest( run)? *$/.test(norm)) return true;
return false;
}

function decide(cmd) {
// Strip a leading quiet-run wrapper so `quiet-run.ps1 npm test` is judged like `npm test`.
const norm = cmd
.replace(/\s+/g, ' ')
.trim()
.replace(/(^|[;&|] *)(\.?[\\/])?(scripts[\\/])?quiet-run\.(sh|ps1) +/g, '$1');
if (norm && isFullSuite(norm) && !isScoped(norm)) {
return {
permissionDecision: 'deny',
permissionDecisionReason:
'BLOCKED: the full local test suite is disallowed on this project — it pegs the machine and already runs in CI. ' +
"Run a SCOPED test instead: 'npm test -- <file-or-pattern>' or 'npx vitest run <path/to/file>'. " +
'Allowed remote suites: test:smoke / test:e2e / test:hybrid.',
};
}
return {};
}

if (require.main === module) {
process.stdout.write(JSON.stringify(decide(extractCommand(readEvent()))));
}

module.exports = { decide, extractCommand };
12 changes: 12 additions & 0 deletions .github/hooks/block-full-test-suite.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"command": "node .github/hooks/block-full-test-suite.cjs",
"timeoutSec": 10
}
]
}
}
9 changes: 9 additions & 0 deletions .github/instructions/admin-ui.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
applyTo: "app/admin/**,app/admin-shell/**"
---
# Admin UI (SAPUI5 / Fiori Elements)

- Use the UI5 MCP server: `get_api_reference` for APIs, `run_ui5_linter` and `run_manifest_validation` before you finish.
- Components load as headless componentUsages inside the `sap.tnt.ToolPage` shell (`app/admin-shell/`). The theme is `sap_horizon`.
- **Deploy gate:** Admin UI changes need a full `npm run deploy -- --env <env>`. Don't use `--skip-build` or `-m` scoping, and never bypass Step 3.5 (`scripts/check-shipped-admin-bundle.cjs`). Without a full deploy, a stale admin UI ships.
- User-facing changes should come with an e2e spec (see `docs/developers/reference/e2e-coverage-pattern.md`).
10 changes: 10 additions & 0 deletions .github/instructions/cds.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
applyTo: "db/**/*.cds,srv/**/*.cds,app/*.cds,db-qa/**"
---
# CDS model

- Before you edit, look up entities and annotations with the CAP MCP server: `search_model` for the compiled model, `search_docs` for CAP docs.
- Don't select a HANA BLOB in the same CDS QL query as its metadata. LOB locators expire. Use raw `db.run()`, following the pattern in `srv/lib/content-store.js`.
- Slugs on `TutorialMeta`, `Tutorials`, `Missions` and `Groups` are unique and lowercase. New write paths must upsert on slug.
- Don't bypass `@requires` or `@restrict`. Never edit `gen/`; regenerate it with `cds build`.
- Keep `using` side-effect imports, for example the TechEd one in `db/external-content.cds`.
11 changes: 11 additions & 0 deletions .github/instructions/hugo.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
applyTo: "hugo/**,hugo-apps/**,scripts/parsers/**,scripts/fetch-tutorials.ts"
---
# Hugo, islands and parsers

- `hugo/content/tutorials/` is entirely generated, so never edit it. Change `scripts/parsers/` instead, or the source tutorial repos in the `sap-tutorials` org.
- Tutorial HTML is served from HANA BLOBs, not from `hugo/public/`. Publish through `gh workflow run rebuild-content.yml`, never from a workstation.
- Deploys refuse a dirty tree under `hugo/assets/**` or `hugo/layouts/**` (Step 0.5). Commit or stash those files before deploying.
- `ignore-scripts=true` means `pre*` and `post*` hooks never run. The island manifest and page fallback are explicit `build:all` steps.
- Compare tutorial slugs with `.toLowerCase()`.
- Served tutorials render `<main>` and `<h1>`, not `<article>`. Keep that in mind when writing e2e selectors.
9 changes: 9 additions & 0 deletions .github/instructions/srv-lib.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
applyTo: "srv/lib/**"
---
# srv/lib

- **srv-qa cp-list audit:** If you change anything here, re-walk the transitive `./` imports from `srv/lib/content-store.js`. Confirm that every dependency is in the `srv-qa` `cp` list in `.deploy/mta.yaml`. A missing dependency crashes QA at boot.
- `srv/lib/completion-rollup.js` is not a dependency of `content-store.js`. Group and mission completions are derived from rollups (see CLAUDE.md, "Completions rollup").
- Feature flags (`KG_*`, provenance, NGDS) fail open and default to OFF. Keep it that way.
- Run scoped tests for the module you touched: `npm test -- <pattern>`.
Loading
Loading