Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
310f183
docs(ktt): design spec for Kasimir Teaches TLAs (KTT)
jung-thomas Sep 12, 2026
0fdbdbb
docs(ktt): implementation plan for Kasimir Teaches TLAs (KTT)
jung-thomas Sep 12, 2026
5697263
feat(ktt): add KTT_LESSON task type and KttLessons catalog entity
jung-thomas Sep 12, 2026
46c3839
feat(ktt): KttService.completeLesson records KTT_LESSON TaskRecord (i…
jung-thomas Sep 12, 2026
89e3a97
feat(ktt): syncProgress merges local and HANA progress on login
jung-thomas Sep 12, 2026
aed6a0e
feat(ktt): surface KTT lessons in MyCompletions as kind:ktt
jung-thomas Sep 12, 2026
303d520
feat(ktt): fail-open Kasimir banter action backed by @cap-js/ai
jung-thomas Sep 12, 2026
1949a9a
feat(ktt): register KTT_ENABLED db flag and gate /ktt write actions
jung-thomas Sep 12, 2026
4a63c86
feat(ktt): lesson schema, generator, and reviewed content data file
jung-thomas Sep 12, 2026
ab56b60
fix(ktt): correct CDL/LOB facts and harden lesson validation
jung-thomas Sep 12, 2026
3e52f92
feat(ktt): scaffold ktt Vue island and register Vite entry
jung-thomas Sep 12, 2026
b2a39f4
feat(ktt): pure lesson engine — scoring, XP, wrong-answer re-queue
jung-thomas Sep 12, 2026
e264e7b
feat(ktt): rigged SVG Kasimir with mood state machine + reduced-motion
jung-thomas Sep 12, 2026
6689e6c
feat(ktt): skill-tree map with lesson lock/unlock/done states
jung-thomas Sep 12, 2026
d4ccaf0
feat(ktt): lesson runner, results, local progress + best-effort serve…
jung-thomas Sep 12, 2026
04efe7e
fix(ktt): real XP emit, Results delta, immediate screen transition, O…
jung-thomas Sep 12, 2026
82b8aee
feat(ktt): Hugo page + layout with SSR shell and island mount
jung-thomas Sep 12, 2026
9465158
feat(ktt): add KTT to the Explore navigation menu
jung-thomas Sep 12, 2026
073fd89
build(ktt): generate ktt lessons as part of build:all
jung-thomas Sep 12, 2026
e9842df
test(ktt): post-deploy e2e smoke for /explore/ktt/ (self-skipping)
jung-thomas Sep 12, 2026
53f6cb2
fix(ktt): seed KttLessons catalog via generated CSV
jung-thomas Sep 12, 2026
3e56e5d
fix(ktt): fail closed when KTT_ENABLED is off
jung-thomas Sep 12, 2026
1f089b0
fix(ktt): use csrfFetch for POST actions; stage KttLessons csn snapshot
jung-thomas Sep 12, 2026
6cc8fcc
test(2245): pin provenance JWS verify to fixture clock (fix time-bomb)
jung-thomas Sep 12, 2026
a6ca135
build(ktt): regenerate csn + migration table with cds 10.1.0 compiler
jung-thomas Sep 12, 2026
6629109
feat(ktt): redraw Kasimir as recognizable grey tuxedo cat mascot
jung-thomas Sep 12, 2026
4d41fb4
build(ktt): stamp csn with lockfile-pinned compiler v7.0.1 (match CI)
jung-thomas Sep 12, 2026
ee9a204
feat(ktt): refine Kasimir — smaller warm eyes, blink in all moods, fi…
jung-thomas Sep 12, 2026
a85836c
feat(ktt): pass-3 Kasimir polish — remove double whiskers, per-eye co…
jung-thomas Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions db/data/com.sap.developers.ims-KttLessons.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ID;legacyId;slug;unitId;title
9077e000-0000-4000-8000-000000090001;90001;unit-1-platform-lesson-1;unit-1-platform;Who's SAP, and what's BTP?
9077e000-0000-4000-8000-000000090002;90002;unit-1-platform-lesson-2;unit-1-platform;The CAP Stack
9077e000-0000-4000-8000-000000090003;90003;unit-1-platform-lesson-3;unit-1-platform;Deploying & Operating
9077e000-0000-4000-8000-000000090004;90004;unit-2-cds-lesson-1;unit-2-cds;The CDS Language Family
9077e000-0000-4000-8000-000000090005;90005;unit-2-cds-lesson-2;unit-2-cds;Protocols & Standards
9077e000-0000-4000-8000-000000090006;90006;unit-2-cds-lesson-3;unit-2-cds;Tools of the Trade
9077e000-0000-4000-8000-000000090007;90007;unit-3-hana-lesson-1;unit-3-hana;The HANA Universe
9077e000-0000-4000-8000-000000090008;90008;unit-3-hana-lesson-2;unit-3-hana;Integration & Migration
9077e000-0000-4000-8000-000000090009;90009;unit-3-hana-lesson-3;unit-3-hana;Data Engineering Basics
9077e000-0000-4000-8000-000000090010;90010;unit-4-security-lesson-1;unit-4-security;Authentication & Tokens
9077e000-0000-4000-8000-000000090011;90011;unit-4-security-lesson-2;unit-4-security;Identity & Factors
9077e000-0000-4000-8000-000000090012;90012;unit-4-security-lesson-3;unit-4-security;Business & Governance
13 changes: 13 additions & 0 deletions db/ktt.cds
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace com.sap.developers.ims;
using { com.sap.developers.ims as ims, cuid } from './schema';

/** Catalog of KTT lessons — metadata only, so a KTT_LESSON completion
row in TaskRecords can join to its title/kind in MyCompletions.
Progress lives in TaskRecords, not here. Seeded from hugo/data/ktt_lessons.json. */
entity KttLessons : cuid {
legacyId : Integer @assert.unique; // stable int used as TaskRecords.taskLegacyId
slug : String(120) @assert.unique;
unitId : String(60);
title : String(200);
order : Integer default 0;
}
42 changes: 42 additions & 0 deletions db/last-dev/csn.json
Original file line number Diff line number Diff line change
Expand Up @@ -3840,6 +3840,48 @@
},
"@cds.persistence.name": "COM_SAP_DEVELOPERS_IMS_UIEVENT"
},
"com.sap.developers.ims.KttLessons": {
"kind": "entity",
"doc": "Catalog of KTT lessons — metadata only, so a KTT_LESSON completion\nrow in TaskRecords can join to its title/kind in MyCompletions.\nProgress lives in TaskRecords, not here. Seeded from hugo/data/ktt_lessons.json.",
"@cds.persistence.journal": true,
"elements": {
"ID": {
"key": true,
"type": "cds.String",
"length": 36,
"@cds.persistence.name": "ID"
},
"legacyId": {
"@assert.unique": true,
"type": "cds.Integer",
"@cds.persistence.name": "LEGACYID"
},
"slug": {
"@assert.unique": true,
"type": "cds.String",
"length": 120,
"@cds.persistence.name": "SLUG"
},
"unitId": {
"type": "cds.String",
"length": 60,
"@cds.persistence.name": "UNITID"
},
"title": {
"type": "cds.String",
"length": 200,
"@cds.persistence.name": "TITLE"
},
"order": {
"type": "cds.Integer",
"default": {
"val": 0
},
"@cds.persistence.name": "ORDER"
}
},
"@cds.persistence.name": "COM_SAP_DEVELOPERS_IMS_KTTLESSONS"
},
"com.sap.developers.ims.CatGameAwards": {
"kind": "entity",
"doc": "\"Hit the Cat\" mini-game daily point ledger (issue #2042).\n\nOne row = one calendar day on which a signed-in player earned the daily\ncat-game award during a given Devtoberfest event. The award endpoint\n(POST /api/devtoberfest/cat-game/award) writes exactly one row per\n(user, event, day): 5 points per day, once per day, capped at 100 points\ntotal per event, and only while that event is active.\n\nThe natural (user, event, awardDate) tuple is the PRIMARY KEY — no surrogate\nID — so HANA enforces the once-per-day rule at the DB layer: a second insert\nfor the same day collides on the PK and the handler maps it to\n\"already-today\" (race-safe, unlike a CAP-only @assert.unique which this\nrepo's raw db.run() inserts bypass — see srv/lib/resolve-db-user.js).\n\n`createdAt` (from `managed`) is the actual award instant and is what the\ncross-container GAMEBOARD_BONUS_V1 view exposes as AWARD_DATE, so the\ngameboard's event-window filter always sees an in-window timestamp (the\nendpoint only ever inserts while the event is live).",
Expand Down
1 change: 1 addition & 0 deletions db/persistence.cds
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ annotate ims.ChannelCollections with @cds.persistence.journal;
annotate ims.ChannelCollectionItems with @cds.persistence.journal;
annotate ims.ChannelTopicMap with @cds.persistence.journal;
annotate ims.ChannelSubmissions with @cds.persistence.journal;
annotate ims.KttLessons with @cds.persistence.journal;
5 changes: 3 additions & 2 deletions db/schema.cds
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ using from './advocates';
using from './devtoberfest';
using from './homepage';
using from './channels';
using from './ktt';

// Sequence-backed business ID for backward compatibility with legacy integer IDs
aspect LegacyKeyed {
Expand All @@ -16,7 +17,7 @@ aspect LegacyKeyed {
type ExperienceLevel : String(255) enum { beginner; intermediate; advanced; }
type TaskStatus : String(50) enum { ACTIVE; INACTIVE; }
type MissionType : String(20) enum { SEQUENTIAL; SET; }
type TaskType : String(20) enum { TUTORIAL; GROUP; CHECKPOINT; PUZZLE; PETOBERFEST; }
type TaskType : String(20) enum { TUTORIAL; GROUP; CHECKPOINT; PUZZLE; PETOBERFEST; KTT_LESSON; } // KTT (#KTT) — mostly-fun acronym trainer
type EventType : String(20) enum { DEVTOBERFEST; TECHED; CODEJAM; CHALLENGE; OTHER; }

aspect TaskBase : cuid, managed, LegacyKeyed {
Expand Down Expand Up @@ -192,7 +193,7 @@ entity TaskRecords : cuid, managed, LegacyKeyed {
// NVARCHAR(5000); the enum is enforced at the CDS layer (@Common.ValueList
// dropdowns + admin write-paths) rather than as a DB constraint, so this
// change requires no .hdbmigrationtable ALTER.
taskType : String enum { TUTORIAL; MISSION; GROUP; STEP; CHECKPOINT; PUZZLE; PETOBERFEST; };
taskType : String enum { TUTORIAL; MISSION; GROUP; STEP; CHECKPOINT; PUZZLE; PETOBERFEST; KTT_LESSON; }; // KTT (#KTT) — mostly-fun acronym trainer
status : String enum { COMPLETED; IN_PROGRESS; SUPERSEDED; };
progress : Integer default 0;
completionTime : Int64;
Expand Down
10 changes: 10 additions & 0 deletions db/src/com.sap.developers.ims.KttLessons.hdbmigrationtable
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
== version=1
COLUMN TABLE com_sap_developers_ims_KttLessons (
ID NVARCHAR(36) NOT NULL,
legacyId INTEGER,
slug NVARCHAR(120),
unitId NVARCHAR(60),
title NVARCHAR(200),
"ORDER" INTEGER DEFAULT 0,
PRIMARY KEY(ID)
)
Loading
Loading