Informe JSON sin procesar legible por máquina
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 1469,
"has_wiki": false,
"homepage": null,
"languages": {
"Shell": 9021,
"Python": 73037,
"JavaScript": 31640,
"PowerShell": 3787,
"TypeScript": 1039141
},
"pushed_at": "2026-07-27T00:21:06Z",
"created_at": "2026-03-28T21:31:57Z",
"owner_type": "User",
"updated_at": "2026-07-27T00:21:10Z",
"description": null,
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "TypeScript",
"significant_languages": [
"TypeScript"
]
},
"owner": {
"blog": null,
"name": null,
"type": "User",
"login": "juergenbeck",
"company": null,
"location": null,
"followers": 0,
"avatar_url": "https://avatars.githubusercontent.com/u/19701813?v=4",
"created_at": "2016-06-02T04:53:20Z",
"is_verified": null,
"public_repos": 3,
"account_age_days": 3710
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [],
"recent_commits": [
{
"oid": "e3fa8e976cd9e049c9ad2f3e3292e4ab55518306",
"body": "Nach ADR-028 prüft der Hook nur noch hinzugefügte Zeilen. Damit entfällt der\nGrund, eigene Prosa in handover/, changelog/, reviews/, research/, recherche/,\npoc/, _archive/ und 99_archiv/ auszunehmen, ebenso alte-notizen,\nlessons-learned und skeptiker-review. Neue Dateien dort werden jetzt geprüft.\n\n\n[…]\nieden:\nbacklog und planung sind in der Praxis DevOps-Dumps, memory-snapshot ist eine\nKopie, die man nicht anfassen darf.\n\nDieselbe Klassifikation in DEFAULT_EXCLUDE_RE (Wirkung nur im md_only-Profil).",
"is_bot": false,
"headline": "generated-Ausnahmen auf ihren eigentlichen Zweck entschlacken",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-27T00:21:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f7c168a0fb9dad37cb6858e605e8278131e61fac",
"body": "Die zentrale Hook-Kette verbot bisher nur den Rechtspfeil (U+2192),\nMarkants lokale typo_check_lib dagegen alle fünf. Damit war das\nBereinigungswerkzeug fix-typografie.py strenger als der Hook, den es\nbedient, und dieselbe Regel wirkte je nach Repo unterschiedlich.\n\nJetzt einheitlich in commit-msg, \n[…]\nock-typografie.py und\ncheck-tool-umlaute.py: U+2192, U+2190, U+2194, U+21D2, U+21D4.\n\nVerifiziert: alle fünf Zeichen blocken an allen vier Punkten, Zitate in\nBackticks und Code-Fences bleiben erlaubt.",
"is_bot": false,
"headline": "Typografie-Sperre auf alle fünf Pfeilzeichen erweitern",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-27T00:05:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a69f9ceaa4bbc7f192b0046b2fcf95dbcdf38ceb",
"body": "Bisher prüfte der Hook den ganzen Dateiinhalt. Damit verlangte er Änderungen an\neingefrorener Historie, sobald jemand eine alte Datei aus anderem Grund anfasst, und\ndie Pfad-Ausnahmeliste musste jede Ordner-Umbenennung nachziehen (bei handover ->\nsessions ist genau das misslungen).\n\nDer Scan läuft w\n[…]\n\n\nBelegt an drei Fällen: neue Datei mit Verstoß blockiert; Bestandsdatei mit 17\nAlt-Verstößen plus sauberer Zeile läuft durch; Bestandsdatei mit unsauberer neuer\nZeile blockiert genau an dieser Zeile.",
"is_bot": false,
"headline": "Pre-Commit prüft ab jetzt nur hinzugefügte Zeilen (ADR-028)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-26T23:07:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d1a8271821280d4c1075d124c2bc16bf212806a6",
"body": "Der Stamm \"aussehen\" stand in ss_stems, obwohl das Wort korrekt\ngeschrieben ist (aus plus sehen) und gar keine Variante mit ss hat.\nEr blockte dadurch eine korrekte Commit-Message am Wort \"aussehendes\".\nNach der Pruefregel im Skill umlaute darf nur ein Stamm in die Liste,\ndessen korrekte Form ein scharfes s traegt.",
"is_bot": false,
"headline": "Umlaut-Trigger: Fehlalarm-Stamm aussehen entfernt",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-26T22:36:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "77bf999c430405f443a4c721c3a74879354ba12d",
"body": "Die Trigger-Liste kannte bisher nur die voll ASCII-isierte Form solcher\nWörter (`groess`, `gemaess`), nicht die halb korrekte Mischform, bei der\nder Umlaut richtig steht und nur das scharfe s durch ss ersetzt ist. Genau\ndiese Schreibweise rutschte am 26.07. unbemerkt in eine Commit-Message.\n\nNeu in \n[…]\n\nein massiver Fehlalarm. Aufgenommen wird nur, wessen korrekte Form ein\nscharfes s trägt.\n\nIsoliert verifiziert: alle vier Stämme blocken einzeln, die Gegenprobe mit\nflüssig und Schlüssel läuft durch.",
"is_bot": false,
"headline": "Umlaut-Hooks: Mischformen mit korrektem Umlaut und falschem ss ergänzt",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-26T19:12:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3cd030c51470a47a2c9b2c4e016cb4a09e31878d",
"body": "…enommen\n\nDer Stamm für „außerdem\" fehlte in der zentralen Trigger-Liste; eine Commit-Message\nmit dem Surrogat lief ungeblockt durch. Als fc=false ergänzt, wirkt also nur im\ncommit-msg-Hook: die Datei-Treffer liegen überwiegend in eingefrorener Historie\n(Handover- und State-Snapshots), die man nicht\n[…]\nthooks/fix-typografie.py ersetzt verbotene Typografie\nregelbasiert in Markdown, mit derselben Fundstellen-Logik wie der Hook. Damit\nbekommt jedes Repo das Werkzeug über den Sync statt über eine Kopie.",
"is_bot": false,
"headline": "Umlaut-Trigger ergänzt und Typografie-Werkzeug in die Hook-Kette aufg…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-26T16:50:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f547cd8a752786b8f2a5c90e3619b54b17d92e6d",
"body": "Zentrale Trigger-Liste um den fehlenden Stamm für Wächter ergänzt (wirkt nur im\ncommit-msg-Hook, damit Personennamen in Dateien nicht blockiert werden). Der Sync\nzieht zugleich den seit dem letzten Rollout aufgelaufenen Stand der Kette nach.",
"is_bot": false,
"headline": "Umlaut-Hooks: Trigger-Stand 2026-07-26 nachgezogen",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-26T15:43:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "772a2f4ad10f1dd14e3cc74544511474febf9bcb",
"body": "Zentral in umlaute-triggers.json auf fc=true gesetzt und per Sync-UmlautTriggers.ps1 ausgerollt. Vorher fing nur die Commit-Message-Prüfung diesen Stamm, die Datei-Inhalt-Prüfung nicht.",
"is_bot": false,
"headline": "Umlaut-Trigger: Stamm `waere` gilt jetzt auch für Datei-Inhalte",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-26T09:12:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e7db0023d24dced1a4738ac680e699c8a07426f9",
"body": "…ommit- und commit-msg-Check)",
"is_bot": false,
"headline": "Umlaut-Sync: Typografie-Sperre ausgerollt (block-typografie.py, pre-c…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-25T19:58:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1a753cf915cf34539806c310de0037dc5c1f4a0a",
"body": "…docs (RETRO13-02/-03, OE-26 option 0)",
"is_bot": false,
"headline": "devkit 0.10.2, cli 0.10.8: AGENT.md cross-WebResource + submit-idiom …",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-21T19:48:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "890ac2eebbce0c5e0d1cf01a6a3299b9680015d4",
"body": "…tValue() without submit (RETRO13-01)",
"is_bot": false,
"headline": "devkit 0.10.1, cli 0.10.7: gate + AGENT.md flag off-form $unsafe().se…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-21T19:21:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9947f1c71a8a70294e268c964a0bf510fd33f75c",
"body": null,
"is_bot": false,
"headline": "Release @xrmforge/devkit 0.10.0, cli 0.10.6 (OE-25 tests/ static checks)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T13:41:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4fabeeba846f3c20d9876598b7bbc5716fe6e965",
"body": "Scaffolded projects excluded tests/ from both tsc (include: src/ + generated/ only)\nand eslint (files: src/**), so test code had no static analysis - only vitest runtime\nexecution. This adds:\n\n- tsconfig.tests.json (extends tsconfig.json, skipLibCheck true, types xrm+node,\n includes tests/): a seco\n[…]\ne error in a\n test file fails tsconfig.tests.json).\n\nVerified against the markant showcase: the tests/ typecheck surfaces 49 real,\npreviously-hidden test-code type errors (retrieveRecord mock casts).",
"is_bot": false,
"headline": "Typecheck and lint tests/ in scaffolded projects (OE-25)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T13:38:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "428fa0b1d4be897f2f220888dfff69138830c610",
"body": "Neue Heuristik is_frontmatter_value in der geteilten umlaut_check_lib: ein\neinzelner Skalar-Wert im führenden YAML-Frontmatter (z.B. `name: zellenlaeufer`)\nwird als technischer Bezeichner ausgenommen, ohne Whitelist. Prosa-Werte und\nVorkommen außerhalb des Frontmatters bleiben geprüft. Zentraler Sync-Nachzug\naus dem Template (claudecode 5eb22a1).",
"is_bot": false,
"headline": "Umlaut-Check: Frontmatter-Wert-Filter (ADR-2026-07-19-1123)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T10:56:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "86b81eba4d7598a3aa3802da660fbb7eb3d29265",
"body": "…CONS-02)",
"is_bot": false,
"headline": "Release @xrmforge/devkit 0.9.1, cli 0.10.5 (AGENT.md gate note for F-…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T08:07:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "14c0d323b76939d7b3508ea04af9ea66c9215eee",
"body": "…te check)",
"is_bot": false,
"headline": "Release @xrmforge/devkit 0.9.0, cli 0.10.4 (F-CONS-02 any-response ga…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T07:17:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6b4fc2c5c813b6ebfacc5824913e20a150ba0bcc",
"body": "New multi-line check \"Untyped retrieveRecord response\" in validate-form.mjs\n(checkUntypedRetrieveRecord). retrieveRecord<T = any> returns any by default,\nso an uncast response is silently any and no existing gate catches it\n(no-explicit-any, tsc, Check 3p all pass).\n\nThe check scans the whole declar\n[…]\n is flagged; `as any`/`as Record` go to no-explicit-any / Check 3p.\n\nScaffold regression test added. Changeset: devkit minor, cli patch.\nVerified live against markant: 9 real finds, 0 false positives.",
"is_bot": false,
"headline": "F-CONS-02: gate check for untyped (any) retrieveRecord responses",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T05:48:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5e8b5fc460821c6a8f42c691be63bb2f64ce000b",
"body": "….10.3",
"is_bot": false,
"headline": "Release @xrmforge/helpers 0.17.0, typegen 0.20.0, devkit 0.8.0, cli 0…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T01:17:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c9277bbda252102603c9ea5cea00eaf9258d5807",
"body": "…ed gate\n\nhelpers (minor): parseLookup/parseLookups/parseFormattedValue/expanded/expandedMany\ntake WebApiRecord (object & { length?: never }) - a response cast to a generated\nEntity interface goes straight in (no Record cast, never left as any), while a whole\nresult collection passed by mistake (a f\n[…]\n: unknown } (F-CONS-03); AGENT.md\nteaches the direct reader path, documents normalizeGuid, points to form-index.json.\n\ncli (patch): re-pin. Changesets added; NOT published (awaiting release approval).",
"is_bot": false,
"headline": "OE-21/OE-22/OE-23 + F-CONS-01/03: reader signatures, form-index, scop…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-19T01:06:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c20be4b99c370e699577e02369e71a4a60dd99a7",
"body": "… regression)\n\nThe scaffold eslint.config.js now ignores legacy-reference/** in addition to dist/\nand scripts/, so `pnpm lint` (eslint .) stays green on migration-reference code left\nunconverted, aligned with the validate-form gate (eslint src/).\n\nThe Session-71 fix (A71-03) lived only in the generated showcase eslint.config.js\n(untracked) and was lost on the round-13 reset; moving it into the devkit template\nmakes it durable. Adds a scaffold regression test.\n\ndevkit 0.7.41, cli 0.10.2 (patch).",
"is_bot": false,
"headline": "Scaffold eslint: ignore legacy-reference/** (fixes F-MK13-01 / A71-03…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-18T12:03:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "91837036a23bdbe87a4765124f554801a0754627",
"body": "Hebt die generierten Hook-Dateien (commit-msg, umlaut_check_lib.py,\ncheck-tool-umlaute.py, README) auf den aktuellen Stand der zentralen\nTrigger-Liste und Templates. Neu im Dateinamen-Erkenner der Lib: die\nDiagramm-Endungen (drawio, mmd, mermaid, puml, plantuml, vsdx) plus\nJSON-Key-Filter, damit solche Dateinamen nicht mehr als Umlaut-Verstoß\ngewertet werden.",
"is_bot": false,
"headline": "Umlaut-Hook-Kette auf zentralen Template-Stand aktualisiert",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-12T20:16:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "48f1b5a872b16ed1677f232d02a5ba7f9e16eabc",
"body": "… scaffold)",
"is_bot": false,
"headline": "Release @xrmforge/devkit 0.7.40, @xrmforge/cli 0.10.1 (wrapEnableRule…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-08T14:01:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "45f4df4c7649146e17da04cd8801b18ddeb360d2",
"body": "A ribbon Enable Rule must be synchronous and return a boolean; an async rule\nreturns a truthy Promise (the button is then always shown - a common legacy bug).\nwrapEnableRule wraps it fail-closed (false on error), logs only, never a banner\n(it runs on every ribbon refresh). Added to the error-handler.ts template, the\nvalidate-form.mjs HANDLER_WRAPPERS gate, the AGENT.md instructions and the\nscaffold test. Changeset: devkit patch.",
"is_bot": false,
"headline": "Add wrapEnableRule to devkit scaffold for ribbon Enable Rules",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-08T13:52:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6c978a59fbc3160960609864d8ce218c72b939cd",
"body": "helpers 0.16.0: typedField(fc, field, kind) for variable field names,\navoiding the F-LMA12-01 kindMap union trap (OE-17 b). test-d proves all\nseven kinds stay exact.\n\ntypegen 0.19.0 + cli 0.10.0: generateFieldKinds is opt-in (default off,\n--field-kinds / config fieldKinds); XxxExpands unchanged (OE-\n[…]\n matches the gate (F12-03),\nAGENT.md updates (F12-02 seven AttrKinds, typedField union trap, FieldKinds\nopt-in, F-MK12-01 wrap* are local). Scaffold pins cli ^0.10.0 / helpers ^0.16.0.\n\nNot published.",
"is_bot": false,
"headline": "Runde 12 fix stack: typedField, FieldKinds opt-in, kindMap gate",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-08T04:30:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a582422cf8660c89f83ab0a137f251909dc34221",
"body": "…re (OE-15)\n\nDataverseHttpClient now runs retry/backoff/rate-limit/timeout through the shared\nResilientRunner from @xrmforge/dataverse-core (new dependency), over a Node\nbearer-token NodeTransport that implements the core DataverseTransport. The\nNode-only concerns the browser-lean runner omits stay \n[…]\nons (Juergen): scope S2 (full migration, not S1), error-wrap E1, 401-recovery\nlocation 401-C (typegen wraps the runner call; core stays browser-lean).\n\ntypegen 0.18.0 (MINOR), cli 0.9.3 (propagation).",
"is_bot": false,
"headline": "typegen: migrate HTTP client + sanitizers onto @xrmforge/dataverse-co…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-06T13:57:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1bcfec8fe8eb260b046b5449c9f1aec6f71d3973",
"body": "…it 0.7.38, cli 0.9.2)\n\nhelpers: add typedFields(fc, kindMap) - the typed, NULLABLE counterpart to typedForm\nfor genuinely cross-entity / cross-form scripts where no single FormTypeInfo fits\n(Option B). The kindMap drives per-field types; every accessor is nullable (honest,\nunlike a per-entity union\n[…]\nlue/setValue layer as the Rule-19 anti-pattern it replaces; scaffold\nhelpers pin ^0.15.0. cli: propagate typegen 0.17.0 + devkit 0.7.38.\n\nAll 4 gates green (build/test/typecheck/lint); monorepo 18/18.",
"is_bot": false,
"headline": "OE-16: cross-entity typedFields (helpers 0.15.0, typegen 0.17.0, devk…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-06T06:48:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "66e3cf13fb198ceae7b6de2d1d4e28e7e8cb8eef",
"body": "…ified)\n\ntypegen 0.16.0 (MINOR): keep standalone EntityName fields (AttributeOf null, e.g. activitytypecode); still exclude lookup companions (owneridtype, regardingobjecttypecode). Verified live against markant-dev. Fix-comment example corrected to the real property name regardingobjecttypecode.\n\nd\n[…]\n0.9.1 (PATCH): propagate typegen 0.16.0 + devkit 0.7.37.\n\nCHANGELOGs: add new entries and backfill the missing 0.15.0/0.7.36/0.9.0 entries (stale since the session-56 publish, npm-publish pitfall 13).",
"is_bot": false,
"headline": "Release typegen 0.16.0, devkit 0.7.37, cli 0.9.1 (F-LMA11-04 live-ver…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-06T04:42:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "44e7d2caaeb899ac5d93d512fb3f05fd4635128f",
"body": "…idate-form 3n)\n\n- F-MK11-01: scaffold.ts pins cli ^0.9.0, testing ^0.8.0 (current minors)\n- F-MK11-02: AGENT.md template polymorphic @odata.bind uses target-qualified XxxExpands (4 spots)\n- validate-form 3n: FetchXML attribute= regex matches double-quote too, [a-z] interpolation guard\n- F-LMA11-04:\n[…]\nCT; CACHE_VERSION 3->4\n- Tests: type-mapping companion/standalone split, entity-generator fixture realistic\n\nLive verification of F-LMA11-04 (activitytypecode AttributeOf null) pending before publish.",
"is_bot": false,
"headline": "Framework fixes from showcase round 11 (F-MK11-01/02, F-LMA11-04, val…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-06T03:54:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0df6ae70a490c1c4a9f15e74b68fdedcf76aafba",
"body": "…ransport\n\nAdd @xrmforge/dataverse-core@0.1.0 (runtime-neutral: OData sanitizers,\nDataverseTransport interface, browser-lean ResilientRunner, error types).\n\nAdd @xrmforge/dataverse-client@0.1.0 (BrowserTransport cookie-fetch verified\nagainst a live org, retrieveAll nextLink paging with a 100-page sa\n[…]\nher with the typegen client runner migration, since delegating\nwould switch the thrown error type from ApiRequestError to DataverseError).\n\nAll gates green per package; monorepo build 9/9, test 18/18.",
"is_bot": false,
"headline": "OE-15 stage 1: dataverse-core + dataverse-client (retrieveAll), FakeT…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-05T22:02:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "151aed714060a11ddc571663423e619340a15fb5",
"body": "Familien-Standard nach Palas-Vorbild (claudecode-ADR-2026-07-04-0943): Füllung aus dem\njüngsten usage-Eintrag des Transcripts, auch nach Compact korrekt. Schwellen 50/70/85,\nFenster via CLAUDE_CONTEXT_WINDOW. Repo-eigener Übergabe-Hinweis ersetzt die toten\nVerweise auf den nur in Markant vorhandenen Skill claude-code-optimierung.",
"is_bot": false,
"headline": "feat(hooks): Kontextlast misst echte usage-Token statt Byte-Heuristik",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-04T07:57:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e7cbd90b3305605beb8abfcc7b9e4e61a6dc0759",
"body": "… Mojibake am Handover-Regex an",
"is_bot": false,
"headline": "fix(hooks): stdin auf UTF-8 rekonfigurieren, Umlaut-Prompts kamen als…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-07-04T07:18:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "32a49969ff93b06e22f7df95a5f6bc30a760335d",
"body": "check-tool-umlaute.py (permissionDecision deny, eingebettete Trigger-Daten, AskUserQuestion inkl. preview plus TaskCreate/TaskUpdate, dazu Typografie-Sperre gegen Halbgeviert-/Geviertstrich und Pfeil) nach .claude/hooks/ ausgerollt und in .claude/settings.json als PreToolUse-Hook (matcher AskUserQuestion|TaskCreate|TaskUpdate) verdrahtet. Zentral aus ~/.claude/hook-templates via Sync-UmlautTriggers.ps1. Bestehende Hooks bleiben unangetastet.\n\nEntscheid: claudecode ADR-2026-06-26-1254.",
"is_bot": false,
"headline": "PreToolUse-Surrogat-Sperre für prosa-tragende Tool-Aufrufe verdrahtet",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-26T11:08:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b006ce193d154eadf3d30a739f70bde018245477",
"body": "…d (F-MK9-08-Sub)\n\nPolymorphic lookups (Customer, custom multi-target) need a target-qualified $expand\nnavigation property per target. The name is case-sensitive and not reliably\nconstructible (ownerid -> owninguser/owningteam, custom lookups carry SchemaName\ncasing), so it is read from OneToManyRel\n[…]\n; metadata-client/EntityTypeInfo mocks updated.\n Verified live against markant-dev (customerid_account/contact; ownerid special case).\n\nBumps: typegen 0.15.0, devkit 0.7.36, cli 0.9.0. Not published.",
"is_bot": false,
"headline": "feat(typegen): generate XxxExpands enum for polymorphic lookup $expan…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-22T06:46:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a43542249f960703a657d8f280e2b65524f1931d",
"body": "…ation (Runde 10)\n\nhelpers README 'What you get' table was stale across several releases, not just this\none: add clearAppNotification, parentXrm/getWebResourceContext (this round) plus the\npreviously-missing expanded/expandedMany, setAndSubmit, formLookupIdUnsafe/Unsafe,\ngetEnvironmentVariable, isUn\n[…]\n MockControl.setContentWindow; list the now-exported\nTrackedAppNotification type (added to index.ts, return type of getGlobalNotifications).\n\ntesting build+typecheck green; type present in dist .d.ts.",
"is_bot": false,
"headline": "docs: bring helpers/testing READMEs current; export TrackedAppNotific…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T21:29:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9f6e5fb74d3694d4f4b30fab584bb791f76f071f",
"body": "… OE-14)\n\nhelpers 0.14.0:\n- clearAppNotification(id): non-breaking counterpart to addAppNotification,\n encapsulates the Xrm.App optional-at-runtime cast (FW-4)\n- parentXrm() + getWebResourceContext(): browser-safe HTML WebResource context\n helpers, replace the window.parent / page-context hand-cas\n[…]\n-4), SchemaName casing read-not-guess (FW-6), WF/system actions have no\n generated executor (FW-7)\n\nAll 4 gates green (build 7/7, test 14/14 incl. K44-01 scaffold-typecheck,\ntypecheck 9/9, lint 7/7).",
"is_bot": false,
"headline": "feat: HTML WebResources first-class + clearAppNotification (Runde 10,…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T21:14:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4bffba7647341f8f8a7a26eeefafa07bfc7228bf",
"body": "…blocks",
"is_bot": false,
"headline": "chore(hooks): umlaut check for all text files; code warns, .md still …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T17:51:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0b437443aafb2f8b10b96981a7afe274498b897b",
"body": "…2, devkit 0.7.34, cli 0.8.20)\n\n- helpers (R46-06): clarify expanded<T> JSDoc - returns null only for an absent/null/array\n nav property; a present object (even {}) is returned as-is. Doc/.d.ts only, no behaviour change.\n- typegen (R46-07): extract a single shared buildAttributeMemberName() in labe\n[…]\ngacy modernization).\n- cli: propagate typegen 0.14.2 + devkit 0.7.34 (no source change).\n\nR46-03/04/05 were already resolved in d7c7ea4 (Session 46); confirmed by reading the tests.\nNot yet published.",
"is_bot": false,
"headline": "fix: R46-02/06/07 doc + refactor batch (helpers 0.13.1, typegen 0.14.…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T10:34:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d7c7ea4cbe76d15d57f1e18d04fe42ae47a2dfa3",
"body": "… (R46-01)\n\n0.14.0 extended the cached EntityTypeInfo (multiSelectPicklistAttributes) and\nnormalized MultiSelect attributes (Virtual -> MultiSelectPicklist) on load, but\nleft the cache manifest version at '1'. With useCache:true an old cache was\naccepted as compatible, so an unchanged-from-cache ent\n[…]\n05 (form-generator collision guard + SchemaName\nfallback + multi-part SchemaName, metadata-client MultiSelect negative case,\nhelpers expanded empty-object). Propagate to cli 0.8.19. All 4 gates green.",
"is_bot": false,
"headline": "fix(typegen): bump CACHE_VERSION to 2 to invalidate pre-0.14.0 caches…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T04:06:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9602d847c59ef083ddc1a4430c3d08ecb485cc80",
"body": "New tests/scaffold-typecheck.test.ts scaffolds a real project into a temp dir,\nsymlinks @xrmforge/helpers and @types/xrm into a temp node_modules offline (no\nnpm install), and runs tsc --noEmit against the unchanged generated tsconfig,\nexpecting exit 0. Catches type errors in shipped templates (error-handler.ts,\nexample-form.ts, shared/*) that the devkit tsc excludes (templates/** is in its\nexclude). Test-only, no version bump; runs in the existing vitest/CI gate.",
"is_bot": false,
"headline": "K44-01: typecheck scaffold templates with a devkit test (Option C)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T03:23:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fc70db084a7437fef42de16052a4974ab7e8c573",
"body": "helpers 0.13.0: expanded<T>(entity, nav): Partial<T> | null (single-valued) and\nexpandedMany<T>(entity, nav): Partial<T>[] (collection-valued) read an expanded\nnavigation property from a Web API response as a typed object/array. Partial<T>\nis honest about a partial $select inside the expand; replace\n[…]\n\ndevkit 0.7.33: scaffold pins helpers ^0.13.0; AGENT.md documents reading expand\nresults via expanded/expandedMany instead of hand-casting. cli 0.8.18 propagation.\nAll 4 gates green; +7 helpers tests.",
"is_bot": false,
"headline": "F-MK9-08: typed $expand readers expanded<T>() / expandedMany<T>()",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T00:46:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6a9219b4a353af57e4bdcfb2b7be46fa5fa57802",
"body": "…solution\n\nFields/NavigationProperties/FormFields enum members now derive from the attribute\nSchemaName instead of the display label, dropping the order-dependent ordinal\nsuffix. Deterministic, stable and guessable (statecode -> StateCode), matching\npac modelbuilder / XrmDefinitelyTyped. Label stays\n[…]\nedicated cast query so the enum is generated\n(F-MK9-09).\n\ntypegen 0.14.0 (MINOR, breaking output), devkit 0.7.32 (AGENT.md naming note),\ncli 0.8.17 (propagation). All 4 gates green; 462 typegen tests.",
"is_bot": false,
"headline": "F-MK9-05/07/09: SchemaName-based Fields enum members + MultiSelect re…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-21T00:40:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cd4992a32326ec71f369a2086c44a27826bc040c",
"body": "helpers: addAppNotification gains an optional autoHideMs that schedules\nXrm.App.clearGlobalNotification after the delay (fire-and-forget), replacing\nhand-built transient-notification helpers (account/opportunity duplicated one).\n+2 tests with fake timers. helpers 0.11.0 -> 0.12.0 (MINOR).\ndevkit scaffold pin helpers ^0.12.0 + AGENT.md note; devkit 0.7.30 -> 0.7.31.\ncli 0.8.15 -> 0.8.16 (workspace:* propagation). All 4 gates green.",
"is_bot": false,
"headline": "F-MK9-10: addAppNotification autoHideMs (self-clearing banner)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-20T22:44:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0939f48676260c01e593934e2c48b353f69b9683",
"body": "…template\n\nDecision Option C (app-level banner error surface). error-handler.ts template:\n- wrapCommand is now generic (wrapCommand<TArgs extends unknown[] = []>) so ribbon\n command handlers declare extra params type-safely instead of ...args: never[]\n (default [] = backward compatible).\n- new wra\n[…]\ny compiling against @types/xrm + helpers\n(templates are excluded from the devkit tsc). devkit 0.7.29 -> 0.7.30 (template-only\nPATCH), cli 0.8.14 -> 0.8.15 (workspace:* propagation). All 4 gates green.",
"is_bot": false,
"headline": "F-MK9-02: typed wrapCommand<TArgs> + new wrapGridCommand in scaffold …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-20T21:14:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "07a799c358c6722fa6dc6a66ac3de94f265304c5",
"body": "… MockControl.refresh (F-MK9-01), AGENT.md NavigationProperties path + 5 pitfalls (F-MK9-04)",
"is_bot": false,
"headline": "Runde 9 framework fixes: tree-shakeable action executors (F-LMA9-01),…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-20T17:12:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f7d36eee5c0a04d43b4eed89d7473f111e06b9eb",
"body": "… multi-form pattern (OE-13)\n\nReplace the \"per-entity union FormTypeInfo (planned)\" note with a clear statement that\nraw Xrm.FormContext + named constants is the deliberate, supported pattern for both\ncross-entity and single-entity-multi-form scripts. The union type was considered and\nrejected (OE-1\n[…]\nccess to fields the active form may not carry -\nthe false compile-time safety the framework exists to prevent.\n\ndevkit 0.7.27 -> 0.7.28 (template-only), cli 0.8.12 -> 0.8.13 (workspace:* propagation).",
"is_bot": false,
"headline": "AGENT.md template: raw FormContext + named constants as the supported…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T17:33:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f9f371f681e335cca6a4dc556e0721a79d35ed0d",
"body": "…8-N3); devkit 0.7.27 + cli 0.8.12\n\nCommitted-not-published (version > npm so the changed AGENT.md content has its own version, no\nsame-version drift). Publish as doc-addendum or bundle into the next release.\n- devkit 0.7.27: AGENT.md template - cross-entity/cross-form script pattern (raw FormContex\n[…]\nr than per-control (F-R8-N3b / F-LMA7-10)\n- cli 0.8.12: propagate devkit 0.7.27 (no cli source change)\nbuild --force 7/7, test 14/14, typecheck 9/9, lint 7/7; dist/templates/AGENT.md content verified.",
"is_bot": false,
"headline": "chore(devkit): AGENT.md cross-form pattern + section-toggle note (F-R…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T15:48:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "09ef77292e23e6c72ee693c6430590401ff61fc2",
"body": "…ld pins + CHANGELOGs (Runde 8)\n\nBundles with the already-committed cli 0.8.11 + eslint-plugin 0.3.2 (Session 41) for one publish block.\n- helpers 0.11.0 (MINOR): setAndSubmit, formLookupId/Unsafe, isUnsavedRecord, getEnvironmentVariable\n- testing 0.5.0 (MINOR): online.execute override + OptionSet/v\n[…]\nit 0.7.26 (PATCH): scaffold pins helpers ^0.11.0 / testing ^0.5.0 (0.x caret) + AGENT.md Runde-8 docs\nbuild --force 7/7, test 14/14, typecheck 9/9, lint 7/7; dist content verified per Stolperfalle 17.",
"is_bot": false,
"headline": "chore(release): helpers 0.11.0, testing 0.5.0, devkit 0.7.26 + scaffo…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T15:21:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "77ba9cf9a6a759a57d9474f71f6e94876b83a745",
"body": "…ntrol(string) pitfall\n\n- Packages line + NEVER block: setAndSubmit (on-form), formLookupIdUnsafe/Unsafe, getEnvironmentVariable, isUnsavedRecord\n- Section 5b: getAttribute/getControl on lookups need the BLANK name (form-level FormFieldsEnum / NavigationProperties), never the entity Fields _value-fo\n[…]\nped $context fails (no string overload); use raw ctx.getFormContext().getControl(name) (F-R8-N5)\n\nScaffold pin bumps (helpers ^0.11.0 / testing ^0.5.0) + version bumps deferred to the bundled release.",
"is_bot": false,
"headline": "docs(devkit/AGENT.md): Runde-8 helpers + F-MK8-05 lookup rule + getCo…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T15:16:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7f009b82f5f3913f091632eaa31e9e184e131951",
"body": "…k methods (Runde 8 gaps)\n\nRemaining mock gaps the .1 testing release did not close (Runde 8):\n- setupXrmMock webApiOverrides.execute / executeMultiple: the default online.execute returns a 204 (no body), making Custom API executors that call response.json() throw. Tests can now inject a JSON Respon\n[…]\naultView (lookup views), setFilterXml/getFilterXml (subgrid, not in @types/xrm).\n- MockAttribute: getOptions/setOptions (OptionSet option list seed).\n\n+6 tests (142 total). build/typecheck/lint green.",
"is_bot": false,
"headline": "feat(testing): online.execute override + OptionSet/view/filterXml moc…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T15:04:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bd8b9dfce65e8a220bd80fe52510eee2535c3008",
"body": "…tEnvironmentVariable (Runde 8 gaps)\n\nGenuine framework gaps surfaced by the Runde 8 showcases (survive the .1 republish):\n- setAndSubmit(attr, value): on-form set + SubmitMode.Always one-liner, type-safe (F-LMA8-N1, the dominant idiom, 200+ call-sites). Explicit opt-in, does not change setValue sem\n[…]\nentVariableCache: cached env-var reader, default fallback, OData-escaped, errors propagate (F-MK8-N4a)\n\n+18 tests (107 total). build/typecheck/lint green. Version bump deferred to the bundled release.",
"is_bot": false,
"headline": "feat(helpers): setAndSubmit, formLookupId/Unsafe, isUnsavedRecord, ge…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T15:00:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f38958755a35ab864e2b373cb2740b37a78d42fc",
"body": "…sion from package.json\n\n- cli README: init --force skips existing files, never overwrites (matched\n to xrmforge init --help). Docs-only patch bump 0.8.10 -> 0.8.11.\n- eslint-plugin: plugin.meta.version now read from package.json at load time\n instead of a hardcoded literal (was stale at 0.3.0). Test asserts against\n package.json so it cannot drift again. Patch bump 0.3.1 -> 0.3.2.\n- Not published (bundle with the next framework release).",
"is_bot": false,
"headline": "Fix README init --force wording (cli) + derive eslint-plugin meta.ver…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T14:46:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "723ea4d28ef8b0187c9ccc51dcc116280f309262",
"body": "Fix the outdated package table and roadmap in README.md/README.de.md: drop\nthe drifting version numbers, move \"xrmforge init\" from Planned to Shipped,\nand remove the fixed test count. Patch-bump all seven packages so the new\nper-package READMEs become visible on npm at the next publish (npm renders\n\n[…]\ni 0.8.10, helpers 0.10.1, webapi 0.1.2, testing 0.4.1,\ndevkit 0.7.25, eslint-plugin 0.3.1. Docs only, no source change; build 7/7\nand test 14/14 green. NOT yet published (interactive publish pending).",
"is_bot": false,
"headline": "Prepare docs release: root README cleanup + patch bumps for all packages",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T10:10:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f0a02ed78ee346ee220d4133b5c83ec44b22de07",
"body": "npm showed no README on any @xrmforge/* package page; the detailed root\nREADME belongs to the private root package and is never published. Add a\ndedicated README per package (cli, typegen, helpers, webapi, testing,\ndevkit, eslint-plugin) with usage, API overview, and cross-links.\n\nVerified via npm pack --dry-run that README.md ships in every tarball\n(npm always includes README regardless of the files field), so no\npackage.json change is needed.",
"is_bot": false,
"headline": "Add per-package READMEs for all seven npm packages",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-19T08:38:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3502ba37840f7cf1bf3e6e0ecb6ef42120e5866e",
"body": "…ion base (Runde 7 Prio 6/7)\n\n- form-mapping.json records per-form `fields` + `isMain` marker, built from structured\n per-form metadata during generation instead of regex over the output (F-MAR7-04)\n- typed form sections extend Xrm.Collection.ItemCollection<Section> so get(index)/get()/\n forEach/g\n[…]\nce) (F-LMA7-11)\n- README EN/DE: reproducible-CLI-version tip (npx caches @latest; pin or use local binary) (F-LMA7-02)\n- bumps: typegen 0.13.0 (MINOR), devkit 0.7.24, cli 0.8.9; per-package CHANGELOGs",
"is_bot": false,
"headline": "feat(typegen): form-mapping fields/isMain + typed-section ItemCollect…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T16:46:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f848e8467f6b9a0825f99fa42f46073bb2bfde09",
"body": "…fication (F-MAR7-03, F-LMA7-07/09)\n\nHoist helpers the showcase sessions hand-rolled per form into @xrmforge/helpers: parseMultiSelect(value, emptyAsNull?) normalizes MultiSelect OptionSet shapes (comma string / number[] / number / null) to number[] (or null), dropping empty parts before Number() (n\n[…]\nNEVER entries against hand-rolled equivalents + @odata.bind note. Scaffold helpers pin ^0.9.0 -> ^0.10.0. Bumps: helpers 0.10.0 (minor), devkit 0.7.23, cli 0.8.8. All 4 gates green (helpers 89 tests).",
"is_bot": false,
"headline": "feat(helpers): parseMultiSelect, clear/setUnsafeAndSubmit, addAppNoti…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T13:03:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e2905e56aefe8ddfb828453d139aca0d1ede8a19",
"body": "Bound MS-standard operations (SynchronizePhoneNumbers, PredictResult) share an exported name across entity action modules, so the barrel's export * from './actions/...' collided with TS2308 on an unfiltered 'generate --actions' run (the --actions-filter workaround only masked it). Actions/functions \n[…]\non clarified (entities + forms via export *; OptionSets/Fields/Actions imported directly, name-collision-safe).\n\nBumps: typegen 0.12.2, devkit 0.7.22, cli 0.8.7. All 4 gates green (typegen 453 tests).",
"is_bot": false,
"headline": "fix(typegen): stop export-star of action modules in barrel (F-LMA7-01)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T12:02:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7fe8ccf62693f05bb21237e1558769de2683ff89",
"body": "createFormMock gains a formType option (seed getFormType, test Create-only paths). MockAttribute gains getText/setText + getPrecision/setPrecision. MockEntity gains addOnSave/removeOnSave + FormMock.fireOnSave(saveMode). setupXrmMock exposes userSettings.roles as a real ItemCollection (get/forEach/g\n[…]\nst.\n\nAGENT.md template testing section documents the new helpers. Scaffold testing pin ^0.3.0 -> ^0.4.0.\n\nBumps: testing 0.4.0 (minor), devkit 0.7.21, cli 0.8.6. All 4 gates green (testing 136 tests).",
"is_bot": false,
"headline": "feat(testing): close complex-form mock gaps (F-MAR7-02)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T11:42:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bd6ae8f91a7e3fcb068fe2a85027e5061a0e509c",
"body": "…MAR7-01)\n\nA void action executor (createBoundAction/createUnboundAction without a TResult type arg) was typed Promise<Response> but at runtime returned response.json() (200) or the raw Response (204), while execute() already throws on non-2xx. Following the type with if (!resp.ok) crashed at runtim\n[…]\n case; matching NEVER entry, subagent-handoff note, corrected before/after example. Scaffold helpers pin ^0.8.0 -> ^0.9.0.\n\nBumps: helpers 0.9.0 (minor, type-level breaking), devkit 0.7.20, cli 0.8.5.",
"is_bot": false,
"headline": "fix(helpers): void Custom API executors return void, not Response (F-…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T11:13:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4e6d4347fb860693a2908fdf8648367569b02052",
"body": "…7-06)\n\n$unsafe(Lookup) takes an attribute logical name -> use XxxNavigationProperties\n(blank), not XxxFields (_value-form, resolves to null at runtime). Non-lookup\noff-form fields still use XxxFields. Doc-only: a static gate cannot distinguish\nlookup from non-lookup at the $unsafe call site without false positives. Part of\nthe unpublished devkit 0.7.19 / cli 0.8.4.",
"is_bot": false,
"headline": "docs(devkit): cover $unsafe on off-form lookups in AGENT.md 5b (F-LMA…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T06:20:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "23d321d8de9d7f4edca155ce65a977dd07813243",
"body": "AGENT.md section 5b: the XxxFields lookup enum is already _value-form (use in\n$select/$filter), XxxNavigationProperties is blank (use for parseLookup/$expand/\n@odata.bind). Double-wrapping _${XxxFields.X}_value or passing a Fields value to\nparseLookup compiles green but breaks at runtime (OData 400 \n[…]\ncaffold.test.ts asserts the new section ships.\n\ndevkit 0.7.18 -> 0.7.19 (template-only), cli 0.8.3 -> 0.8.4 (propagation, pulls\ndevkit 0.7.19 via workspace:*, no cli source change). All 4 gates green.",
"is_bot": false,
"headline": "feat(devkit): scaffold lookup convention guidance + gate (F-LMA7-05)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-18T06:18:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c75dc12ab1a5a8a1accb29837023f1da055e18b4",
"body": "GridControl.setFilterXml is missing from the typings (cast the control), and\nXrm.App global-notification `level` is an XrmEnum (not available at runtime;\npass the numeric value). Both hit in the markant showcase run. Folded into the\nunpublished devkit 0.7.18 entry.",
"is_bot": false,
"headline": "Add two @types/xrm gaps to AGENT.md pitfalls list (Runde-6 follow-on)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-17T10:03:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "44df3e319b906078fcb134c07b7e63fb5ad6bd15",
"body": "K32-06 follow-on: withProgress no longer opens its own error dialog (the\nhandler wrapper wrapHandler/wrapCommand owns the single error UI). Updated\nthe README usage comments and the \"Progress Indicator\" section in both\nlanguage versions accordingly.",
"is_bot": false,
"headline": "Fix stale withProgress error-dialog claim in README (EN+DE)",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-17T10:01:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c24606e9c24d6cd66910b431bd334312237e36b2",
"body": "- typegen [0.12.1]: escape apostrophes in emitted FormXML names (new\n generators/string-escape.ts; section/tab names, subgrid/quickview ids).\n A section named \"note's information\" no longer breaks the generated TS.\n- helpers [0.8.0]: add isFormType(ctx, FormType) (TS2367-safe form-type\n equality)\n[…]\nard uses isFormType; scaffold pins\n helpers ^0.8.0 / testing ^0.3.0.\n- cli [0.8.3]: init next-steps print --output ./generated.\n\nAll gates green (build 7/7, test 14 tasks, lint 7/7). Publish pending.",
"is_bot": false,
"headline": "Fix Runde-6 framework findings K32-02 to K32-07",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-17T08:40:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2896c94e55942951b850743f96e7cf7799bccdfe",
"body": "…32-01)\n\nThe AGENT.md scaffold template now teaches callCloudFlow (helpers 0.7.0) as the canonical way to call a Power Automate cloud flow (HTTP-request trigger) from a form script: helpers package blurb, a NEVER rule against hand-rolled fetch/XMLHttpRequest for flow calls, a 'Cloud Flow Call' befor\n[…]\ncklog C, found in the Session 32 audit. devkit 0.7.16 -> 0.7.17 (template-only PATCH), cli 0.8.1 -> 0.8.2 (propagation, pulls devkit 0.7.17 via workspace:*). All 4 gates green, dist template verified.",
"is_bot": false,
"headline": "feat(devkit): document callCloudFlow in AGENT.md scaffold template (K…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-16T11:13:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "224127053fee06a58cf7de8014fc3900a05ad45a",
"body": "…CloudFlow)\n\nA 0.x caret never crosses the 0.6/0.7 boundary, so fresh init projects pulled helpers 0.6.x without callCloudFlow. Bumps: devkit 0.7.15 -> 0.7.16 (scaffold pin), cli 0.8.0 -> 0.8.1 (propagation so npx xrmforge init ships the new devkit).",
"is_bot": false,
"headline": "chore(devkit): bump scaffold helpers pin ^0.6.1 -> ^0.7.0 (reach call…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-16T10:39:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8701023ec4fa6e0977be18f0598c838a714882cb",
"body": "…r calls (Backlog C)\n\nBrowser-safe callCloudFlow<TReq, TRes>(triggerUrl, body?, options?): POSTs the body as JSON, returns parsed JSON / raw text / undefined (204), throws on non-2xx with status + body. Covers the direct HTTP-trigger case (Custom API / proxied flows stay with createUnboundAction). Trigger URL (SAS) is a parameter, never hard-coded; compose with withProgress. Zero Node deps.\n\n7 fetch-mocked tests. Bump: helpers 0.6.3 -> 0.7.0 (minor).",
"is_bot": false,
"headline": "feat(helpers): add callCloudFlow for typed Power Automate HTTP-trigge…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-16T10:25:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e4ba546c82b3bd28f890b10b3db15b5334cef737",
"body": "…ufe 2)\n\ngenerate now auto-loads a local ./.env (via dotenv, without overriding real env vars) and, in an interactive terminal, prompts for any still-missing connection/credential value (hidden secret input). Full precedence per value: CLI flag > env var > ./.env > xrmforge.config.json > interactive\n[…]\nt scaffold .gitignore now ignores .env/.env.local; scaffold cli pin ^0.7.0 -> ^0.8.0.\n\nNew cli dependency: dotenv (zero-dependency). Bumps: cli 0.7.0 -> 0.8.0 (minor), devkit 0.7.14 -> 0.7.15 (patch).",
"is_bot": false,
"headline": "feat(cli): auto-load .env and interactive credential prompt (OE-12 St…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-16T09:47:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bb5098913d72f41bbec62ca84f14c7034921bedb",
"body": "…E-12 Stufe 1)\n\ngenerate now reads XRMFORGE_URL/TENANT_ID/CLIENT_ID/CLIENT_SECRET from the environment (XRMFORGE_TOKEN already supported). Precedence per value: CLI flag > env var > xrmforge.config.json. Fixes K30-05 (the CLI advised XRMFORGE_CLIENT_SECRET but never read it). buildAuthConfig is now \n[…]\nv block, so the secret never reaches the runner's process list; scaffold cli pin ^0.6.0 -> ^0.7.0 (env reading needs cli >= 0.7.0).\n\nBumps: cli 0.6.2 -> 0.7.0 (minor), devkit 0.7.13 -> 0.7.14 (patch).",
"is_bot": false,
"headline": "feat(cli): resolve connection/credentials from XRMFORGE_* env vars (O…",
"author_name": "Jürgen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-16T07:57:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "dcc323dcd9780bfadc6aa498a801eaed1b9a401b",
"body": "…erschien nie)\n\nDer PostToolUse-Hook gab hookSpecificOutput ohne hookEventName aus; Claude Code\nverwarf den additionalContext daher still. Aus dem zentralen Template gesynct,\nauf macOS live verifiziert.",
"is_bot": false,
"headline": "check-umlaute.py: hookEventName PostToolUse ergänzen (Schreibwarnung …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-15T05:24:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "55ae911866a7a51988c6c5a6595a45a71ef29640",
"body": "…GELOG\n\nThe manual publishes left several per-package CHANGELOGs stale (only the workspace\nchangelog tracked them). Reconstruct from the workspace changelogs and git history:\n- helpers: 0.6.2, 0.6.3\n- typegen: 0.10.2 (git-only), 0.11.0, 0.11.1, 0.12.0\n- cli: 0.4.21 (git-only), 0.5.0, 0.5.1, 0.5.2 (git-only), 0.6.0, 0.6.1, 0.6.2\n- eslint-plugin: new CHANGELOG (0.1.0 through 0.3.0)\n\ngit-only interims are marked as such. Docs only, not in the npm tarballs\n(files: [\"dist\"]), no version bump.",
"is_bot": false,
"headline": "docs: backfill helpers/typegen/cli CHANGELOGs, add eslint-plugin CHAN…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T06:19:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7aeb90eff37c6ae499a8e5dcc37d936e08e33276",
"body": "The manual publishes since 0.7.7 did not update the per-package CHANGELOG\n(only the workspace changelog tracked them). Reconstruct entries 0.7.8 through\n0.7.13 from the workspace changelogs, each with its finding reference. 0.7.8 is\nmarked git-only (never published, folded into 0.7.9). Docs only, not in the npm\ntarball (files: [\"dist\"]), no version bump.",
"is_bot": false,
"headline": "docs: backfill devkit CHANGELOG 0.7.8-0.7.13",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T06:07:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a0639b08fdc814fc6fa43da7fdf5c4aa8065eef3",
"body": "The typedForm API exposes controls.fieldName (a getControl proxy), not\n$control(name). $control was replaced by the controls proxy (helpers 0.5.0,\nfinding K25-03); a form.$control(...) call throws at runtime. Align the\nGET-trap description in docs/architecture/13-helpers.md (EN) and\ndocs/architektur/13-helpers.md (DE). Docs only, no version bump.",
"is_bot": false,
"headline": "docs: correct typedForm GET-trap to controls.fieldName",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T05:55:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ea6217b34b270dce1b451e9b14896154b85a42af",
"body": "cli pulls @xrmforge/devkit and @xrmforge/typegen via workspace:*. Republishing\ncli freezes the new devkit 0.7.13 (gate consolidation, F28-01 AGENT.md, K29-01\nexample-form template, CI validate step) and typegen 0.12.0 into the versions\nthat `npx xrmforge init` installs. No cli source change.",
"is_bot": false,
"headline": "Bump cli 0.6.1 -> 0.6.2 to propagate devkit 0.7.13",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T01:19:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2b81c7fada1d16cb01d44b6b12260d4212fcce98",
"body": "Both scaffolded CI templates (GitHub Actions, Azure Pipelines) ran\ntsc + vitest + build but neither eslint nor validate-form.mjs, so the lint\nand pattern-compliance gates only ran locally, never in a scaffolded project's\nCI. Replaced the standalone tsc step with `npm run validate`, which runs\ntsc + \n[…]\n 28 consolidation) - no redundant tsc run.\n\nscaffold.test.ts now asserts the GitHub template contains 'npm run validate'.\nGoes into devkit 0.7.13 (not yet published). All 4 gates green, dist verified.",
"is_bot": false,
"headline": "Run validate (lint + pattern gates) in scaffold CI templates",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T01:06:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "73028d7d4d09342defb15e70424ebe3d34251cbb",
"body": "Five `weiss`, one `schliesst`, one `Schliessen` and one `fuer` in German\ncode-block comments and a test description string used ASCII surrogates\ninstead of real umlauts. They sit inside typescript code fences, which the\numlaut commit hook skips by design, so they were not auto-caught. Focused\ncleanup, no functional change.",
"is_bot": false,
"headline": "Fix remaining ASCII surrogates in README.de.md code-block comments",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T00:52:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "acf7f447b13b58d5e75691678c381d1a6db5baf2",
"body": "…TypeInfo>\n\nSession 28's F28-01 fix corrected AGENT.md, helpers @example and the\ntypes-xrm-extension skill, but missed two derived artifacts that still showed\nthe fragile bare-interface pattern:\n\n- devkit scaffold template example-form.ts: the TODO taught\n typedForm<ExampleForm> (bare interface -> \n[…]\n in\nREADME.de.md, flagged by the umlaut hook.\n\nNo version bump: devkit 0.7.13 is not yet published (the dist template is\nrebuilt before publish), READMEs are not in the npm tarball. All 4 gates green.",
"is_bot": false,
"headline": "Fix F28-01 remnants: example-form template + README use typedForm<...…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-14T00:38:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ae942337fe612e9fc0b670785fcefee5ffce2246",
"body": "AGENT.md and the typedForm @example documented typedForm<FormInterface>, the fragile\npattern: ExtractFields falls back to overload inference that resolves to `never` across\npackage boundaries (typedForm-TS59). The reliable pattern is typedForm<FormTypeInfo> (the\ngenerated TypeInfo bundles the field/\n[…]\n 0.6.3 (@example JSDoc change)\n\nAGENT.md ships in devkit 0.7.13 (already bumped). All gates green. Publish pending\n(interactive): devkit 0.7.13 + helpers 0.6.3 + a cli bump to propagate the templates.",
"is_bot": false,
"headline": "Fix F28-01: AGENT.md + helpers @example use typedForm<FormTypeInfo>",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T23:45:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4c42cf4be54c6e94caa44a2cdfe9b7245e9ff888",
"body": "The checked-in example used the obsolete declare-namespace/.d.ts output and\ngetAttribute chains. Bring it to the current pattern (K22-04).\n\n- generate-from-fixture.ts: drop the obsolete namespace/namespacePrefix generator\n options (only labelConfig remains), write .ts instead of .d.ts, emit a flat \n[…]\n (examples is not a package).\n\nNote: surfaced that AGENT.md documents typedForm<FormInterface>, which fails type\nextraction across package boundaries (use typedForm<FormTypeInfo>). Tracked separately.",
"is_bot": false,
"headline": "Modernize examples/account-form-demo to flat ESM + typedForm",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T23:32:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c22525a6bbecbc36f99ba925bdc5f08e584aa065",
"body": "self-check.sh was orphaned: no package.json script, not referenced by AGENT.md,\nnot run in CI. validate-form.mjs is a superset of its pattern checks plus tsc and\neslint, and runs cross-platform (node, not bash). Retire self-check.sh after porting\nits three unique checks so no coverage is lost.\n\n- va\n[…]\n8 -> 17\n- delete the self-check.sh template (dist follows via copy-templates)\n- devkit 0.7.12 -> 0.7.13\n\nAll four gates green; dist verified (self-check.sh gone, validate-form.mjs has the new checks).",
"is_bot": false,
"headline": "Consolidate scaffold quality gates: validate-form.mjs as single source",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T23:03:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0756d0a0f839ecd64d3a2253af60c01c4052626c",
"body": "PERSIST_PATH_RE von den Markant-Defaults (skills, architekturen, memory) auf\ndocs, skills, memory umgestellt, damit der Recherche-Block-Zähler nach einem\nWissens-Write in den docs/-Baum korrekt zurücksetzt.",
"is_bot": false,
"headline": "Wissens-Persistenz-Hook: Pfad-Tokens an die Doku-Struktur anpassen",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T22:39:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1271544a3cc16ab30df92ef179b3067e871a5300",
"body": "…sistenz\n\n- Umlaut-Kette in .githooks (commit-msg, pre-commit, umlaut_check_lib.py) und\n PostToolUse-Schreibwarnung check-umlaute.py, ausgerollt aus der zentralen\n Trigger-Liste.\n- UserPromptSubmit check-kontextlast.py: Warnung bei 40/60/75 Prozent Kontextfüllung.\n- UserPromptSubmit check-wissens-persistenz.py: Erinnerung, Wissen wegzuschreiben.\n- SessionStart/-End Git-Sync und core.hooksPath-Selbstaktivierung.",
"is_bot": false,
"headline": "Claude-Code-Hooks einrichten: Umlaut-Schutz, Kontextlast, Wissens-Per…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T17:41:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1c3737bb34bf1d20ebad5a8c96a177ae24725e98",
"body": "K23-01 cleanup: generators emit flat ES modules (.ts), but several JSDoc/header comments still said .d.ts. Corrected in entity-generator, action-generator (module header + section + combine note), orchestrator, orchestrator/types, file-writer. Comment-only, no API/behavior/output change, no version bump. All 4 gates green.",
"is_bot": false,
"headline": "docs(typegen): correct stale .d.ts comments to flat ESM (.ts)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T17:06:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "25acc6b805b4bfa25bdcce6f46328279ace768ae",
"body": "…control refs (K25-03), republish helpers JSDoc\n\ndevkit 0.7.11->0.7.12: scaffold cli pin ^0.5.0->^0.6.0 (0.x caret never resolves 0.6.0); example-form template comment controls proxy. helpers 0.6.1->0.6.2: republish typed-form JSDoc fix (ed49a2e) + test comment/name controls. cli 0.6.0->0.6.1: pull devkit 0.7.12 + typegen 0.12.0 via workspace:*.",
"is_bot": false,
"headline": "fix(devkit,helpers): bump cli scaffold pin to ^0.6.0 (K26-01), drop $…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T14:39:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ed49a2e11414d4bfa19424313845fe69169acb03",
"body": null,
"is_bot": false,
"headline": "docs(helpers): correct typed-form JSDoc (\\ -> controls proxy)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T13:59:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1a29aa4a681853f3afc0c0e420c6c21a3d48c808",
"body": "Per review: inactive forms should get no interface regardless of type. The\nactivation filter now sits outside the type group:\n (type eq 2 or type eq 7) and formactivationstate eq 1\nso it applies to Main forms as well, not just Quick Create. Consistent and\ncorrect (inactive Main forms are leftovers no app surfaces). Part of the\nunpublished typegen 0.12.0.",
"is_bot": false,
"headline": "refactor(typegen): apply formactivationstate filter to Main forms too",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T13:34:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8f9a6d57ec38dd47739256053a850c24072d4e74",
"body": "Quick Create forms (systemform type=7) previously had no generated interface.\ntypegen now fetches and generates them, data-driven (no opt-in flag):\n\n- metadata: SystemFormMetadata/ParsedForm carry the form type; getMainForms ->\n getForms fetches Main (type 2) plus ACTIVE Quick Create (type 7 and\n \n[…]\ne duplicate disambiguation.\n- tests: getForms (type carried through, QC included, query filter), QC naming +\n disambiguation. typegen 441 -> 445 tests.\n\ntypegen 0.11.1 -> 0.12.0 (minor, new feature).",
"is_bot": false,
"headline": "feat(typegen): generate active Quick Create forms (type 7)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T13:30:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8a117b08e05daa6691a2ccbbd4ea4e0753f490ad",
"body": "…LMA-02)\n\n- config.ts: add actions/actionsFilter to XrmForgeConfig and mergeWithCliOptions\n (CLI takes precedence). Custom API scope is now check-in-able so `generate`/\n `--check` reproduce without reconstructed CLI options.\n- generate.ts: drop the Commander default `false` on --actions so a confi\n[…]\naults to false, CLI-only behavior unchanged).\n- new config.test.ts: 6 unit tests for mergeWithCliOptions (actions/actionsFilter\n precedence + regression). cli 0.5.x -> 0.6.0 (additive config fields).",
"is_bot": false,
"headline": "feat(cli): read actions/actionsFilter from xrmforge.config.json (F23-…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T13:08:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "91000293b1e88807dd02e1acb6eb6813e64ed1bb",
"body": "…self-check.sh\n\n- eslint-plugin 0.3.0: new AST rules no-raw-field-strings, no-raw-entity-names,\n no-raw-select (in recommended as error). 16 new RuleTester cases (53 total).\n- devkit 0.7.11: CI templates (github-actions/azure-pipelines) drop the\n non-existent `--from-config` flag and use explicit \n[…]\n pin ^0.2.1 -> ^0.3.0.\n- cli 0.5.2: pulls devkit 0.7.11 via workspace:* so `xrmforge init` ships the\n fixed templates.\n\nAlso bundles the Session 24 devkit template fixes (K24-01/K23-02) for release.",
"is_bot": false,
"headline": "feat(eslint-plugin): add no-raw rules; fix scaffold CI templates and …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T12:49:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "449265af9b8cd80f54c2f279a9630ddcbc2ecc1a",
"body": "K24-01: AGENT.md withProgress example used a non-existent signature\nwithProgress(<Promise>, {title}); corrected to withProgress(message, () => op)\nmatching helpers/action-runtime.ts (now also pickLang-compliant).\nK23-02: example-form.test.ts scaffold template showed an outdated createFormMock\nexampl\n[…]\ntest files), typecheck 9/9, lint 7/7. No version bump: comment/dead-code\nchanges are internal; the devkit template fixes (AGENT.md, example-form.test.ts)\nride the next release before showcase round 6.",
"is_bot": false,
"headline": "Doc/comment drift cleanup + remove dead typegen runtime duplicates",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T11:07:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a734331ed2253321f8eb2fd204549e591b512a0f",
"body": "checkGeneratedFile and the write-skip comparison now normalize line endings\nbefore the byte comparison. On Windows with git core.autocrlf=true and no\n.gitattributes, generated files are checked out as CRLF while typegen writes\nLF, which made --check report every file as changed (false drift, exit 2)\n[…]\n generated/** (and\n*.ts/*.mjs/*.json) to eol=lf for clean diffs. README --check section (EN+DE)\nupdated to note that line endings are no longer drift.\n\nBumps: typegen 0.11.1, devkit 0.7.10, cli 0.5.1.",
"is_bot": false,
"headline": "fix(typegen): make generate --check line-ending insensitive (CRLF/LF)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-13T08:47:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e56aeebf030c0ae48b7eb987cde2d6f8a722853d",
"body": "…in the minor)",
"is_bot": false,
"headline": "fix(devkit): scaffold cli pin follows cli 0.5.0 (0.x caret stays with…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-12T08:08:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0b46302e48e22026f731ebb3618b318a618b3bec",
"body": null,
"is_bot": false,
"headline": "chore: release typegen 0.11.0, devkit 0.7.9, cli 0.5.0",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-12T08:08:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "42cf5b8259b52c0d58a4a7544d290fbec75ac72a",
"body": "xrmforge generate --check runs the full generation in-memory and compares the result byte-by-byte against the output directory without any write access (no output files, no cache reads or updates). Findings are reported per category (Entities, Fields, Forms, OptionSets, Actions) with three drift cla\n[…]\n On fetch failures or abort no check result is produced (error, not drift). Docs: README flag table + drift detection section (EN/DE), AGENT.md drift check section. Closes OE-11 (Option B, Release 2).",
"is_bot": false,
"headline": "feat: drift check mode for generate (--check, exit 0/1/2)",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-12T08:08:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "313e6e6c23ebe5e08c767541219b608af3c0cbb7",
"body": null,
"is_bot": false,
"headline": "chore: release typegen 0.10.2, devkit 0.7.8, cli 0.4.21",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-12T07:59:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "762c7266aaead932e35df044d40182e6040ff5e5",
"body": "…sion pins\n\nexample-form.ts and example-form.test.ts imported symbols only used in commented examples, so freshly scaffolded projects (and this repo's lint) failed no-unused-vars. The scaffolded package.json pinned helpers ^0.3.0 and cli ^0.4.11; 0.x caret ranges only allow the same minor, so new projects installed outdated helpers without typedForm fixes, controls proxy, and auto-submit. Pins updated to current minors.",
"is_bot": false,
"headline": "fix(devkit): scaffold template lint errors and outdated @xrmforge ver…",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-12T07:59:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9efe86a6c7a752bf8c96a8e98d436e60c4e10cc4",
"body": "…response properties\n\nOData returns customapi rows in server order (no orderby), so parameter order in generated action modules followed createdon and shifted whenever parameters were recreated. getCustomApis() now sorts APIs, request parameters, and response properties alphabetically by uniquename \n[…]\nput for all generators. Note: the first generate run after this release produces a one-time reordering diff in consumer projects.\n\nPrerequisite for drift detection (generate --check, OE-11 Release 1).",
"is_bot": false,
"headline": "fix(typegen): deterministic ordering of Custom APIs, parameters, and …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-06-12T07:58:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c40b3edaacd3dd22bea585d13b175555b21c99e0",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: release helpers 0.6.1, devkit 0.7.7, cli 0.4.20",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-04-09T18:48:37Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b831f400dcaa8cb0a06bd65f62bb74d16981c655",
"body": "…at runtime)\n\nesbuild does not resolve const enums from .d.ts files. XrmEnum.FormType\nfrom @types/xrm is a const enum that only exists at compile time. Using\nit in code causes \"XrmEnum is not defined\" at runtime in D365.\n\nAdded FormType enum to @xrmforge/helpers with same values (Undefined=0,\nCreate=1, Update=2, ReadOnly=3, Disabled=4, BulkEdit=6).\n\nAGENT.md: NEVER use XrmEnum.FormType, use FormType from @xrmforge/helpers.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: FormType const enum in helpers (XrmEnum.FormType does NOT exist …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-04-09T18:48:25Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c95daa9dfbe89885602c8074fb76cd0a02a1d27a",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: release helpers 0.6.0, typegen 0.10.1, cli 0.4.19",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-04-09T17:22:21Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "3d70b0a69aaf8a138b4e419877c8319c92dd6095",
"body": "…setSubmitMode)\n\ntypedForm proxy now wraps every attribute with a Proxy that intercepts\nsetValue() and automatically calls setSubmitMode('always') afterwards.\n\nD365 AutoSave only submits \"dirty\" fields. Programmatically set values\nvia setValue() are NOT marked dirty by default, causing silent data l\n[…]\ndeveloper: form.name.setValue('X') handles everything.\nNo more paired setValue/setSubmitMode calls. No more data loss on AutoSave.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(helpers): typedForm auto-submits on setValue (no more forgotten …",
"author_name": "Juergen Beck",
"author_login": "juergenbeck",
"committed_at": "2026-04-09T17:21:15Z",
"body_truncated": true,
"is_coding_agent": true
}
],
"releases_count": 0,
"commits_last_year": 250,
"latest_release_at": null,
"latest_release_tag": null,
"releases_from_tags": false,
"days_since_last_push": 3,
"active_weeks_last_year": 10,
"days_since_latest_release": null,
"mean_days_between_releases": null
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": false,
"has_contributing": true,
"health_percentage": 57,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": true
},
"ecosystem": {
"packages": [
{
"name": "@xrmforge/cli",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"typescript",
"xrm",
"dataverse",
"cli",
"code-generation"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/cli",
"is_deprecated": false,
"latest_version": "0.10.8",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 60,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 2339,
"first_published_at": "2026-04-01T06:12:21.279000Z",
"latest_published_at": "2026-07-21T19:48:22.263000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 8
},
{
"name": "@xrmforge/devkit",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"typescript",
"xrm",
"dataverse",
"esbuild",
"web-resources",
"iife"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/devkit",
"is_deprecated": false,
"latest_version": "0.10.2",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 57,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 2285,
"first_published_at": "2026-04-03T19:17:34.264000Z",
"latest_published_at": "2026-07-21T19:48:22.406000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 8
},
{
"name": "@xrmforge/webapi",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"typescript",
"xrm",
"webapi",
"dataverse",
"odata",
"query-builder"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/webapi",
"is_deprecated": false,
"latest_version": "0.1.2",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 3,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 30,
"first_published_at": "2026-04-02T20:27:15.419000Z",
"latest_published_at": "2026-06-19T13:16:06.614000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 41
},
{
"name": "@xrmforge/helpers",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"typescript",
"xrm",
"dataverse",
"web-resources",
"helpers"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/helpers",
"is_deprecated": false,
"latest_version": "0.17.0",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 27,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 831,
"first_published_at": "2026-04-04T13:56:34.024000Z",
"latest_published_at": "2026-07-19T01:17:24.475000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 11
},
{
"name": "@xrmforge/testing",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"typescript",
"xrm",
"testing",
"mock",
"form-scripts",
"dataverse"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/testing",
"is_deprecated": false,
"latest_version": "0.8.0",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 14,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 399,
"first_published_at": "2026-04-02T10:50:03.103000Z",
"latest_published_at": "2026-07-05T22:49:16.962000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 24
},
{
"name": "@xrmforge/typegen",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"typescript",
"xrm",
"dataverse",
"type-generator",
"declaration-files"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/typegen",
"is_deprecated": false,
"latest_version": "0.20.0",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 37,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 1284,
"first_published_at": "2026-04-01T06:09:41.478000Z",
"latest_published_at": "2026-07-19T01:17:24.830000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 11
},
{
"name": "@xrmforge/eslint-plugin",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"eslint",
"eslint-plugin",
"xrm",
"dataverse",
"form-scripting"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/eslint-plugin",
"is_deprecated": false,
"latest_version": "0.3.2",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 6,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 132,
"first_published_at": "2026-04-03T20:49:08.757000Z",
"latest_published_at": "2026-06-19T15:27:52.823000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 40
},
{
"name": "@xrmforge/dataverse-core",
"exists": true,
"license": "MIT",
"keywords": [
"dynamics-365",
"dataverse",
"odata",
"web-api",
"typescript",
"fetch"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@xrmforge/dataverse-core",
"is_deprecated": false,
"latest_version": "0.1.0",
"repository_url": "https://github.com/juergenbeck/XrmForge",
"versions_count": 1,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 192,
"first_published_at": "2026-07-05T22:49:05.132000Z",
"latest_published_at": "2026-07-05T22:49:05.428000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 24
}
]
},
"popularity": {
"forks": 0,
"stars": 1,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": null,
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"examples"
],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"examples/account-form-demo/tsconfig.json",
"packages/cli/tsconfig.json",
"packages/dataverse-client/tsconfig.json",
"packages/dataverse-core/tsconfig.json",
"packages/devkit/tsconfig.json",
"packages/eslint-plugin/tsconfig.json",
"packages/helpers/tsconfig.json",
"packages/testing/tsconfig.json",
"packages/typegen/tsconfig.json",
"packages/webapi/tsconfig.json"
],
"toolchain_manifests": [],
"largest_source_bytes": 38309,
"source_files_sampled": 197,
"oversized_source_files": 0,
"agent_instruction_files": [
"CLAUDE.md",
"packages/devkit/src/scaffold/templates/AGENT.md"
],
"agent_instruction_max_bytes": 66013
},
"dependencies": {
"manifests": [
"package.json"
],
"advisories": {
"error": null,
"scope": "published_package",
"source": "osv",
"findings": [],
"collected": true,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 82,
"malicious_count": 0,
"assessed_package": "npm:@xrmforge/cli@0.10.8",
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"npm"
],
"dependencies": [
{
"name": "@xrmforge/devkit",
"manifest": "packages/cli/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:*"
},
{
"name": "@xrmforge/typegen",
"manifest": "packages/cli/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:*"
},
{
"name": "commander",
"manifest": "packages/cli/package.json",
"ecosystem": "npm",
"version_constraint": "^13.0.0"
},
{
"name": "dotenv",
"manifest": "packages/cli/package.json",
"ecosystem": "npm",
"version_constraint": "^17.4.2"
},
{
"name": "@xrmforge/dataverse-core",
"manifest": "packages/dataverse-client/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:*"
},
{
"name": "esbuild",
"manifest": "packages/devkit/package.json",
"ecosystem": "npm",
"version_constraint": "^0.25.0"
},
{
"name": "@azure/identity",
"manifest": "packages/typegen/package.json",
"ecosystem": "npm",
"version_constraint": "^4.6.0"
},
{
"name": "@xrmforge/dataverse-core",
"manifest": "packages/typegen/package.json",
"ecosystem": "npm",
"version_constraint": "workspace:*"
},
{
"name": "fast-xml-parser",
"manifest": "packages/typegen/package.json",
"ecosystem": "npm",
"version_constraint": "^5.5.9"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 0,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "juergenbeck",
"commits": 250,
"avatar_url": "https://avatars.githubusercontent.com/u/19701813?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [
"eslint.config.js",
"eslint.config.mjs"
],
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"pnpm-lock.yaml"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 0,
"reason": "project has 0 contributing companies or organizations -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": null,
"reason": "packaging workflow not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "20 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "e3fa8e976cd9e049c9ad2f3e3292e4ab55518306",
"ran_at": "2026-07-30T13:47:40Z",
"aggregate_score": 3.1,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-27T00:21:42Z",
"oldest_open_prs": [],
"last_merged_pr_at": null,
"ci_last_conclusion": "SKIPPED",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/juergenbeck/XrmForge",
"host": "github.com",
"name": "XrmForge",
"owner": "juergenbeck"
},
"metrics": {
"overall": {
"key": "overall",
"band": "at_risk",
"name": "Overall health",
"note": null,
"notes": [],
"value": 46,
"inputs": {
"security": 45,
"vitality": 43,
"community": 44,
"governance": 32,
"engineering": 70
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "at_risk",
"name": "Vitality",
"value": 43,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 71,
"inputs": {
"commits_last_year": 250,
"human_commit_share": 1,
"days_since_last_push": 3,
"active_weeks_last_year": 10
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 3 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 3
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "10/52 weeks with commits",
"points": 6.9,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 10
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "250 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 250
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "critical",
"name": "Release discipline",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 1,
"inputs": {
"releases_count": 0
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "no releases published",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_releases_published",
"params": {}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "no releases",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_releases",
"params": {}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "no releases",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_releases",
"params": {}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "at_risk",
"name": "Community & Adoption",
"value": 44,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 1,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "1 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 1
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "good",
"name": "Community health",
"note": null,
"notes": [],
"value": 77,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": true,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 18,
"status": "met",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 6.3,
"status": "met",
"details": [],
"max_points": 6.3
}
]
},
{
"key": "ecosystem_adoption",
"band": "moderate",
"name": "Ecosystem adoption (downloads)",
"note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"registry_dependents"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 65,
"inputs": {
"packages": [
"@xrmforge/cli",
"@xrmforge/devkit",
"@xrmforge/webapi",
"@xrmforge/helpers",
"@xrmforge/testing",
"@xrmforge/typegen",
"@xrmforge/eslint-plugin",
"@xrmforge/dataverse-core"
],
"dependents": null,
"ecosystems": "npm",
"total_downloads": null,
"monthly_downloads": 7492
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "7,492 downloads/month across npm",
"points": 51.7,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 7492,
"ecosystems": "npm"
}
}
],
"max_points": 80
},
{
"key": "registry_dependents",
"name": "Registry dependents",
"detail": "not reported by this ecosystem",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_reported_by_this_ecosystem",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "at_risk",
"name": "Sustainability & Governance",
"value": 32,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 10,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "critical",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution",
"pr_acceptance"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 1,
"inputs": {
"merged_prs": 0,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "no decided pull requests or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_decided_prs_or_data",
"params": {}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "at_risk",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 33,
"inputs": {
"followers": 0,
"owner_type": "User",
"is_verified": null,
"owner_login": "juergenbeck",
"public_repos": 3,
"account_age_days": 3710
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "0 followers of juergenbeck",
"points": 0,
"status": "missed",
"details": [
{
"code": "owner_followers",
"params": {
"count": 0,
"login": "juergenbeck"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "3 public repos, account ~10 yr old",
"points": 16.4,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 3
}
},
{
"code": "account_age_years",
"params": {
"years": 10
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"@xrmforge/cli",
"@xrmforge/devkit",
"@xrmforge/webapi",
"@xrmforge/helpers",
"@xrmforge/testing",
"@xrmforge/typegen",
"@xrmforge/eslint-plugin",
"@xrmforge/dataverse-core"
],
"ecosystems": "npm",
"any_deprecated": false,
"min_days_since_publish": 8
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "8 package(s) on npm",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 8,
"ecosystems": "npm"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 8 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 8
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "60 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 60
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "good",
"name": "Engineering Quality",
"value": 70,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 80,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "2 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 2
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": "eslint.config.js, eslint.config.mjs",
"points": 16,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "eslint.config.js, eslint.config.mjs"
}
}
],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "moderate",
"name": "Documentation",
"note": null,
"notes": [],
"value": 55,
"inputs": {
"topics": [],
"has_wiki": false,
"homepage": null,
"has_readme": true,
"has_docs_dir": true,
"has_description": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 45,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests",
"packaging",
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 31,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 15,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 3,
"scorecard_aggregate": 3.1
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 0 contributing companies or organizations -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "20 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "dependency_advisories",
"band": "excellent",
"name": "Dependency advisories",
"note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the npm:@xrmforge/cli@0.10.8 runtime dependency closure — what installing the published package pulls in — 82 packages. Reachability is not analyzed.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"no_advisories_left_outstanding"
]
}
},
{
"code": "weights_renormalized",
"params": {}
},
{
"code": "advisories_scope_published",
"params": {
"package": "npm:@xrmforge/cli@0.10.8",
"assessed": 82
}
},
{
"code": "advisories_reachability",
"params": {}
}
],
"value": 100,
"inputs": {
"source": "osv",
"advisories": 0,
"affected_packages": 0,
"assessed_packages": 82,
"unassessed_packages": 0,
"affected_by_severity": "none",
"direct_affected_packages": 0
},
"components": [
{
"key": "direct_dependencies_free_of_known_advisories",
"name": "Direct dependencies free of known advisories",
"detail": "no direct dependency carries a known advisory",
"points": 35,
"status": "met",
"details": [
{
"code": "no_direct_advisories",
"params": {}
}
],
"max_points": 35
},
{
"key": "indirect_dependencies_free_of_known_advisories",
"name": "Indirect dependencies free of known advisories",
"detail": "no indirect dependency carries a known advisory",
"points": 25,
"status": "met",
"details": [
{
"code": "no_indirect_advisories",
"params": {}
}
],
"max_points": 25
},
{
"key": "no_advisories_left_outstanding",
"name": "No advisories left outstanding",
"detail": "no advisory carries a publication date",
"points": 0,
"status": "excluded",
"details": [
{
"code": "advisories_no_publication_date",
"params": {}
}
],
"max_points": 40
}
]
},
{
"key": "malicious_dependencies",
"band": "excellent",
"name": "Malicious dependencies",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"source": "osv",
"meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
"packages": [],
"red_flag": false,
"assessed_packages": 82,
"malicious_packages": 0,
"direct_malicious_packages": 0,
"withdrawn_malicious_packages": 0,
"installable_malicious_packages": 0
},
"components": [
{
"key": "no_dependency_reported_as_a_malicious_package",
"name": "No dependency reported as a malicious package",
"detail": "no dependency is reported as a malicious package",
"points": 100,
"status": "met",
"details": [
{
"code": "no_malicious_dependencies",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "good",
"name": "AI Readiness",
"value": 71,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "excellent",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.92,
"agent_instruction_files": [
"CLAUDE.md",
"packages/devkit/src/scaffold/templates/AGENT.md"
],
"agent_instruction_max_bytes": 66013
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "CLAUDE.md, packages/devkit/src/scaffold/templates/AGENT.md",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "CLAUDE.md, packages/devkit/src/scaffold/templates/AGENT.md"
}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "92 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 92,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "moderate",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 62,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"pnpm-lock.yaml"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": true,
"typecheck_configs": [
"examples/account-form-demo/tsconfig.json",
"packages/cli/tsconfig.json",
"packages/dataverse-client/tsconfig.json",
"packages/dataverse-core/tsconfig.json",
"packages/devkit/tsconfig.json",
"packages/eslint-plugin/tsconfig.json",
"packages/helpers/tsconfig.json",
"packages/testing/tsconfig.json",
"packages/typegen/tsconfig.json",
"packages/webapi/tsconfig.json"
],
"agent_commit_share": 0.04,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": "eslint.config.js, eslint.config.mjs",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "eslint.config.js, eslint.config.mjs"
}
}
],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "examples/account-form-demo/tsconfig.json, packages/cli/tsconfig.json, packages/dataverse-client/tsconfig.json, packages/dataverse-core/tsconfig.json, packages/devkit/tsconfig.json, packages/eslint-plugin/tsconfig.json, packages/helpers/tsconfig.json, packages/testing/tsconfig.json, packages/typegen/tsconfig.json, packages/webapi/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "examples/account-form-demo/tsconfig.json, packages/cli/tsconfig.json, packages/dataverse-client/tsconfig.json, packages/dataverse-core/tsconfig.json, packages/devkit/tsconfig.json, packages/eslint-plugin/tsconfig.json, packages/helpers/tsconfig.json, packages/testing/tsconfig.json, packages/typegen/tsconfig.json, packages/webapi/tsconfig.json"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "4 of the last 100 commits agent-authored or agent-credited",
"points": 8,
"status": "partial",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 4,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"primary_language": "TypeScript",
"largest_source_bytes": 38309,
"source_files_sampled": 197,
"oversized_source_files": 0
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "TypeScript (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "TypeScript"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "0/197 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 197,
"oversized": 0
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"examples"
],
"has_mcp_signal": false,
"api_schema_files": []
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "examples",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "examples"
}
}
],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-30T13:47:45.263860Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/j/juergenbeck/XrmForge.svg",
"full_name": "juergenbeck/XrmForge",
"license_state": "standard",
"license_spdx": "MIT"
}