promotional bannermobile promotional banner

Ka0s KickCD (Retail)

Tracks interrupt + CC cooldowns on a movable icon grid
Back to Files

1.5.0-release

File nameKickCD-1.5.0-release.zip
Uploaded
Oct 9, 2026
Downloads
21
Size
6.7 MB
Flavors
Retail
File ID
9110172
Type
R
Release
Supported game versions
  • 12.1.0

What's new

tag fe84dfb3391843ec70e7233be5daba3193b5cb6f 1.5.0-release
Author:    Tushar Saxena <tushar.saxena@gmail.com>
Date:    Fri Oct 9 19:26:44 2026 +0530

Release 1.5.0

commit 0990fdc7973ed6e5bc7bfdce036375ec350ce81c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 9 19:21:55 2026 +0530

    Release 1.5.0: version bump, release notes and the gated release run

    Version 1.4.0 -> 1.5.0 in KickCD.toc (## Version) and core/KickCD.lua
    (NS.VERSION). The launcher test reads the TOC, so no test pins a literal.

    Release gate, read from docs/automated-tests/20261009-191808/manifest.json
    (run with --release 1.5.0 at c6470e7), all six pass:
    - Lint: pass, 0 warnings / 0 errors in 127 files
    - Tests: pass, 1319 passed, 0 failed, 1 skipped (a kit diagnostics
      contract branch this addon does not take), 1320 total
    - Perf: pass, 7 scenarios measured
    - Complexity: pass, lizard 1.24.0, 26160 NLOC / 3616 functions, avg CCN 2.1
    - CCN <= 15: 0 warnings, max CCN 15
    - Sighted: blindFiles 0 (first sighted run in this record)

    Files:
    - KickCD.toc, core/KickCD.lua: the version stamp
    - README.md: new 1.5.0 row at the top of Version History (/kcd profile,
      the target-casting glow for any cast, UTF-8 cast bar truncation, the
      cast bar anchor on an empty grid, drag strip tooltips and the Spells
      list gap)
    - docs/automated-tests/20261009-191808/: the release bundle, with its
      ANALYSIS.md
    - docs/automated-tests/RESULTS.md: the run's row and the watch list
      refreshed to this run (no function above CCN 15; no file in the
      1000-1500 band, all nine formerly tracked files #24-#32 peeled out)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01J2w6FgfFYw93meWZN9Ahn6

commit c6470e76397c3265d94622d7027217c19143b042
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 9 18:53:21 2026 +0530

    SD-FIN-03: remove dead test seam Helpers.__gridCtx

    Zero callers anywhere; no doc or surface pin named it.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01J2w6FgfFYw93meWZN9Ahn6

commit 31c0de19088e463eae1f09feec87a3b778ee665d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 9 17:49:30 2026 +0530

    SD-FIN-02: sync docs to code (collection sync-docs pass 2026-10-09)

    Docs and comment citations reconciled against today's tree: stale counts,
    drifted file:line citations, orphan anchors and toolchain gaps, each verified
    independently before applying. Comment edits are comment-only. Dead-export
    candidates reported, not removed. Green gate run after the edits.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01J2w6FgfFYw93meWZN9Ahn6

commit 0ca71f00114d6c6e87652d4cbea6b92b91efcb41
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:21:15 2026 +0530

    KC-STD: Roll the standards reference to v2.77.0 and sync the KC docs

    Standards reference (wow-revendor-standards procedure, against
    WowAddonStandards feat/2026-10-07-review-audit-remediation at ffcb11a,
    standard v2.77.0):
    - Three places checked: KickCD.toc ## X-Standard, the README Standard
      badge (bare image, not a link) and CLAUDE.md "Standards compliance
      (read first)" already carry the canonical, version-free form; v2.77.0
      did not change it, so none moved.
    - Retired notation: zero dotted global section numbers in the live tree
      (excluding libs/, tests/_kit/ and the frozen audits, reviews,
      automated-tests, revendor, superpowers and perf-analysis bundles).
      Range check: 934 filename-§N citations, every one resolving against
      v2.77.0's section files; the only two non-parsing hits are the
      canonical block's literal `filename-§N` placeholder.
    - WS-08 (versioning-git branch wording): no live doc restates trunk-only
      prose; CLAUDE.md's "never auto-stage/commit/push" stays true. WS-03:
      no live doc restates the shebang carve-outs; .gitattributes already
      carries both. No live doc names a "current" standard version; the
      "standard v2.54.0/v2.65.0/v2.67.0 introduced X" citations stay (history).
    - WS-07 citation form: four comments cited the vendored LibKa0s payload
      by bare line number, and all four had drifted after the v1.71.0
      re-vendor (PerfPanel.lua:185-196, Options.lua:210, DebugLog.lua:477,
      :482). Comment-only, they now cite by symbol: core/PerfSetup.lua,
      tests/test_perfsetup.lua, tests/test_constants.lua,
      tests/test_surface_parity.lua.

    Docs sync of KC-01..KC-10:
    - docs/castbar.md: the GRID_LAYOUT cache keeps primaryIcon verbatim, nil
      included, so a PRIMARY bar on an empty grid falls back to the grid
      frame (KC-01).
    - docs/schema.md: nameTruncate counts UTF-8 characters, not bytes (KC-02).
    - docs/debug.md: the diagnostics icongrid row names the three cached
      glow-gate scalars, `any` included (KC-03).
    - docs/module-map.md: Util.Throttle's zero-argument EMPTY_ARGS sentinel
      and its Cooldowns coalescer caller (KC-06).
    - docs/ARCHITECTURE.md: /kcd debug's unknown word refuses without the
      toggle, and castbar/interrupt take an optional target/focus word (KC-04).
    - docs/smoke-tests.md: new GRID-18 (KC-03), CAST-16 (KC-01) and LOC-7
      (KC-02), index ranges moved; DIAG-2 and SLASH-14 (already extended by
      KC-04) get Pending sign-off rows saying so. All recorded unrun.
    - Already in place and verified: icon-grid.md, data-flow.md (KC-03),
      slash-dispatch.md, debug.md castbar/interrupt sections and README FAQ
      (KC-04), schema.md/module-map.md/ARCHITECTURE.md SCHEMA_VERSION (KC-05),
      DEPENDENCIES.md (KC-07), the KC-08/KC-09 edits.

    docs/test-cases.md regenerated with no change: Total 1319 equals the
    README Tests badge 1319/1319. No version bump, no CHANGELOG section.

    Findings: none directly (item carries no finding ids); docs sync for
    KC-R-01..05, KC-A-04.

    Deviations: the WS-07 SHOULD speaks of another repo's code; the four
    fixed citations point into this repo's vendored copy of LibKa0s, which
    is that repo's code, and had all gone stale, so they were converted
    (comment-only). The item named docs/slash-dispatch.md and README for
    sync; both were already current after KC-04 and were left unchanged.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 0ca71f00114d6c6e87652d4cbea6b92b91efcb41
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:21:15 2026 +0530

    KC-STD: Roll the standards reference to v2.77.0 and sync the KC docs

    Standards reference (wow-revendor-standards procedure, against
    WowAddonStandards feat/2026-10-07-review-audit-remediation at ffcb11a,
    standard v2.77.0):
    - Three places checked: KickCD.toc ## X-Standard, the README Standard
      badge (bare image, not a link) and CLAUDE.md "Standards compliance
      (read first)" already carry the canonical, version-free form; v2.77.0
      did not change it, so none moved.
    - Retired notation: zero dotted global section numbers in the live tree
      (excluding libs/, tests/_kit/ and the frozen audits, reviews,
      automated-tests, revendor, superpowers and perf-analysis bundles).
      Range check: 934 filename-§N citations, every one resolving against
      v2.77.0's section files; the only two non-parsing hits are the
      canonical block's literal `filename-§N` placeholder.
    - WS-08 (versioning-git branch wording): no live doc restates trunk-only
      prose; CLAUDE.md's "never auto-stage/commit/push" stays true. WS-03:
      no live doc restates the shebang carve-outs; .gitattributes already
      carries both. No live doc names a "current" standard version; the
      "standard v2.54.0/v2.65.0/v2.67.0 introduced X" citations stay (history).
    - WS-07 citation form: four comments cited the vendored LibKa0s payload
      by bare line number, and all four had drifted after the v1.71.0
      re-vendor (PerfPanel.lua:185-196, Options.lua:210, DebugLog.lua:477,
      :482). Comment-only, they now cite by symbol: core/PerfSetup.lua,
      tests/test_perfsetup.lua, tests/test_constants.lua,
      tests/test_surface_parity.lua.

    Docs sync of KC-01..KC-10:
    - docs/castbar.md: the GRID_LAYOUT cache keeps primaryIcon verbatim, nil
      included, so a PRIMARY bar on an empty grid falls back to the grid
      frame (KC-01).
    - docs/schema.md: nameTruncate counts UTF-8 characters, not bytes (KC-02).
    - docs/debug.md: the diagnostics icongrid row names the three cached
      glow-gate scalars, `any` included (KC-03).
    - docs/module-map.md: Util.Throttle's zero-argument EMPTY_ARGS sentinel
      and its Cooldowns coalescer caller (KC-06).
    - docs/ARCHITECTURE.md: /kcd debug's unknown word refuses without the
      toggle, and castbar/interrupt take an optional target/focus word (KC-04).
    - docs/smoke-tests.md: new GRID-18 (KC-03), CAST-16 (KC-01) and LOC-7
      (KC-02), index ranges moved; DIAG-2 and SLASH-14 (already extended by
      KC-04) get Pending sign-off rows saying so. All recorded unrun.
    - Already in place and verified: icon-grid.md, data-flow.md (KC-03),
      slash-dispatch.md, debug.md castbar/interrupt sections and README FAQ
      (KC-04), schema.md/module-map.md/ARCHITECTURE.md SCHEMA_VERSION (KC-05),
      DEPENDENCIES.md (KC-07), the KC-08/KC-09 edits.

    docs/test-cases.md regenerated with no change: Total 1319 equals the
    README Tests badge 1319/1319. No version bump, no CHANGELOG section.

    Findings: none directly (item carries no finding ids); docs sync for
    KC-R-01..05, KC-A-04.

    Deviations: the WS-07 SHOULD speaks of another repo's code; the four
    fixed citations point into this repo's vendored copy of LibKa0s, which
    is that repo's code, and had all gone stale, so they were converted
    (comment-only). The item named docs/slash-dispatch.md and README for
    sync; both were already current after KC-04 and were left unchanged.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit d1a32a8aa241113ceefcd42448d435619bba8a9a
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:45:34 2026 +0530

    KC-09: Qualify standalone bare §N citations in tests and live docs

    documentation-§6 (as WS-07 restates it) asks each standalone section
    citation to name its section file. Comment and doc text only; no
    behaviour change and no test_source_style guard (per the verdict).

    - tests/test_flow_traces.lua: the twelve standalone §8/§9 sites
      (:28, :52, :68, :83, :110, :133, :145, :216, :228, :258, :275, :318)
      now read debug-logging-§8 / debug-logging-§9.
    - tests/test_library_lines.lua:97 -> debug-logging-§8.
    - docs/settings-panel.md:62 -> options-ui-§7, :203 -> options-ui-§14.
    - docs/slash-dispatch.md:71 and :98 (cited as :70/:97) ->
      slash-commands-§7.

    Left as they are: same-sentence continuations at
    test_flow_traces.lua:22 and slash-dispatch.md:118, plus
    docs/smoke-tests.md's own retired section numbers.

    Finding: KC-A-03.

    Deviation: docs/slash-dispatch.md:241 also had a standalone bare §5,
    which the audit did not list. It is now slash-commands-§5 (settings
    read/write output format), so the item's verify grep leaves only
    qualified citations or same-sentence continuations.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 460c7a4e1781bc5e4b61a445be8e042f557675de
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:42:09 2026 +0530

    KC-08: Name rules, not counts, in four drifted inventories

    Resolves KC-A-02 (documentation-§5 count drift). Each site carried a
    count or closed list that had already gone stale:

    - docs/ARCHITECTURE.md: drop "Eight do" / "The other thirty-six" and the
      closed file list (settings/OptionsSetup.lua was missing from it). State
      the rule instead -- a file reads the first vararg only to hand the
      folder name to a vendored LibKa0s payload that cannot infer it -- and
      give the git grep that lists the files today.
    - .luacheckrc: the M4c-06 history comment keeps the historical
      twenty-nine (past tense) and drops the present-tense "Eight files" and
      "thirty-three authored files" counts, pointing at the ARCHITECTURE rule.
    - docs/compat-layer.md: NS.State.SetInCombat is called from core/State.lua's
      combat listener, an AceEvent target armed by State.Arm (re-armed and
      re-seeded by State.StandUp), not a bootstrap CreateFrame.
    - .pkgmeta: drop "Seven files, 7.5M" and the size claim; the
      media/screenshots art is project-page material the CurseForge CDN serves.

    Deviation: the compat-layer row also names State.StandUp, because it is
    a second SetInCombat caller in the same file and "called only by the
    listener" would otherwise be a new inaccuracy.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 619f277537a32f2a29bbb9015fdf97871205f14d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:38:51 2026 +0530

    KC-07: Trim .luacheckrc read_globals to names a linted file reads bare

    Resolves KC-R-08 (review F-008, continuing F-016). The top-level
    read_globals carried 44 names that no linted file reads bare, so a new
    bare call to any of them (for example the legacy UIDropDownMenu_AddButton)
    would have linted clean.

    Census (git grep -nwE '(^|[^._A-Za-z0-9"])NAME' over linted .lua, i.e.
    excluding libs/, tests/_kit/, docs/audits/, docs/reviews/, _dev/, with
    comment lines dropped): 0 bare readers for all 44 names, except three
    hits that are not reads: _G (every hit is an _G.X field access, and _G is
    already in std lua51), UnitChannelInfo (inside a help string in
    core/KickCD.lua:415) and time (inside a message string in
    tests/test_color_shape.lua:542).

    Removed: _G, GetTime, GetTimePreciseSec, GameFontNormal,
    GameFontHighlight, GameFontDisable, STANDARD_TEXT_FONT, hooksecurefunc,
    securecallfunction, issecretvalue, C_Timer, C_Spell, C_SpecializationInfo,
    GetLocale, InCombatLockdown, PlaySound, UnitCastingInfo, UnitChannelInfo,
    UnitExists, UnitCanAttack, UnitGUID, UnitName, UnitIsDead, IsLoggedIn,
    UISpecialFrames, UIDropDownMenu_AddButton, CreateColorFromHexString,
    WrapTextInColorCode, CopyTable, wipe, tContains, tinsert, tremove,
    strsplit, strtrim, strjoin, date, time, BackdropTemplateMixin,
    CreateFromMixins, NORMAL_FONT_COLOR, HIGHLIGHT_FONT_COLOR, RED_FONT_COLOR,
    GREEN_FONT_COLOR. The 24 bare-read names stay. luacheck . stays 0/0 with
    nothing to restore. No files["tests/"] read_globals stanza was added.
    Group headings regrouped so none is left empty ("fonts / textures used
    in DebugLog / panels" went with its names).

    Ripples: DEPENDENCIES.md cite .luacheckrc:48-79 -> :48-68, and the
    tests/wow_mock.lua comment that said `date` is in read_globals now says
    it no longer is. tests/test_lintconfig.lua pins no removed name, so it
    is unchanged; test count unchanged (1319 passed, 1 skipped), so
    docs/test-cases.md and the badge need no regeneration.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 0b42a855851bf2cc2116a37e08d5bcc1e5464ee3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:34:50 2026 +0530

    KC-06: reuse a frozen empty-args sentinel for zero-arg Throttle calls

    Util.Throttle packed `{ n = select('#', ...), ... }` on every wrapped()
    call, including the zero-argument calls Cooldowns' refresh coalescer makes
    on every SPELL_UPDATE_COOLDOWN / _USABLE / _CHARGES: one throwaway table per
    event in combat. A file-scope `EMPTY_ARGS = { n = 0 }`, never written to,
    now stands in when select('#', ...) == 0; fire() only reads args.n and
    unpacks, so sharing it is safe. Calls with arguments still get a fresh
    table per burst, and the closure comment now names the sentinel and why it
    is safe.

    Tests (characterization, green before and after the change):
    - a zero-argument throttle fires fn once per burst with no arguments
    - a zero-arg burst after an args burst does not leak the old args

    docs/test-cases.md regenerated and the README Tests badge moved to
    1319/1319. No perf scenario added, per the verified verdict on KC-R-09.

    Finding: KC-R-09

    Deviation: the sentinel's explanatory comment sits above the function's
    `---` doc block rather than inside it, so the doc block stays attached to
    Util.Throttle.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit ef6ec90ef86bf7ff8b1bf92b399ed47a7cfc7095
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:28:36 2026 +0530

    KC-05: publish the migration target as NS.SCHEMA_VERSION; drop the alias

    savedvariables-§1 names the runner's target NS.SCHEMA_VERSION, the
    spelling the other ten addons use. KickCD kept it as a file-local
    CURRENT_DB_VERSION republished as Database.CURRENT_DB_VERSION.

    - core/Database.lua publishes NS.SCHEMA_VERSION = 5 (value unchanged, no
      stored data changes) and no longer sets Database.CURRENT_DB_VERSION.
    - core/Database_Migrations.lua reads NS.SCHEMA_VERSION; the runner loop
      and the missing-step jump use it; comments renamed.
    - modules/Diagnostics.lua's state section prints schema stored vs
      NS.SCHEMA_VERSION.
    - tests: new tests/test_database.lua case pins NS.SCHEMA_VERSION == 5, a
      fresh install stamped with it, and the alias gone (red on HEAD: got
      nil); test_diagnostics reads NS.SCHEMA_VERSION; comments and the
      test_color_shape red-under note renamed.
    - docs: ARCHITECTURE.md, module-map.md (incl. "this file publishes
      NS.SCHEMA_VERSION"), schema.md renamed; frozen bundles untouched.
    - docs/test-cases.md regenerated and README Tests badge moved to
      1317/1317 (Total row 1317).

    Finding: KC-A-04.

    Deviation: the optional "NS.SCHEMA_VERSION == #steps + 1" pin was not
    added, because Database_Migrations keeps its step table file-local and
    the item asks for it only if the table is exposed.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit ffcb11aea6aa77ef3988546dda348928df4faaef
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:23:43 2026 +0530

    KC-04: /kcd debug refuses an unknown word untoggled; castbar takes focus

    An unknown /kcd debug word used to refuse and then re-enter runDebug(self, ""),
    which toggled the debug console, so a typo such as `/kcd debug spels` opened
    or closed it. The sub-verb list printer is now a file-local printDebugList:
    the bare verb still toggles the console and prints it (debug-logging-§5), and
    the unknown-word path refuses and prints it without the toggle.

    runDebug now passes the remainder after the sub-verb to the row. A file-local
    parseDebugUnit accepts '' / target / focus (any case); castbar calls
    Castbar:DebugDump(unit) and interrupt Compat.DebugInterrupt(unit), and any
    other word is refused ("unknown unit '<w>', expected target or focus")
    through refuse() with no dump. Help strings name the optional unit.

    Tests (tests/test_slash.lua): the 'toggle it back' workaround is gone from
    the unknown-word case, and a new case pins the console's shown state across
    `/kcd debug NoSuch` from both states; four cases cover castbar default /
    focus, interrupt focus, and a refused bogus unit. Docs: debug.md,
    slash-dispatch.md, testing.md, smoke-tests.md (SLASH list, DIAG-2) and the
    README FAQ; docs/test-cases.md regenerated, badge 1316/1316.

    Findings: KC-R-03, KC-R-04.

    Deviations: the item expected the default `/kcd debug castbar` case to be
    green on HEAD; it was red there because HEAD called DebugDump() with nil
    (the callee defaulted to target), and the test asserts the explicit unit.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit eaa01c9667698a9d65ee9dfdfb98ca6699c0ff17
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:18:08 2026 +0530

    KC-03: address review — diagnostics prints the any-cast gate, newInstance declares it

    Review of 33696cd found two missed ripples of the third gate scalar:

    - modules/Diagnostics.lua: the IconGrid section's gate line printed only
      lastGateCasting and lastGateInterruptible, so for a friendly caster it
      read "gate casting=false interruptible=nil" while the gate had moved on
      the raw cast state. It now appends any=<lastGateAnyCasting>.
    - modules/IconGrid.lua: newInstance declares lastGateAnyCasting = nil
      beside the other two cached gate scalars (no runtime change; the
      constructor lists all per-instance state, as docs/icon-grid.md names).
    - tests/test_diagnostics.lua: red-first case "the IconGrid gate line names
      all three cached gate scalars, the raw cast state included".
    - docs/test-cases.md regenerated (Total 1311), README Tests badge 1311/1311.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 33696cdfba99661c3f0f51d9bbc3e7338b2f2eca
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:12:35 2026 +0530

    KC-03: glow gate tracks any target cast for the target_casting trigger

    The 'target_casting' glow trigger reads inst.isCasting() (any cast by
    the unit, the same meaning as the same-named visibility mode), but
    IconGrid:RefreshAllGlows keyed its short-circuit gate only on
    IsHostileUnitCasting and the interruptibility tri-state. For a friendly
    or otherwise non-attackable caster both stayed at (false, nil), so the
    per-icon UpdateGlow never ran: the glow did not start on the cast and
    went stale when it ended.

    Decision: 'target_casting' = any cast, friendly or hostile;
    'target_casting_interruptible' stays hostile-only. The trigger is
    unchanged and the gate is fixed:

    - modules/IconGrid_Visibility.lua: RefreshAllGlows computes a third
      scalar, anyCasting = hostileCasting or instanceCasting(inst) (no extra
      API read when a hostile cast is already known); gateMoved compares
      inst.lastGateAnyCasting too; the cache stores three scalars (still no
      table). Doc comments name the three gate inputs and why the raw cast
      state is in it. RefreshAllGlows and gateMoved stay under CCN 15.
    - defaults/Profile.lua: glow-trigger comment says 'target_casting' is
      any cast and 'target_casting_interruptible' hostile only.
    - tests/test_icongrid_glowgate.lua: red-first case "a friendly cast
      moves the gate for the target_casting trigger" (red on HEAD: the spy
      UpdateGlow ran once, not twice) and "an unmoved friendly-cast gate
      still short-circuits".
    - docs/data-flow.md (glow paragraph) and docs/icon-grid.md describe the
      three-scalar gate; docs/test-cases.md regenerated, README badge
      1308 -> 1310.

    Finding: KC-R-05.

    Deviation: docs/icon-grid.md had no glow-gate paragraph to update; the
    existing glow-gate prose lives in docs/data-flow.md, which carries the
    full description, and icon-grid.md gains a sentence on the cast-filter
    paragraph. tests/perf.lua has no glowGate scenario (the bracket is
    in-game only), so the perf gate is the offline run passing unchanged.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 36a880844762145ee026428738c1e3a6f218b30d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:04:38 2026 +0530

    KC-02: count cast-bar name truncation in UTF-8 characters, not bytes

    truncateName measured the spell name with #name and cut it with
    string.sub under a "Truncate after (characters)" label, so accented
    names were cut early, Cyrillic at about half and CJK at about a third of
    the promised length, and a cut could split a code point into an invalid
    glyph. modules/Castbar.lua gains a file-local utf8Prefix(s, cap) that
    mirrors MultiMeters' utf8Truncate (every byte outside 0x80-0xBF starts a
    character; return s:sub(1, i-1) at the (cap+1)th start, else s).
    truncateName keeps its nil / 0 / secret short-circuits, then appends the
    ellipsis only when utf8Prefix actually cut. A name of exactly maxChars
    characters is never truncated whatever its byte length. The stale
    "byte-counted" header comment is rewritten (characters, no split code
    point, pure Lua because strlenutf8 is absent headlessly, never called on
    a secret), and docs/castbar.md's truncation sentence now says characters.
    No LibKa0s helper (Option B per the verified verdict).

    Tests (tests/test_castbar_helpers.lua), red first on HEAD:
    - TruncateName('Éclair de givre', 3) == 'Écl…'
    - CJK: TruncateName('脚踢打断', 2) == '脚踢…'
    - a 4-character Cyrillic name at cap 4 is returned unchanged
    - every output, over caps 1..12 on four names, is valid UTF-8
    Existing ASCII and secret pass-through cases unchanged and green.
    docs/test-cases.md regenerated and README badge moved 1304 -> 1308.

    Finding: KC-R-02.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 5cd119e3e9bb9ac859ee4f1ccea0a7589c256643
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 19:59:54 2026 +0530

    KC-01: drop a stale primary-icon anchor when the icon grid empties

    Castbar:OnGridLayout cached payload.primaryIcon only when it was non-nil,
    but IconGrid announces primaryIcon = nil for an empty grid and releases the
    old button to its pool (ClearAllPoints + Hide). The cache kept that orphan,
    so ApplyAnchor in PRIMARY mode kept anchoring to it and never reached the
    resolveGridFrame fallback. The payload is the full layout announcement, so
    primaryIcon is now copied verbatim (nil included); gridFrame keeps its guard
    since every announcement carries it. The misleading "defensive" comment is
    rewritten, and resolvePrimaryIcon's comment in Castbar.lua now says the
    cache can hold nil and the bar then falls through to the grid frame.

    Tests (tests/test_castbar_frame.lua), red first on HEAD:
    - an empty grid announcement drops the cached primary icon and anchors to
      the grid frame (red: cache still held btnA)
    - a focus grid announcement never touches the target bar's cache

    docs/test-cases.md regenerated and the README Tests badge moved to
    1304/1304. Owner smoke check (empty spell list in PRIMARY mode, cast bar
    stays visible at the grid) is the owner's to run.

    Findings: KC-R-01

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit e1dabec707024d9cf57b18912b936921a427ec93
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 19:52:54 2026 +0530

    RV-KC: re-vendor LibKa0s v1.71.0 (kit 38) with v1.69.0-v1.70.0 span

    Mechanical re-vendor from the LOCAL LibKa0s tag v1.71.0 (cb274a4):
    libs/LibKa0s/ and tests/_kit/ replaced whole from git archive (base
    v1.70.0 confirmed against the payload bytes). Minors: WidgetsLineChart 3,
    WidgetsAutocomplete 2, Slash 20 / SlashParse 2, Env 2, OptionsIdList 4;
    kit revision 37 -> 38 (new secrets.lua, --list Totals exclude declared
    skips).

    - CLAUDE.md provenance line v1.70.0 -> v1.71.0.
    - docs/testing.md: the version-now sentence is de-tagged (it no longer
      names the tag ../LibKa0s sits on; it states the two agree only between
      a re-vendor and the library's next tag) so it cannot rot (KC-A-01).
    - docs/test-cases.md regenerated with --list: Total 1302 now equals the
      README badge (1302/1302) and a '| Skipped | 1 |' row carries the
      diagnostics opt-out declared skip (KC-A-07). Badge unchanged.
    - docs/revendor/2026-10-07-v1.71.0/ (01_DELTA, 02_CANDIDATES,
      05_SUMMARY): candidates (Kit.secret + issecretvalue installer,
      LineChart clipping/hover, Autocomplete re-hook guard) listed as not
      adopted in this run (owner scope ruling 5); no interview, no issue.
    - docs/revendor/2026-10-07-v1.69.0-v1.70.0/ (01_DELTA, 05_SUMMARY): span
      bundle for the unrecorded re-vendors da8a8b8 (v1.69.0) and 9d4a10b
      (v1.70.0), base v1.68.1; Autocomplete noted as a possible Spells
      add-box candidate, not adopted, no issue (KC-A-01).

    Blocker fixed host-side (mechanical, from kit 38): tests/test_list_mode.lua
    pinned revision 37's Totals (Total == every bullet, skips included) and
    failed 1302 vs 1303. The case is replaced by one asserting the new
    contract no less strictly: Skipped row == bullets marked "(skipped: ...)"
    and Total + Skipped == every bullet. No edit under libs/ or tests/_kit/
    beyond the copy.

    Not committed: test_eol flagged docs/audits/2026-10-07/01_CURRENT_STATE.md
    and 02_DEVIATIONS.md as LF on disk (index already correct, pre-existing);
    repaired by re-checkout, no content change.

    Gate: 1302 passed, 0 failed, 1 skipped; luacheck 0/0 in 127 files;
    lizard no function above CCN 15; largest authored .lua 996 lines.

    Findings: KC-A-01, KC-A-07.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 99136049d7fef7d40047959b794f219dc89199c4
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 16:51:55 2026 +0530

    RA-00: record 2026-10-07 standards audit and review bundles

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 9d4a10bd3519acee65e0f73e107a2858e62cb018
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:38:50 2026 +0530

    chore: re-vendor LibKa0s v1.70.0

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 9d4a10bd3519acee65e0f73e107a2858e62cb018
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:38:50 2026 +0530

    chore: re-vendor LibKa0s v1.70.0

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit da8a8b882a4984893b422e43cfd7e06a7646ce21
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:52:58 2026 +0530

    chore: re-vendor LibKa0s v1.69.0 (kit 37; adds the line chart widget)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 7b29045a6542b39dc64034e1ec0a372d3f35f289
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Sun Oct 4 15:17:12 2026 +0530

    DC-REV-01: re-vendor LibKa0s v1.68.1 (kit 36; no library minor moved)

    Both payloads copied whole from the pushed annotated tag v1.68.1 (9000cbd, tag object 9fb7956)
    via git archive. libs/LibKa0s/ is byte-identical to v1.68.0's: no LibStub minor moves, no file
    added or removed, no floor rises. tests/_kit/ moves to kit revision 36 (framework.lua,
    run-automated-tests.sh, test_eol.lua): the kit names /dev-copilot:* commands where it named
    /wow-addon:*. Nothing was removed upstream, so nothing was deleted. diff -r against the tag is
    empty for both payloads, with and without --strip-trailing-cr.

    The CLAUDE.md provenance line rolls to v1.68.1 in this commit, and docs/testing.md's version-now
    sentence rolls with it. No prose here names the kit revision this repo holds; every remaining
    "kit 35" names the revision the sighted complexity suite arrived in, so it stays. No contract
    blocker.

    Zero adoption candidates (rename-only release), so no interview. Item stays a settled decline
    (#14). Frozen bundle: docs/revendor/2026-10-04-v1.68.1/ (01_DELTA, 02_CANDIDATES, 05_SUMMARY).

    Tests: 1302 passed / 1 skipped / 1303, unchanged (including both vendor-sync cases).
    docs/test-cases.md regenerates identical; the README badge is unchanged.
    luacheck: 0 warnings / 0 errors in 127 files.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01MsGF7a1YxB69EsRnBC8rcE

commit 7b29045a6542b39dc64034e1ec0a372d3f35f289
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Sun Oct 4 15:17:12 2026 +0530

    DC-REV-01: re-vendor LibKa0s v1.68.1 (kit 36; no library minor moved)

    Both payloads copied whole from the pushed annotated tag v1.68.1 (9000cbd, tag object 9fb7956)
    via git archive. libs/LibKa0s/ is byte-identical to v1.68.0's: no LibStub minor moves, no file
    added or removed, no floor rises. tests/_kit/ moves to kit revision 36 (framework.lua,
    run-automated-tests.sh, test_eol.lua): the kit names /dev-copilot:* commands where it named
    /wow-addon:*. Nothing was removed upstream, so nothing was deleted. diff -r against the tag is
    empty for both payloads, with and without --strip-trailing-cr.

    The CLAUDE.md provenance line rolls to v1.68.1 in this commit, and docs/testing.md's version-now
    sentence rolls with it. No prose here names the kit revision this repo holds; every remaining
    "kit 35" names the revision the sighted complexity suite arrived in, so it stays. No contract
    blocker.

    Zero adoption candidates (rename-only release), so no interview. Item stays a settled decline
    (#14). Frozen bundle: docs/revendor/2026-10-04-v1.68.1/ (01_DELTA, 02_CANDIDATES, 05_SUMMARY).

    Tests: 1302 passed / 1 skipped / 1303, unchanged (including both vendor-sync cases).
    docs/test-cases.md regenerates identical; the README badge is unchanged.
    luacheck: 0 warnings / 0 errors in 127 files.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01MsGF7a1YxB69EsRnBC8rcE

commit 604797d2324972a25d4b65a2bb0482ca8117df05
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Sun Oct 4 14:21:52 2026 +0530

    DC-REN-01: name the dev-copilot commands in live docs

    The wow-addon plugin merged into dev-copilot 2.0.0. Live docs and test
    comments now name the dev-copilot commands; frozen bundles stay as written.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01MsGF7a1YxB69EsRnBC8rcE

commit 604797d2324972a25d4b65a2bb0482ca8117df05
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Sun Oct 4 14:21:52 2026 +0530

    DC-REN-01: name the dev-copilot commands in live docs

    The wow-addon plugin merged into dev-copilot 2.0.0. Live docs and test
    comments now name the dev-copilot commands; frozen bundles stay as written.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01MsGF7a1YxB69EsRnBC8rcE

commit 0759d7b115a6f8aeffcc76ec23798ccc8e388b3f
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Sat Oct 3 12:47:57 2026 +0530

    SD-FIN-01: sync docs (Pillow via apt on Ubuntu 24.04; lizard note; drag-handle minor)

    pip install Pillow fails under PEP 668, so DEPENDENCIES uses python3-pil; the harness's lizard-sighted case is noted; IconGrid_Handle names the vendored WidgetsDragHandle minor 4.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01GBEbct8mwzFqZSG1oTkv8f

commit 961c6525a401da0ed6ff953c29e0e58a72be4450
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 23:47:57 2026 +0530

    TP-KC-01: both drag strips' tooltips open beside the strip (tooltipPlace)

    Adopts LibKa0s WidgetsDragHandle minor 4's tooltipPlace on the cast bar's
    and the icon grid's strips. NS.Util.PlaceTooltipBeside (core/Util.lua)
    anchors the tooltip TOPLEFT to the strip's TOPRIGHT, or TOPRIGHT to its
    TOPLEFT when the strip's right edge plus the tooltip's width would pass the
    screen's right edge. The comparison is in screen pixels (each read times its
    frame's effective scale; the grid strip takes the master scale). A hovered ?
    mark resolves to its strip, so both show the tooltip in one place. Every
    read is guarded through NS.Compat.IsSecret plus nil and type checks; on any
    untrusted read it answers nil with nothing anchored, so the widget falls
    back to the cursor tooltip. It returns true only once placed.

    Why adopt when the strips were already frame-owned (ANCHOR_TOP), not
    cursor-owned: the owner's request is the tooltip BESIDE the strip, right or
    left at the screen edge. ANCHOR_TOP is not that. It opens upward into what
    KickCD stacks above the strip (the unit label, and the Focus grid over
    Target's by default), it gives the ? mark a second position, and near the
    screen top it is clamped back over the strip being hovered. AuraMaster
    (TP-AM-01) places its strip tooltips the same way. Reasoning recorded in
    docs/revendor/2026-10-02-v1.68.0/03_DECISIONS.md.

    Test first: six PlaceTooltipBeside cases in test_util_anchor.lua (right,
    left flip, mark -> strip, scaled strip, secret read, nil read) and one
    hover case each in test_castbar_frame.lua and test_icongrid_handle.lua
    (owned once by UIParent at ANCHOR_NONE, anchored beside the strip). All
    eight were red before the code.

    Docs: both handle headers, castbar.md, icon-grid.md, module-map.md;
    smoke-tests.md gains CAST-15 and GRID-17 (owner-run, unmarked), CAST-10
    corrected, routing and owed table updated. Bundle 05_SUMMARY.md.

    Gate: 1302 passed / 0 failed / 1 skipped (1303), was 1294 (1295);
    docs/test-cases.md regenerated, README badge 1302. luacheck 0/0 in 127
    files. Sighted complexity: pass, max CCN 15, 0 warnings
    (PlaceTooltipBeside CCN 10). Every file under 1500 lines. No version bump.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 961c6525a401da0ed6ff953c29e0e58a72be4450
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 23:47:57 2026 +0530

    TP-KC-01: both drag strips' tooltips open beside the strip (tooltipPlace)

    Adopts LibKa0s WidgetsDragHandle minor 4's tooltipPlace on the cast bar's
    and the icon grid's strips. NS.Util.PlaceTooltipBeside (core/Util.lua)
    anchors the tooltip TOPLEFT to the strip's TOPRIGHT, or TOPRIGHT to its
    TOPLEFT when the strip's right edge plus the tooltip's width would pass the
    screen's right edge. The comparison is in screen pixels (each read times its
    frame's effective scale; the grid strip takes the master scale). A hovered ?
    mark resolves to its strip, so both show the tooltip in one place. Every
    read is guarded through NS.Compat.IsSecret plus nil and type checks; on any
    untrusted read it answers nil with nothing anchored, so the widget falls
    back to the cursor tooltip. It returns true only once placed.

    Why adopt when the strips were already frame-owned (ANCHOR_TOP), not
    cursor-owned: the owner's request is the tooltip BESIDE the strip, right or
    left at the screen edge. ANCHOR_TOP is not that. It opens upward into what
    KickCD stacks above the strip (the unit label, and the Focus grid over
    Target's by default), it gives the ? mark a second position, and near the
    screen top it is clamped back over the strip being hovered. AuraMaster
    (TP-AM-01) places its strip tooltips the same way. Reasoning recorded in
    docs/revendor/2026-10-02-v1.68.0/03_DECISIONS.md.

    Test first: six PlaceTooltipBeside cases in test_util_anchor.lua (right,
    left flip, mark -> strip, scaled strip, secret read, nil read) and one
    hover case each in test_castbar_frame.lua and test_icongrid_handle.lua
    (owned once by UIParent at ANCHOR_NONE, anchored beside the strip). All
    eight were red before the code.

    Docs: both handle headers, castbar.md, icon-grid.md, module-map.md;
    smoke-tests.md gains CAST-15 and GRID-17 (owner-run, unmarked), CAST-10
    corrected, routing and owed table updated. Bundle 05_SUMMARY.md.

    Gate: 1302 passed / 0 failed / 1 skipped (1303), was 1294 (1295);
    docs/test-cases.md regenerated, README badge 1302. luacheck 0/0 in 127
    files. Sighted complexity: pass, max CCN 15, 0 warnings
    (PlaceTooltipBeside CCN 10). Every file under 1500 lines. No version bump.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 18dc978fea7d59ea58b486df32ccb10c78f1f9ff
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 23:42:12 2026 +0530

    TP-KC-01: re-vendor LibKa0s v1.68.0 (WidgetsDragHandle 4; kit 35 unchanged)

    Whole-folder copy of libs/LibKa0s/ and tests/_kit/ from the local tag v1.68.0
    (cc9f5eb, == ../LibKa0s HEAD; git diff --quiet v1.68.0 -- LibKa0s testkit
    clean). The one moved file is WidgetsDragHandle.lua, minor 3 -> 4: the
    optional tooltipPlace(tip, frame) spec field and descriptor `place`. Without
    a hook a hover makes minor 3's calls in minor 3's order, so KickCD's two
    strips (cast bar, icon grid) are unchanged by this commit. The kit did not
    move (revision 35). No file added or removed; nothing deleted. diff -r of
    both folders against the tag is empty; CRLF working tree as before.

    Provenance line in CLAUDE.md and docs/testing.md's version-now line roll to
    v1.68.0. No blocker (3g: additive only). No span bundle, no base correction.

    Frozen bundle: docs/revendor/2026-10-02-v1.68.0/ (01-04; 05 lands with the
    adoption commit). Decision recorded there: adopt tooltipPlace on both strips.

    Tests: 1294 passed / 0 failed / 1 skipped (1295) before and after, vendor
    sync green, so docs/test-cases.md and the README badge are unchanged.
    luacheck 0/0 in 127 files. Sighted complexity: pass, max CCN 15, 0 warnings.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 719e9650df62bbcae754bfc03ac66db7348636b9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 10:24:31 2026 +0530

    CA-FIN-02: doc sync before merge

    Refresh three stale file:line citations (test_coresetup ls popen, NS.COMMANDS publish, Slash.lua out sink).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 719e9650df62bbcae754bfc03ac66db7348636b9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 10:24:31 2026 +0530

    CA-FIN-02: doc sync before merge

    Refresh three stale file:line citations (test_coresetup ls popen, NS.COMMANDS publish, Slash.lua out sink).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit eff6cfcd55bdf3f502aea8517282c773171e9f92
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 02:07:21 2026 +0530

    CA-KC-02: adopt Core.SECRET; delete PANEL_HEADER_TOP/HEIGHT (KickCD#36 items 4-5)

    core/CoreSetup.lua publishes NS.SECRET on both paths: lib.SECRET live, and the
    "<secret>" literal in the library-absent arm only, where the stub
    NS.SafeToString now returns it too (D3.11, events-frames-taint-§8).
    core/Compat.lua's safeRender returns NS.SECRET at call time, so the
    `/kcd debug interrupt` dump and every SafeToString line spell one sentinel.

    core/Constants.lua deletes PANEL_HEADER_TOP and PANEL_HEADER_HEIGHT, which had
    no reader: lib.LAYOUT.HEADER_TOP/HEADER_HEIGHT are INTERNAL to LibKa0s-Options
    and never handed to a host, so they are deleted rather than re-read (D3.7). The
    PANEL_PADDING_X comment now explains both.

    Tests: NS.SECRET equals lib.SECRET live and the stub literal degraded; a
    source scan that "<secret>" is spelled only in CoreSetup's library-absent arm;
    the two PANEL_HEADER_* cases replaced by a stays-deleted case, and the
    restatement lint widened to HEADER_TOP/HEADER_HEIGHT. Docs: module-map,
    ARCHITECTURE (cites refreshed), compat-layer, debug, testing, smoke checks
    DIAG-45 and DEGRADED-15 with Pending sign-off rows, test-cases.md and the
    badge (1294/1294).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 6cd075e972b8209ac1e3544de85801f1520d39a7
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 02:02:36 2026 +0530

    CA-KC-02: characterization test for the degraded interrupt dump's <secret>

    Pins that with LibKa0s absent, `/kcd debug interrupt` still renders a
    secret-tainted name and position as <secret>. Green on today's code, before
    KickCD#36 item 4 moves core/Compat.lua's safeRender onto NS.SECRET, which
    the library-absent arm of core/CoreSetup.lua must then supply. test-cases.md
    and the badge (1292/1292).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 2353c1a32b33a4ecb46c90059554290fd385a5df
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 01:58:06 2026 +0530

    CA-KC-01: adopt Slash.SplitVerb, FindCommand and CommandRows (KickCD#36 items 1-3)

    settings/Slash.lua publishes NS.Slash.SplitVerb / FindCommand / CommandRows on
    both paths: LibKa0s-Slash-1.0's minor-19 members live, and a minimal stub in
    the library-absent arm (verb split, guarded lookup, PLAIN `cmd  desc` rows, no
    FormatRow copy, D3.6). The stub's LandingRows / HelpRows and verb lookup reuse
    them.

    core/KickCD.lua deletes lowerFirst and findCommand and reads NS.Slash.* at call
    time: runDebug's inline verb split, both lookups, and both sub-help loops
    (`/kcd debug` and `/kcd spells`, D3.7) now go through the library. Sub-help
    rows change hex case only (|cFFFFFF00), matching `/kcd help`.

    Tests: the characterization rows tightened to exact bytes, a source-scan guard
    that core/KickCD.lua carries no `|cffffff00/kcd`, lowerFirst or findCommand,
    the degraded sub-lists pinned to the plain shape, the stub vocabulary's
    contract, and the surface-parity case naming the three members. Docs:
    slash-dispatch, module-map, ARCHITECTURE, smoke checks SLASH-14 and
    DEGRADED-14 with Pending sign-off rows, test-cases.md and the badge
    (1291/1291). Two stale settings/Slash.lua line cites in tests refreshed.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit ece3a6e43c26819d2b0bf15cebface4e51c4c503
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 01:53:00 2026 +0530

    CA-KC-01: characterization tests for the /kcd debug and /kcd spells sub-levels

    Pins today's sub-help rows (shared-format, table order, case-insensitive hex),
    the unknown-debug-word refusal and reprint, case-insensitive sub-verb matching
    with the remainder's case kept, and the degraded sub-lists answering. Green on
    today's code, before KickCD#36 items 1-3 adopt Slash.SplitVerb, FindCommand
    and CommandRows.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 1777794325acb7645aaef0b7fa258da2a8c82c64
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 01:47:41 2026 +0530

    CA-KC-NM: the Options descriptor passes addonName (LibKa0s#42)

    settings/OptionsSetup.lua keeps its first vararg as `addonName` (was `_`)
    and passes `addonName = addonName,` on the Options descriptor beside
    parentTitle/mainPanelName, so an IdList help mark draws the library's own
    `info` art (Options 28 / OptionsIdList 3) rather than the client glyph.
    Latent here: KickCD has no IdList with help today. The library-absent
    path is unaffected (the descriptor only gains a string field).

    Test first: tests/test_options_panel.lua gains a source-pattern guard
    (the vararg is named addonName, and the descriptor table passes
    `addonName = addonName,`) plus an on-disk assert that
    libs/LibKa0s/media/icons/info.tga is vendored. Red on the old source.

    Totals: 1282 passed / 1 skipped / 1283 -> 1283 passed / 1 skipped / 1284.
    luacheck 0/0. Vendor parity clean. Sighted complexity green (max CCN 15).
    Docs: test-cases.md regenerated, README badge, smoke-tests.md PANEL-30
    (index range, OptionsSetup partial-change line, Pending sign-off row).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 48f79605d8d07ec3d7d2fe81893e7e6e75227469
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 01:40:11 2026 +0530

    CA-KC-RV: re-vendor LibKa0s v1.67.0 (Core 10, Options 28, OptionsIdList 3; kit 35 unchanged)

    Whole-folder copy of libs/LibKa0s/ and tests/_kit/ from the local tag v1.67.0
    (0bccf4c, == ../LibKa0s HEAD, clean tree): Core 9 -> 10 (MakeResizable
    canResize / onResizeStop / gripParent), Options 27 -> 28 (docblock),
    OptionsIdList 2 -> 3 (addonName loaded-addon guard). The kit did not move
    (revision 35). No file added or removed; nothing deleted. diff -r of both
    folders against the tag is empty; CRLF working tree as the v1.66.0 re-vendor.

    Provenance line in CLAUDE.md and docs/testing.md's version-now line roll to
    v1.67.0. No consumer test broke from a library change. KickCD passes none of
    the new MakeResizable fields (its grips are the library's console, copy
    window and perf panel) and builds no IdList; addonName is CA-KC-NM.

    Frozen bundle: docs/revendor/2026-10-02-v1.67.0/ (candidates listed, not
    interviewed, per the census adoption design).

    Tests: 1282 passed / 0 failed / 1 skipped (1283) before and after, so
    docs/test-cases.md and the README badge are unchanged. luacheck 0/0 in 127
    files. Sighted complexity: pass, max CCN 15, 0 warnings, blindFiles 0.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 499cf1e398c79124751041c341c2f87ed14dca79
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 00:40:12 2026 +0530

    README: an FAQ row for /kcd perf

    /kcd perf was in NS.COMMANDS (and /kcd help) but nowhere in the README. One FAQ row names the
    start, finish and report steps and points at bare /kcd perf for the rest.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 499cf1e398c79124751041c341c2f87ed14dca79
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 00:40:12 2026 +0530

    README: an FAQ row for /kcd perf

    /kcd perf was in NS.COMMANDS (and /kcd help) but nowhere in the README. One FAQ row names the
    start, finish and report steps and points at bare /kcd perf for the rest.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 5657d508061ac2da36b392bbd20d732848b0a4ec
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 00:13:29 2026 +0530

    GI-FIN-02: record the 2026-10-02 smoke passes; doc sync

    GRID-15 and GRID-16 (KickCD#9, the ticker owns time) passed in the owner's 2026-10-02 client run
    and leave Pending sign-off. module-map re-measures three peeled files that grew later in the pass
    (none back in the band); ARCHITECTURE names IconGrid's five siblings.

    Gate: 1282 pass / 0 fail / 1 skip; luacheck 0/0 in 127 files; vendor diff empty.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 5657d508061ac2da36b392bbd20d732848b0a4ec
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 2 00:13:29 2026 +0530

    GI-FIN-02: record the 2026-10-02 smoke passes; doc sync

    GRID-15 and GRID-16 (KickCD#9, the ticker owns time) passed in the owner's 2026-10-02 client run
    and leave Pending sign-off. module-map re-measures three peeled files that grew later in the pass
    (none back in the band); ARCHITECTURE names IconGrid's five siblings.

    Gate: 1282 pass / 0 fail / 1 skip; luacheck 0/0 in 127 files; vendor diff empty.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7u34U99DrEPHJTMx6E6u8

commit 1589fb8aee4ee99c919e0a3c66c7fbeeba720d41
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 15:38:14 2026 +0530

    GI-KC-12: split the three sighted CCN>15 functions below 15, behaviour identical

    The functions the re-vendored kit's sighted complexity suite reports above
    CCN 15 (the same set 02a listed at validation time):

      Cooldowns.Refresh (modules/Cooldowns.lua)             46 -> 12
        newPassLog 5, emitState 3, dropSpell 2, withdrawGcd 5, stampGcd 9,
        noteChange 8, logPass 6. The pass log is built only while the console
        listens (the old per-pass locals, now one table, still zero-alloc with
        debug off); MaterialChange, a pure function, is now called only when its
        answer is logged.
      IconGrid.Layout (modules/IconGrid.lua)                29 -> 9
        layoutSettings 10, bindIcons 2, announceLayout 2, warnTruncation 8.
        IconGrid.lua stays out of the layout-§1 band (997 -> 996 lines).
      (anonymous)@764 tests/test_perfsetup.lua, the bracket-leak scan   19 -> 2
        sourceLines 2, noteGuards 4, opensBracket 3, blockLeaks 6, fileLeaks 7.

    Characterization: tests/test_cooldowns_refresh.lua and
    tests/test_icongrid_layout_pass.lua (previous GI-KC-12 commit) green before
    and after. The leak scan, being a test, was characterized by mutation: two
    mutants of Cooldowns:PollSpell's Notes (drop the early-return Note; drop
    both) produce byte-identical failure reports before and after the split.

    Sighted complexity: 3 warnings (max 46) -> 0 warnings (max 15), blindFiles 0,
    bandFiles 0, overCapFiles 0. Totals unchanged: 1282 passed / 1 skipped /
    1283 before and after. luacheck 0/0.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 9787b9e65a40562c57b1db13d8474d3ed6414ed3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 15:32:49 2026 +0530

    GI-KC-12: characterization tests for Cooldowns:Refresh and IconGrid:Layout

    Written and run green against the unsplit functions the sighted complexity
    gate reports above CCN 15 (Cooldowns.Refresh 46, IconGrid.Layout 29), so the
    splits that follow are checked rather than assumed.

    tests/test_cooldowns_refresh.lua (10): the two guards, the vanished-spell
    sentinel and drop=[] (and that a drop alone keeps the (gcd) marker), the exact
    summary line shape and order, the emitted payload, a secret-charges emit with
    no line, no GCD attribution written with the console off, the unchanged
    record's withdrawal rule, the changed record's stamping in every branch, and
    the spellPoll / stateEmit Perf notes.

    tests/test_icongrid_layout_pass.lua (9): the no-grid guard, the per-button
    binding and its order, every config default and pass-through, the empty-list
    size and payload, the laid-out size and payload, the truncation warning's
    dedup / re-arm / clear and its ?/? key.

    The third function, test_perfsetup's leak-scan case (anonymous, CCN 19), is a
    test; its characterization is a mutation run recorded in the refactor commit.

    Totals: 1263 passed / 1 skipped / 1264 -> 1282 passed / 1 skipped / 1283.
    luacheck 0/0. test-cases.md regenerated, README badge.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit e0da04c2131e26fa667fec4f6a972fb017ffeb0d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 15:26:37 2026 +0530

    GI-KC-11: the Spells list renders through H.RenderGrid with no gap (KickCD#10)

    fillRows hands one wide item per entry to H.RenderGrid(ctx, items, scroll,
    { gap = false }) (LibKa0s v1.66.0's parent and opts.gap), instead of its own
    scroll:AddChild loop. Each row is built INTO the full-width group the grid
    hands make (Spells.BuildRow gains an optional `into`), so that group is the
    row: the one child the List layout stacks, ROW_HEIGHT tall, and the frame the
    ReorderList controller is handed. reorder:AddRow runs after RenderGrid
    returns, because the grid adds the group to the scroll after make. A row that
    cannot be built answers false and the grid releases its group. The empty list
    is the grid's one item, the guidance label. renderRows keeps its DoLayout.

    Tests first: tests/test_settings_spells_grid.lua (5 cases). Red against the
    old loop: the RenderGrid call shape, and the empty-list label as the grid's
    item. Green pins carried across: one group per entry with no spacer, the
    controller's frames in list order at exactly ROW_HEIGHT, an unbuilt row
    leaving no blank group. test_settings_spells_editor's rebuildRows helper skips
    the guidance's group (one Label child), which no row is.

    Totals: 1258 passed / 1 skipped / 1259 -> 1263 passed / 1 skipped / 1264.
    luacheck 0/0. Sighted complexity unchanged (3 warnings, blindFiles 0).
    Docs: settings-panel.md, module-map.md 20a, smoke-tests.md SPELLS-13,
    test-cases.md regenerated, README badge.

    Deviation from 02a part B: the row is built into the grid's group rather than
    nested inside it, so the registered group's height is set to ROW_HEIGHT by
    the builder itself and the editor suite's row indices are unchanged.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 5fa1ec8e68f67332e957000f24d3b02cea47a815
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 15:15:43 2026 +0530

    GI-KC-10R: comments describe the KickCD#9 emit contract, not the removed handle re-emit

    Review follow-up to ee541b1. Comment-only: the Refresh 'logged' comment, the
    refreshWithChurnedHandle section header, and two test comments now say handle
    churn produces neither an emit nor a log line (the icon ticker re-fetches the
    handle). Suite totals unchanged: 1258/0/1 before and after.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit ee541b1222412a12676bbf6f04ff1283af8c4b18
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 15:11:17 2026 +0530

    GI-KC-10: the ticker owns time-varying icon render; Cooldowns emits only on material change (KickCD#9)

    Emit = state changed, ticker = time passed.

    - Cooldowns.StateChanged drops the two handle-identity compares and becomes
      MaterialChange plus the conservative emit when either charge count is
      secret. Cooldowns.RechargeHandle(spellID) publishes the existing recharge
      read for the ticker.
    - modules/IconGrid_Ticker.lua: the set becomes _cdIcons (icon -> branch);
      _RegisterCdIcon / _UnregisterCdIcon / _StopCdTicker replace the text-icon
      trio. Icon:StartCooldownTick registers any icon on branch 1 or 2 whatever
      showCooldownText says, and paints the first frame with the same call a
      tick makes (Icon:_PaintCooldown: body alpha/tint curves on branch 1 only,
      GCD-suppression alpha, text). Icon:_TickCooldown re-fetches the handle
      each tick (plain isActive + GetSpellCooldownDuration, or
      Cooldowns.RechargeHandle). Perf bucket name `cdText` kept.
    - Icon:Apply does the state work (branch, swipe arm, first paint, ticker
      registration, glow) only on plainStateMoved or force; otherwise only the
      charges badge. The swipe is armed only there, never per tick.
    - No Lua comparison on any DurationObject getter (landmine test added).

    Two additions beyond 02a, both needed once the emit stops carrying a fresh
    handle:
    - A finished swipe on a still-active spell is re-armed once by the next
      tick (OnCooldownDone sets btn._swipeDone). This covers the GCD ->
      real-cooldown handoff, where an off-GCD interrupt pressed under a GCD
      changes neither isActive nor handle presence, and a recharge rolling onto
      the next charge. Without it the swipe would stop at the GCD's end.
    - On isActive=false the ticker hides the swipe and text but keeps the icon
      registered until Apply takes it to idle, so a recast inside
      SPELL_UPDATE_COOLDOWN's lag (Cooldowns sees active -> active, no emit)
      re-arms instead of leaving a blank icon. 02a's "unregister" became
      "stay registered in an ended state".

    Tests first, red against the old code (12 failing): test_cooldowns_gates
    (identity no longer emits), test_cooldowns (one emit across polls of an
    unchanged cooldown, isActive flip emits, secret charges emit every poll),
    test_icongrid_apply (swipe armed only on state work, steady payload touches
    only the badge), test_icongrid_render (ticked with text off, no per-tick
    re-arm, ended hide, recast re-arm, OnCooldownDone re-arm, branch 2 leaves
    the body alone, landmine handle), test_icongrid_curves (GCD -> real CD
    dims and tints by ticks alone). Suite 1246/0/1 -> 1258/0/1.

    tests/perf.lua: iconApply steady state 848.0 -> 0.0 bytes/iter (ceiling
    re-baselined 900 -> 32 with the three-line record); spellState 1696.6 ->
    1.5; new cdText scenario asserts 2 API calls per tick.

    Docs: midnight-quirks (the forced emit rate is history), data-flow,
    module-map, ARCHITECTURE, performance, message-bus, icon-grid, testing,
    debug, slash-dispatch, smoke-tests GRID-15/16 + pending rows, test-cases
    regenerated, README badge 1258/1258.

    luacheck 0/0. Sighted complexity unchanged: 3 warnings, all pre-existing
    (Cooldowns.Refresh 46, IconGrid.Layout 29, test_perfsetup anon 19; GI-KC-12).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 442dab84b69c9e751fc14549748dd63ed216a840
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:50:17 2026 +0530

    GI-KC-01R + GI-KC-02R + GI-KC-04R + GI-KC-05R: comments cite the files the peels moved symbols to

    shouldBeVisible -> IconGrid_Visibility.lua, ApplyLock -> IconGrid_Handle.lua, the cooldown
    ticker -> IconGrid_Ticker.lua (renderer stays in IconGrid_Render.lua), ApplyAnchor ->
    Castbar_Frame.lua, the migration ladder -> Database_Migrations.lua; PerfSetup drops a stale
    line number. Comment-only.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 071f93a63d44f08efbc88988c4974b4e8cb3f971
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:42:58 2026 +0530

    GI-KC-07R: re-point five citations to tests/test_slash_degraded.lua

    GI-KC-07 moved the disabled-state and degraded-stub cases out of
    tests/test_slash.lua but left five pointers naming the old file:
    core/KickCD.lua (enable/disable stay live while disabled; FEATURE_VERBS
    vs the live gate), settings/Slash.lua and tests/test_locale.lua (the
    stub's DisabledLine library constant), and docs/slash-dispatch.md's
    enable/disable row. Comment- and doc-only; suite totals unchanged
    (1246 passed, 0 failed, 1 skipped, 1247 total).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 63ecea251c98a6a6b26c2729e0653b9c96a1e5a4
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:35:59 2026 +0530

    GI-KC-RVR: DEPENDENCIES.md names the sighted complexity runner, not raw lizard

    The "Am I set up correctly?" block still gave the raw blind
    `lizard -l lua -x ...` command as "the `complexity` suite", which
    contradicted docs/performance.md:236 and docs/testing.md after GI-KC-RV.
    It now gives `bash tests/_kit/run-automated-tests.sh --suite complexity`
    (the sighted suite, kit 35). Docs only; suite totals unchanged
    (1246 passed, 0 failed, 1 skipped, 1247 total), luacheck 0/0, complexity
    verdict green.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 7bc51bc3f2268b0a9588ab25832e87b4a48589fa
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:27:25 2026 +0530

    GI-KC-09: split test_perfsetup.lua's suspend/resume and library-absent cases to test_perfsetup_latch.lua (1021 -> 868)

    Test-only move, no case added, removed or renamed (KickCD#32).

    tests/test_perfsetup_latch.lua (166, 7 cases): the "suspend / resume"
    section (the latch as step 0, cast filters disarmed, no re-registration
    mid-capture, resume from current state, the session-only suspended flag)
    and the "degraded path" section (the probe stub answers every member, the
    bracketed paths still run). Every moved case builds its own instance with
    T.load and uses none of the suite's helpers. The L-trap case
    (docs/testing.md names it here) and firstWatchedSpell with its luacheck
    suppression (docs/common-tasks.md cites it) stay in test_perfsetup.lua.
    Registered in SUITES directly after test_perfsetup.

    docs/test-cases.md regenerated (sorted name list identical). module-map's
    band table is now empty: no authored file is in the 1000-1500 band (the
    largest is modules/IconGrid.lua at 996).

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (123 -> 124 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 410a61ed38bdeaca574bfc5a36dc2a17bcc11ebf
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:24:56 2026 +0530

    GI-KC-08: split test_options_panel.lua's degraded-stub and linked-Focus cases to test_options_panel_degraded.lua (1101 -> 742)

    Test-only move, no case added, removed or renamed (KickCD#31).

    tests/test_options_panel_degraded.lua (371, 9 cases): the "degraded path"
    section (the library-absent schema fingerprint, the hollow composers' CLI
    reach, the stub's global reset, the stub's no-panel line), the three
    linked-Focus cases (no hover highlight, opens General on Units, full strip
    inert with only the link note) with their SCHEMA_WIDGET_TYPES local, the
    Focus link tick / Copy button row case, and the stub's no-widget-maker
    source scan. None reads the suite's shared helpers (renderRow, panelSeq,
    the page tables); the degraded cases build their own instances. The L trap
    cases stay in test_options_panel.lua (docs/testing.md names it there), as
    does the reader / stored-FALSE case ARCHITECTURE.md pins. Registered in
    SUITES directly after test_options_panel.

    docs/test-cases.md regenerated (sorted name list identical). Every pointer
    to a moved case re-pointed: ARCHITECTURE's options-ui-§1 deviation rows,
    settings-panel.md, testing.md, slash-dispatch.md, comments in
    settings/OptionsSetup.lua, settings/Panel_Render.lua and
    tests/test_surface_parity.lua. module-map band table row removed.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (122 -> 123 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 411eab8f83a1a92def0a2a813ba98dcfacda6742
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:21:08 2026 +0530

    GI-KC-07: split test_slash.lua's disabled-state and degraded-stub cases to test_slash_degraded.lua (1054 -> 719)

    Test-only move, no case added, removed or renamed (KickCD#30).

    tests/test_slash_degraded.lua (361, 18 cases): the "disabled state
    (slash-commands-§2)" section (disabled(), say(), LIVE and its seven cases)
    and the "degraded stub's contract" section (degraded(), degradedRun(),
    ABSENT and its eleven cases). Every moved case builds its own instance with
    T.load, so none depended on suite order. test_slash.lua keeps its own copy
    of the small say() capture helper, which the `/kcd get` bool case and the
    `/kcd spells add` cases still use. Registered in tests/run.lua's SUITES
    directly after test_slash.

    docs/test-cases.md regenerated (the 18 names move between headings; the
    sorted name list is identical). docs/slash-dispatch.md's four pins re-pointed
    to the new file where their case moved; module-map band table row removed.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after (test_slash 60 -> 42 + test_slash_degraded 18). luacheck 0/0
    (121 -> 122 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 252fdc034847363fa7882f90522efe3cda038d64
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:18:10 2026 +0530

    GI-KC-06: peel the Spells page's chrome-block builders to settings/Spells_Header.lua (1115 -> 914)

    Pure move, no behaviour change (KickCD#28), mirroring Spells_Rows.lua.

    settings/Spells_Header.lua (254): CLASS_DISPLAY_OVERRIDES, titleCaseToken,
    classDisplayName, classColorHex, classIconMarkup, the spec-icon cache,
    specIconMarkup, buildSpecEntries and buildSpellsHeader, published as
    Spells.BuildHeader (renderRows calls it at render time) with the
    TitleCaseToken / ClassDisplayName test exports.

    The page's file-locals reach it through Spells.__headerDeps, filled at
    Spells.lua's file end and read at call time through forwarders (sortedKeys,
    specOrder, currentSpellIds, addFromBox, ADD_STRINGS, HEADER_ROW_GAP). The
    page's mutable state is not copied: buildSpellsHeader reads the selection
    through the existing Spells:GetSelection, writes it through
    __headerDeps.setSelection, and appends to the header-widget list
    __headerDeps.newHeaderWidgets() creates on the page, which
    releaseAceGUITree still releases. Those three lines are the only edits
    inside the moved bodies.

    KickCD.toc: after Spells_Rows.lua under the LOAD-BEARING note (which now
    names both siblings). tests/test_locale.lua's two CLIENT SUPPLIED residue
    rows ("Death Knight", "Demon Hunter") follow the literals to the new file
    (same rows, same case count).

    Docs: module-map (tree, new 20b, band table row removed), ARCHITECTURE
    (subsystem table, load order, the spell-list writer note).

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (120 -> 121 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 2dcf7308f982a3c8306395343af85cfb69e22e34
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:13:51 2026 +0530

    GI-KC-05: peel core/Database.lua's migrations to core/Database_Migrations.lua (1121 -> 758)

    Pure move, no behaviour change (KickCD#29).

    core/Database_Migrations.lua (394): the "Profile migration" section whole --
    LEGACY_TOPLEVEL / foldAnchors / FoldLegacyUnits, BackfillLabelStyle, the
    spec-key helpers and MigrateSpecKeys, the color-shape helpers and
    MigrateColorShape, MigrateFontFlags, the `migrations` ladder,
    reportMigrationFailure and MigrateProfile -- kept together so the runner and
    its steps read in one place. They are defined on NS.Database, which
    Database.lua creates, so the file sits directly after it in the TOC under a
    LOAD-BEARING note. It reads Database.CURRENT_DB_VERSION (already published)
    and the deep copy, now published as Database._copy rather than duplicated.
    Init and OnProfileChanged still call the migrators as methods at run time.

    .luacheckrc: the 212/self entry for MigrateColorShape / MigrateFontFlags
    moves from core/Database.lua (which no longer needs it) to the new file.

    Docs: module-map (tree, item 8, new 8a, band table row removed),
    ARCHITECTURE (subsystem table, load order), debug.md's Init / Migrate tag
    homes.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (119 -> 120 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 5b51f60ed9ecbce9708b6069f795ad40b2680ccb
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:10:57 2026 +0530

    GI-KC-04: peel Castbar's lock/drag/anchor code and EnsureFrame to Castbar_Frame.lua (1251 -> 949)

    Pure move, no behaviour change (KickCD#24, the second peel after
    Castbar_Events in 99211f0).

    modules/Castbar_Frame.lua (347): dragAllowed, onDragStart, saveAnchor,
    onDragStop, SETPOINT_MAP / toSetPoint, Castbar:ApplyAnchor, Castbar:ApplyLock
    and Castbar:EnsureFrame, with the DragAllowed / SaveAnchor / ToSetPoint
    exports. Helpers come off the module table at load (Cfg, ResolveGridFrame,
    IsVisible, and two new exports from Castbar.lua: ResolvePrimaryIcon and
    _OnUpdate, the per-frame loop EnsureFrame wraps once per instance; it is
    defined by the time this file loads, so the wrapped function is the same).
    Castbar.BuildHandle is still read when EnsureFrame runs.

    KickCD.toc: directly after Castbar.lua in the LOAD-BEARING block (note now
    names all five siblings). test_castbar_skin's existing LOC case lists the new
    file (same case, no count change). .luacheckrc gives it the 212/self entry
    Castbar.lua has (ApplyAnchor moved with its receiver). Stale comments in
    Castbar.lua's header / forward declaration and Castbar_Handle.lua re-pointed.

    Docs: module-map (tree, item 15, new 15a, Handle renumbered 15aa, band table
    row removed), ARCHITECTURE (drag-stop writer, load order), castbar.md's
    SETPOINT_MAP home.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (118 -> 119 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit ec383aa4d2b46f467e63dbff157b9134686fd156
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:07:10 2026 +0530

    GI-KC-03: peel the mock's frame model to tests/wow_mock_frames.lua (1233 -> 834)

    Pure move, no behaviour change (KickCD#27).

    tests/wow_mock_frames.lua (418): NUMERIC_GETTERS, recordPoint, the
    FRAME_METHODS table and every method on it, createRegion, recordHook,
    refuseUnknown and makeFrame. It returns { makeFrame, FRAME_METHODS,
    recordHook }; wow_mock.lua loads it with
    assert(loadfile(root .. "/tests/wow_mock_frames.lua"))(root), the same
    root-relative loadfile-and-call the runner uses for wow_mock.lua itself.
    recordHook is exported because build() writes the same HookScript ledger
    for the AceGUI widgets it wraps. The C_Timer queue, AceDB and the build()
    body stay in wow_mock.lua. Not a suite, so not in SUITES; luacheck covers it
    as part of tests/.

    Docs: testing.md's mock layout, common-tasks' linted-files list, module-map
    band table row removed; one test comment re-pointed.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (117 -> 118 files). tests/perf.lua runs clean.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit ef899835843bcb76605dd9c9f7aa30b58edb15a5
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:03:30 2026 +0530

    GI-KC-02: peel IconGrid_Render's cooldown-text ticker to IconGrid_Ticker.lua (1014 -> 859)

    Pure move, no behaviour change (KickCD#26). Named IconGrid_Ticker rather
    than the issue's IconGrid_Text because KickCD#9 (GI-KC-10) makes it the
    ticker that owns an icon's whole time-varying render.

    modules/IconGrid_Ticker.lua (182): the _textIcons / _textTicker locals, the
    SetFormattedText rationale, Icon:StartCooldownText / StopCooldownText /
    _RenderCooldownText (defined on the IconGrid.Icon prototype the render file
    publishes; Mixin copies it at widget creation, after load), and the shared
    ticker block (_tickAllTextIcons, IconGrid:_RegisterTextIcon /
    _StopTextTicker / _UnregisterTextIcon). The cdText Perf bracket moves with it.

    KickCD.toc: after IconGrid_Render.lua under the LOAD-BEARING note, and named
    in the PerfSetup note. test_perfsetup's three bracketed-file lists name it.
    .luacheckrc's 212/self entry for the two text-icon methods moves from
    IconGrid_Render.lua (which no longer needs it) to IconGrid_Ticker.lua.

    Docs: module-map (tree, items 14 and new 14a, Visibility/Handle renumbered
    14b/14c, band table row removed), ARCHITECTURE load order, the mock's
    NewTicker comment.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (116 -> 117 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 04056dfa8a468b6fbc5c8a1bf8099993c917aecd
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 14:00:22 2026 +0530

    GI-KC-01: peel IconGrid's visibility gate, glow gate and drag strip (1420 -> 996)

    Pure move, no behaviour change (KickCD#25).

    modules/IconGrid_Visibility.lua (288): visibilityMode, shouldBeVisible,
    ApplyInterruptibilityMask, IconGrid:RefreshVisibility, OnUnitCastEvent,
    OnTargetChanged, OnFocusChanged and the glow gate (resolveInterruptible,
    gateMoved, logGateChange, RefreshAllGlows), with the VisibilityMode /
    ShouldBeVisible test exports.

    modules/IconGrid_Handle.lua (200), mirroring Castbar_Handle: handleText,
    anchorHandle, buildHandle (published as IconGrid._BuildHandle for EnsureGrid)
    and IconGrid:ApplyLock.

    IconGrid.lua keeps instanceCasting / isEnabled (exported as before), the
    lifecycle, ICON_CAST_ROUTES and onDragStart/onDragStop, and publishes
    IconGrid._instances and IconGrid._OnDragStop, which the siblings read at
    file load. Both siblings sit in KickCD.toc's LOAD-BEARING block after
    IconGrid.lua; Visibility is named in the PerfSetup note and added to
    test_perfsetup's three bracketed-file lists (its visibility / castEvent /
    glowGate brackets moved with it). .luacheckrc gives both files the same
    212/self entry IconGrid.lua has, for the moved methods.

    Docs: module-map (tree, item 12, new 14a/14b, band table row removed),
    ARCHITECTURE (subsystem table, load order), debug.md tag homes,
    midnight-quirks' mask pointer.

    Suite totals identical: 1246 passed / 0 failed / 1 skipped (1247) before
    and after. luacheck 0/0 (114 -> 116 files).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 3901b388ae753b390e93fa5b37a39088838733a0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 13:54:08 2026 +0530

    GI-KC-RV: re-vendor LibKa0s v1.66.0 (kit 35), wire test_lizard_sighted, record sighted complexity

    Whole-folder copy of libs/LibKa0s/ and tests/_kit/ from the local tag v1.66.0
    (e4c5ef7): SlashParse, WidgetsReorder, PerfSampler and PerfCommands added (the
    TOC loads LibKa0s.xml, so no TOC line), kit 34 -> 35 with lizard_sighted.lua and
    test_lizard_sighted.lua. diff -r of both folders against the tag is empty.
    Provenance line and docs/testing.md's version-now line roll to v1.66.0.

    tests/run.lua declares { name='test_lizard_sighted', dir='tests/_kit/' }. The
    complexity rows in docs/testing.md and docs/performance.md name the runner's
    suite instead of the raw (blind) lizard command; CLAUDE.md's gate line quotes
    no lizard. No consumer test broke from a library change.

    Sighted parity named one blind file, tests/test_icongrid_curves.lua (three
    function literals in a for-in header); hoisted to a local, same case.

    Frozen bundles: docs/revendor/2026-10-01-v1.66.0/ (candidates listed, not
    interviewed, per spec S4) and the span back-fill 2026-10-01-v1.64.0-v1.65.0/.

    Tests: 1238 passed / 0 failed / 1 skipped (1239) before; 1246 / 0 / 1 (1247)
    after (+8 kit cases). luacheck 0/0 in 114 files.
    Sighted complexity (run-automated-tests.sh --suite complexity): pass,
    maxCcn 46, warnings 3 (Cooldowns.Refresh 46, IconGrid.Layout 29,
    tests/test_perfsetup.lua:916 anonymous 19; left for GI-KC-12), blindFiles 0
    (1 before the hoist), 3374 functions.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Ng9STmzmM1JYwT2WWSakpL

commit 5277432433927599f8ef6d10d1cc7701118a6943
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:38:25 2026 +0530

    DG-KC-01R: the Clear re-arm case drives all four gates, the cast gate and the cast outcome included

    The case named four console gates but ran only the list and rebuild ones. It now
    runs a secret-flag RefreshAllGlows pass and a Castbar Start/Stop too, and pins
    each line once before a Clear, once after, and quiet on the pass after that.
    Checked red with each of the two new gates put back on a hand-rolled memo.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 5277432433927599f8ef6d10d1cc7701118a6943
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:38:25 2026 +0530

    DG-KC-01R: the Clear re-arm case drives all four gates, the cast gate and the cast outcome included

    The case named four console gates but ran only the list and rebuild ones. It now
    runs a secret-flag RefreshAllGlows pass and a Castbar Start/Stop too, and pins
    each line once before a Clear, once after, and quiet on the pass after that.
    Checked red with each of the two new gates put back on a hand-rolled memo.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit c8eaa99b130280e2a702b60580e8171a53c539d9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:27:56 2026 +0530

    DG-KC-01: adopt: smoke rows for the library's own lines; module map names the sinks

    DIAG-41 (a Slash refusal in the console), DIAG-42 (a Lifecycle edge),
    DIAG-43 (state lines at the first enable) and DIAG-44 (Clear re-arming the
    change gates), in the doc's own shape, with their Pending sign-off row and
    the index range. docs/module-map.md's DebugLog, Launcher, Lifecycle and
    Slash entries say which sink each descriptor is passed and which lines are
    the library's.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 1607b93620df96b92220b034c44d4e3afd41cdaa
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:23:35 2026 +0530

    DG-KC-01: adopt the combat lock's refusal lines on the Grid page's own seams

    The Options descriptor already passed `debug`, so the library's combat-lock
    refusals (Options minor 27) land as they are. The Grid page's two host
    seams that ask the lock, SelectSection and RestoreGridSection, now name
    their act (`section <key>`, `defaults grid/<entry>`) instead of the
    anonymous `change`. The grid combat case pins both lines, once per act;
    docs/debug.md's Cfg rows say what the library writes.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit d4e19c2254e48cc7ba169a2d796f791f332a5371
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:21:11 2026 +0530

    DG-KC-01: adopt the at-enable queue for the dependency and launcher state lines

    The Launcher descriptor takes `debugAtEnable` (Launcher minor 5), so
    `registered` and a missing broker library land the first time logging is
    turned on instead of being gated off at OnEnable. The [Init] summary's
    `, missing <names>` clause, the host's workaround for the same gap, is
    deleted: LibCustomGlow-1.0 and LibSharedMedia-3.0 are one D.DebugAtEnable
    line each, written at load, and the broker pair is the launcher's own line,
    so each missing library is named once. Tests pin both landing after the
    first enable and not repeating on a second; docs/debug.md follows.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 31180f369987b2ba374a1930088b0a7ab702d769
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:14:09 2026 +0530

    DG-KC-01: adopt the console's change gates for the list signatures

    The four hand-rolled "log on change" gates go through the console's
    D.DebugChanged (LibKa0s v1.65.0 DebugLogGates): Cooldowns' rebuild
    signature (_lastRebuildSig), IconGrid's per-unit list signature
    (lastListSig) and cast-gate label (lastCastLabel), and Castbar's per-unit
    cast outcome (lastOutcome). The line is the signature, a unit disabled
    forgets its key, and a Clear or a fresh enable re-arms every gate, which
    the copies never were. A new flow-trace case pins the re-arm; docs/debug.md
    says the gates are the console's.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit f320f9a2c96150c047b76b3a83a394ca779871df
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 01:09:06 2026 +0530

    DG-KC-01: adopt Slash and Lifecycle debug sinks; drop the host's stand-down lines

    The Slash and Lifecycle descriptors take the host's gated sink as `debug`
    (LibKa0s v1.65.0: Slash minor 18, Lifecycle minor 3), so the dispatcher's
    own refusals land as `[Cmd] refused <verb>: <guard>` and each stand-down /
    stand-up edge as one `[Lifecycle]` line naming the hold. core/LifecycleSetup
    .lua's logEdge and its `[State]` edge lines are deleted, so an edge is one
    line, not two. tests/test_library_lines.lua pins the library's lines landing
    in this console, once each, and silent with logging off; docs/debug.md's tag
    table and Coverage name the four tags that are the library's.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit fa8aeadd286fb5d573910216af93af8552f44fe0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 1 00:57:04 2026 +0530

    DG-KC-01: re-vendor LibKa0s v1.65.0 (kit 34); DebugLog stub gains the gate members

    Whole-folder copy of libs/LibKa0s/ and tests/_kit/ from the local tag v1.65.0
    (DebugLogGates.lua added; the kit is unchanged at revision 34). The DebugLog
    degradation stub answers DebugOnce, DebugChanged, DebugForget and
    DebugAtEnable, which the surface-parity case reads off the live instance.
    Provenance line, docs/testing.md's checkout note and docs/debug.md's api
    link roll to v1.65.0.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 8956c0d10ac84fccd3555f14c5a8d32a76101a37
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 21:54:20 2026 +0530

    DL-KC-05: module-map names the console's 3000-line buffer and its resize grips

    core/DebugLogSetup.lua's entry still called the console buffer 1500 lines;
    the vendored DebugLog sets lib.MAX_BUFFER = 3000, and since minor 15 the
    console and the copy window both carry a session-only resize grip
    (Core.MakeResizable). Doc sync only.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 8956c0d10ac84fccd3555f14c5a8d32a76101a37
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 21:54:20 2026 +0530

    DL-KC-05: module-map names the console's 3000-line buffer and its resize grips

    core/DebugLogSetup.lua's entry still called the console buffer 1500 lines;
    the vendored DebugLog sets lib.MAX_BUFFER = 3000, and since minor 15 the
    console and the copy window both carry a session-only resize grip
    (Core.MakeResizable). Doc sync only.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 7a0cdf3307df37cba004ae47130dcbe764353e7a
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 21:19:23 2026 +0530

    DL-KC-04: README uses bullets, never numbered lists (standard v2.72.0 documentation-§1)

    Usage's four setup steps and Reporting a bug's three steps become '- '
    bullets; the setup intro says 'in this order' so the words carry the order
    the numbers did. Reporting a bug now matches the v2.72.0 fixed body with /kcd.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 5e740f343892634d06e4ae4fa5f09352fb5f2a96
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 20:22:28 2026 +0530

    DL-KC-03R: keep README's Reporting a bug section as the standard fixes it (no added sentences)

    documentation-§1 item 9: nothing is added to the section. The enable and the
    link are stated in docs/debug.md and the smoke rows.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 19d25379e1a18f29b78861c6c6674094d6595afb
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 20:16:48 2026 +0530

    DL-KC-03R: add DIAG-39 and DIAG-40 to the re-vendor smoke list

    The "LibKa0s re-vendor, or a seam file" list in docs/smoke-tests.md now
    reads DIAG-16 – 40, so a re-vendor's smoke pass covers the Diagnostics
    link and diagnostics turning logging on, both drawn by the library.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit a5989be9f5d7870dc00f7918583d71d506b334af
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 20:11:22 2026 +0530

    DL-KC-03: re-vendor the final LibKa0s v1.64.0 (kit 34); diagnostics turns logging on for the session

    Both payloads copied whole from the local tag v1.64.0: DebugLog 16 -> 17
    and DebugLogDiagnostics 1 -> 2, whose RunDiagnostics() calls
    SetEnabled(true) before it writes when logging is off (standard v2.71.0,
    debug-logging-§14). The console's Diagnostics link runs the same function.
    Kit revision 34 rewrites the contract case to "turns it on for the session"
    and adds the opt-out case (skipped here: KickCD keeps the default) and the
    already-on case. CLAUDE.md provenance stays v1.64.0.

    The standards reference needs no stamp: the TOC X-Standard, README badge
    and CLAUDE.md follow the standard's versionless templates.

    tests/test_diagnostics.lua: the /kcd diagnostics chat case now expects the
    seam's "debug logging ON" line ahead of the count line and the flag on
    afterwards, and a second run with logging on prints the count line alone.

    docs/debug.md says a run (either form or the link) turns logging on for the
    session and a /reload turns it off; its DebugLog api citation re-pointed to
    version-17.2. README's Reporting a bug, docs/testing.md and
    docs/slash-dispatch.md match. docs/smoke-tests.md corrects DIAG-30 (the
    header reads Debug: ON after the run) and adds DIAG-39 (the orange
    Diagnostics link) and DIAG-40 (diagnostics turns logging on for the
    session, /reload turns it off), all under Pending sign-off.
    docs/test-cases.md regenerated (1230 cases, 1 skipped); badge 1229/1229.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 0cb364dcef690a7de78c2eacc7681c616bdec420
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 17:32:22 2026 +0530

    DL-KC-02R: re-point the NS.COMMANDS citation in common-tasks to core/KickCD.lua:374

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit ad887ed3478b2bda8c8fd8dc326f4e5fddc751a0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 17:23:51 2026 +0530

    DL-KC-02R: /kcd debug and settings-verb refusals reach the log

    The unknown /kcd debug subcommand, the debug topics whose module is
    missing, and the list/get/set/profile "settings layer not ready" guards
    now log through refuse(), like the sibling reset and lock guards.
    docs/debug.md gains a Debug tag row and a coverage row, and lists the
    DebugLog-missing refusals (no sink to write to) as deliberately not logged.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit dc9f03d35d52724493e0e531db9fe5f84d3f7540
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 17:14:37 2026 +0530

    DL-KC-02R: a /kcd reset given a retired page word names the redirect

    settings/Slash.lua's runReset is host code, so its two redirects (reset
    spells, and the five retired page names) are host refusals: one gated [Set]
    line names the word. Pinned in the refusal case of tests/test_flow_traces.lua;
    docs/debug.md's Set row lists the file.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 5c19b749928bb0c1a93c4101abdbf0106a9e6e02
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 17:11:02 2026 +0530

    DL-KC-02R: top-level host verb refusals name their guard too

    refuse() moves up beside p() and takes a tag, so the host's own top-level
    refusals (/kcd lock, unlock, reset, resetall, resetposition with the db or
    the settings layer not ready) log one gated [Set] line naming the guard, as
    the /kcd spells verbs do on [Spells]. The refusal case in
    tests/test_flow_traces.lua pins the lock line; docs/debug.md's Set rows say so.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 6a95be91a6ec63e42e7435497e43c01c526e4775
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 17:05:51 2026 +0530

    DL-KC-02R: refusals and caught errors reach the log, logEdge keeps its own doc

    - core/LifecycleSetup.lua: logEdge and its comment move above eachModule's
      docblock, so each function keeps its own comment.
    - core/SpellInput.lua: the Cooldown Manager walk keeps each distinct caught
      error with its site (GetCooldownViewerCategorySet / ...CooldownInfo), up to
      three plus a +N count, and the one build line names them; nothing is kept
      with the flag off.
    - settings/Panel_Widgets.lua: a link click that raises writes a gated
      [Open] line naming the site and the error, beside the chat line; its
      literal gets a DIAGNOSTIC residue row in tests/test_locale.lua.
    - core/Database.lua: every spell-list writer refusal (add: no spellID,
      unknown class, no list; remove/enable/disable/category: not in the list or
      no list; move: no list, non-number index, out of range, same position;
      reset: no list) logs one gated [Spells] line naming the guard, shared by
      the Spells page and /kcd spells.
    - core/KickCD.lua: /kcd spells refusals the verb owns (parse, usage, no
      list, unknown category or subcommand, class/spec unresolved, db not
      ready) log one gated [Spells] line through refuse().
    - tests: the CM walk case asserts the site and message; new cases for the
      link-click error and the refusal lines; the "writes nothing traces
      nothing" case now pins one refusal line per refused verb. Inventory and
      badge 1226 -> 1228; docs/debug.md tag table and Coverage updated.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 252c38cbffcb513e66a11bb44aa300f5ac2bb16a
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 16:43:43 2026 +0530

    DL-KC-02: debug coverage audit and fill (debug-logging-§8 diagnosis, §9 quiet steady state)

    Fill the gaps the 060 audit found against debug-logging v2.70.0:

    - [State] stand-down (naming the holds) and stand-up edges, from the
      latch's standDown/standUp (core/LifecycleSetup.lua).
    - [IconGrid]/[Castbar] per-unit enable and disable edges.
    - [IconGrid] one change-gated list summary per unit per rebuild: drawn,
      not-castable and duplicate IDs, or why no list was read. Replaces the
      per-duplicate line (debug-logging-§9).
    - [Castbar] the cast outcome, change-gated per unit: shown, suppressed by
      the visibility mode, or skipped for no duration object.
    - [Cooldowns] a rebuild that watched nothing says why, change-gated on
      the rebuild signature.
    - [Open] a settings open refused in combat or with no options layer.
    - [Spells] the cooldown-manager set's build line (size, viewer calls that
      raised) and an add the cooldown-manager gate refused; two Spells lines
      now pass their arguments to the sink instead of pre-formatting.
    - [Init] names an optional library that did not load.

    Tests pin each line with a red-under comment, plus quiet-steady-state
    cases for the list summary, the cast outcome, the rebuild skip and
    Cooldowns:Refresh. docs/debug.md gains a Coverage section; the tag
    table, test inventory and badge follow (1216 -> 1226).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit ffe7a1a80a17a75744fd7692cfb86cc8c31a3f81
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 16:07:51 2026 +0530

    DL-KC-01: re-vendor LibKa0s v1.64.0 (kit revision 33), resize smoke checks

    Copies libs/LibKa0s/ and tests/_kit/ whole from the local tag v1.64.0
    (Core 9 MakeResizable, DebugLog 15.1, Widgets 11.3, PerfPanel 6; the kit
    gains mock_resize.lua) and rolls the CLAUDE.md provenance line and the
    testing.md vendor-state stamp with it. The three-place standards reference
    carries no version, so v2.70.0 needs no edit there. No test fallout: no
    by-name Core parity stub, no host assertion on the resize surface.

    docs/smoke-tests.md gains DIAG-34 - 38 (console resize, session-only size,
    two consoles independent, copy window, perf panel width only), listed in
    the index, the partial-change lists and Pending sign-off.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit f69d967bf5c31030eeca1c149a968f9ad1b9d24f
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 08:52:12 2026 +0530

    SP-FIN-01: re-vendor the test kit at revision 32 (LibKa0s v1.63.0, re-cut)

    LibKa0s folded kit revision 32 into the unpublished v1.63.0: tests/_kit/README.md now counts eleven
    consumers and thirteen copies, and Kit.VERSION is 32. Prose and the revision integer only; no code,
    case or mock changes. tests/_kit/ is byte-identical to the tag again (diff -r empty), so the
    vendor-sync case stays green.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit f69d967bf5c31030eeca1c149a968f9ad1b9d24f
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 08:52:12 2026 +0530

    SP-FIN-01: re-vendor the test kit at revision 32 (LibKa0s v1.63.0, re-cut)

    LibKa0s folded kit revision 32 into the unpublished v1.63.0: tests/_kit/README.md now counts eleven
    consumers and thirteen copies, and Kit.VERSION is 32. Prose and the revision integer only; no code,
    case or mock changes. tests/_kit/ is byte-identical to the tag again (diff -r empty), so the
    vendor-sync case stays green.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 2312d755af6d430ad6f456b04b7078e13931b0d9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 08:12:15 2026 +0530

    SP-FIN-01: point the text-icon comment at IconGrid:_RegisterTextIcon, the ticker's real starter

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 17ed9ce5827cea4a201d7b69c296f478be607500
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Sep 30 01:40:18 2026 +0530

    SP-FIN-01: sync docs (four-page panel, debug sub-verbs, settings load order, git gate evidence)

    Content sync after the smoke-and-profile branch; no structure changed.

    - ARCHITECTURE.md: the settings panel is four pages (General, Grid, Spells,
      Profiles), not six; the settings module-map row names Grid.lua and
      Spells_Rows.lua; thirty-six files write `local _, NS = ...` (44 loaded,
      8 read the folder name), not thirty-three; the /kcd debug sub-verb list
      gains `diagnostics` in table order and says the bare verb also prints
      the list; load order names LibKa0s and AceGUI-3.0-SharedMediaWidgets in
      libs/, opens the settings block with SchemaSetup.lua, and lists Grid.lua
      and Spells_Rows.lua in TOC order.
    - settings-panel.md, slash-dispatch.md: "six pages" -> four, Defaults
      button on General / Grid / Spells.
    - module-map.md: libs/ load-order row names every vendored library;
      tests/test_slash.lua re-measured at 1054 lines (was 1035) in the
      1000-1500 band table.
    - DEPENDENCIES.md: git is needed inside the green gate itself (three
      suites read `git ls-files`), and test_doc_structure.lua also shells to ls.

    Gate: 1216 passed / 0 failed; luacheck 0/0 in 113 files. Test count
    unchanged, so docs/test-cases.md and the README badge are untouched.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 28fe6a95be73b53d99b543397cc77714bf3f12a0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 23:54:07 2026 +0530

    SP-KC-03R: restore the per-page Defaults scope check, fix STATE-15's title

    Old §12 L362 said each panel's Defaults (General / Icons / Cast bar) resets
    only that panel, leaving the others and the spell list untouched. PANEL-17
    covers the Cast bar entry only; PANEL-29 restores the General and Icons
    halves, with echoes checked against the rows' fmt, and is listed under
    Pending sign-off. STATE-15's bold now closes after "(the default)".

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 6c57b0f5e599cfed6ffa6a25871307db1815faed
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 23:33:41 2026 +0530

    SP-KC-03R: set Free before the DEGRADED rename, restore the em-dash separator wording

    DEGRADED-12 needs the Target cast bar in Free mode, but the degraded /kcd set
    writes only enabled and locked and the panel does not open, so the anchor mode
    must be set before libs/LibKa0s is renamed. DEGRADED-5 again says "no em-dash
    separator": seven COMMANDS descriptions carry their own em dash.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 1f8c55c86ae5393d7cf4e3ad4b3860ceab69cd58
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 23:16:25 2026 +0530

    SP-KC-03R: match COMBAT-3 to the combat cover, make COMBAT-5 reachable

    COMBAT-3 expected each sidebar page to print the library's refusal and close
    the Settings window; since Options minor 22 a page shown in combat is covered,
    the window stays open, and the gray locked notice prints once per combat.
    COMBAT-5 asked for a click on the linked note in combat, which the cover
    blocks; it now checks that the cover takes the click and nothing opens.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 465ab582b803d32350e8df0ad9dbe542e1c62db2
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 23:01:27 2026 +0530

    SP-KC-03R: list DIAG-28 and DIAG-30's unrun halves under Pending sign-off

    The 2026-09-26 diagnostics run recorded only part of each: KC-S2 and KC-S4
    cover DIAG-28's kept trace and clean Copy, KC-S5 covers DIAG-30's full
    report and Debug: OFF header. The console opening, the chat count line,
    the agreeing counts and the untraced target change have no result, so both
    checks move off the signed list and get rows for their unrun halves.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 27512ec591c51ef050ec9fc6f9203b9cdeb47c17
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 22:49:38 2026 +0530

    SP-KC-03R: sign the X1.4 minimap pass, unlock before FOCUS-2's enable

    The 2026-09-25 collection-wide minimap re-run (2026-09-23 plan, X1.4)
    passed left-click opening settings, right-click opening the options menu
    and the status tooltip in every addon. INSTALL-11 is now signed, and
    INSTALL-12 and STATE-9 are listed for their unrun halves only.

    FOCUS-2 now unlocks before enabling Focus: a locked cast bar hides
    whenever no cast is live, so the bar only shows as its placeholder.
    FOCUS-3 locks again, since unlocked bypasses visibility.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 6c8387181fe4ab4db27d96b48d4ca2d31f4041cb
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 22:33:47 2026 +0530

    SP-KC-03R: re-verify smoke strings, apply the Pending policy, restore three halves

    The review of the smoke rewrite found three halves of old checks lost, two
    coverage-map gaps and a broken PANEL-18 sentence. Spec S4's clarified
    Pending sign-off rule also applies to the whole doc now.

    - SLASH-10 drags a Free Target cast bar before /kcd resetall and checks it
      comes back to its default anchor (CENTER/CENTER, y = +120) once Free is
      set again (old section 12).
    - PROFILE-3 checks the character, realm and class entries AceDBOptions
      offers, each through KickCDDB.profileKeys (old section 13).
    - LABEL-12 also runs Always mode with the label attached to the cast bar:
      it follows the grid, not the bar's own hiding (old section 22).
    - PANEL-18's note on the ASCII arrow is its own sentence.

    Every expected chat and console string was re-read against the code and
    the vendored LibKa0s, and these were wrong: /kcd get and set echo a
    row's fmt ("50 px", "12 px", "64 px") and a color as {r, g, b, a};
    scale has no fmt ("scale = 2"); a color component above 1 switches to
    the 0-255 scale rather than clamping; the gate hint shares the "allowed
    values:" line; "reset spells" has moved rather than gone; the overflow
    warning's text, one per unit, re-armed once the grid fits; primarySize
    runs 24-96; the cast bar strip's tooltip is titled "KickCD castbar";
    only the slash echo reads "45 deg"; the full combat refusal line; the
    debug spells and castbar dumps, the debug ack, the [Cast] [target] gate
    line and its "none (no hostile cast)" stop, the drag list's own trace
    lines, "Debug: ON/OFF", and the perf start line's timestamp label.

    Pending sign-off now lists every carried-over check with no recorded
    owner pass, the new checks, and every corrected check (211 of 225). Only
    checks the 2026-09-26 Grid page and diagnostics runs passed whole stay
    off it.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 175490f7b9a5d10ceddb1cfa91da5f4fc71f6a2c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 21:56:52 2026 +0530

    SP-KC-03R: restore the smoke coverage the review found lost

    The review of SP-KC-03 found six places where the rewrite dropped or
    blurred an old check:

    - Relinking Focus mid-cooldown (old 20d) had no home; FOCUS-11 runs with
      no cooldown and no per-unit tint. New FOCUS-19 re-ticks the link while
      the cooldown runs and expects Target's dim red, and carries 20d's
      cleanup.
    - The Unit-picker check after a mid-cooldown slash write now sits in
      FOCUS-17's own steps and result; PANEL-13 no longer points ahead to it.
    - COMBAT-10 sets visibility target_casting_interruptible first, the mode
      that drives the interruptible-alpha gate on a secret notInterruptible.
    - FOCUS-13 starts from /kcd resetall and moves three Target rows, so the
      [Set] copy line's N is a checkable 4 (the rows changed plus the link).
    - "Which checks to run" re-derived from the coverage map: COMBAT-6 for a
      re-vendor, CAST-8 and SLASH-4 for target and focus, DIAG-28 for the
      printer and the debug console, and the full reset set for a new schema
      row, so no entry runs fewer checks than the old list.
    - docs/debug.md cites DIAG-17 and GRID-14 alongside the other old
      section 35 checks, wrapped to the file's width.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 89f8ff3d5f0d0a5a417334bb1af9c0cbc66b3931
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 21:39:02 2026 +0530

    SP-KC-03R: fix the review's smoke-doc defects

    The independent review found checks that could pass without exercising
    their behavior, and run guidance narrower than the old doc's.

    - Pending sign-off holds only unsigned checks carried over; the new
      PROFILE-9 - 14, DEGRADED-10 and CAST-14 rows are gone, and DEGRADED-6
      joins it for the unrun section-31 notice-before-the-dump half.
    - STATE-4 and FOCUS-2 turn Focus off first (it defaults on), so enabling
      it while disabled, or building it live, is actually observed.
    - PROFILE-2 copies into a scratch profile, so Default keeps 64 and
      PROFILE-10's /kcd profile switch visibly shrinks the grid to 40.
    - LABEL-15 restores the old section-22 stress run (rapid attach switching,
      slider drags, visibility changes).
    - "Which checks to run" carries every old subset entry's coverage,
      including the re-vendor, hot-path, debug console, perf and media seams.
    - STATE-7 drops the reload persistence INSTALL-5 and CAST-8 already check.
    - LABEL-11 names Attach to castbar for its first pass; SLASH-3's sentence
      reads; PANEL-18 quotes the vendored tooltip's ASCII "->".

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit f926e44221f3ffd7323a8649e1b445e752e402ce
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 21:15:29 2026 +0530

    SP-KC-03: rewrite smoke tests as one evergreen, theme-grouped suite

    The old docs/smoke-tests.md had grown to 1165 lines of numbered sections,
    batch sign-offs and regression history, with the same behaviors checked in
    several places (master enable, lock and drag, resets, profiles, the degraded
    install, the console chrome) and some checks gone stale (a six-page settings
    tree, a hardcoded compose minor, a degraded settings panel that no longer
    exists). Spec S4 of the 2026-09-29 smoke rework asks for one deduplicated
    suite grouped by theme with stable IDs.

    The new doc is 798 lines and 223 checks in 14 themes (INSTALL, SLASH, PANEL,
    PROFILE, STATE, COMBAT, GRID, CAST, FOCUS, LABEL, SPELLS, DIAG, DEGRADED,
    LOC), each check one behavior with a Result line. Every old check maps to a
    new ID; two are dropped because what they checked no longer exists (the
    per-row pcall in Helpers.RenderRows; the settings panel opening without
    LibKa0s). New: PROFILE-9 to 14 and DEGRADED-10 for /kcd profile, and CAST-14
    for empowered casts, which docs/midnight-quirks.md pointed at as a
    nonexistent "smoke C-03 step 4". The NOT YET RUN §31 and §32 checks and the
    new ones sit under Pending sign-off.

    Inbound references move to the new IDs (testing.md, debug.md,
    midnight-quirks.md). DIAG-26 now says "one L" rather than quoting the
    pre-respell perf strings, so the smoke doc's prose waiver goes and
    common-tasks.md's waiver paragraph says so.

    Gate: 1216 passed / 0 failed; luacheck 0/0 in 113 files.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 4907695436969db307181af98a4a5983acce79f5
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 20:42:34 2026 +0530

    SP-KC-02R: split loadInstance's afterFile loop into loadTocFiles (CCN 19 -> 13)

    c2d5852 inlined the afterFile hook loop, its fired-set check and error
    branch into tests/run.lua loadInstance, taking it from CCN 12 to 19. The
    TOC load plus afterFile handling now lives in a local loadTocFiles helper
    (CCN 7); loadInstance is CCN 13. Behavior unchanged: same load order, same
    hook timing, same "is not a TOC file" raise. Re-point the shifted
    tests/run.lua citation in tests/test_source_style.lua (99-108 -> 117-126).

    Gate: 1216/1216 tests, luacheck 0/0, lizard -C 15 (libs/, tests/_kit/
    excluded) 0 warnings.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit a5175b8a86e3450fde3eeb6e5d71b7293b57d205
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 20:25:37 2026 +0530

    SP-KC-02R: re-disable before every live verb in the DISABLED dispatch case

    The review found that the typed LIVE list's `profile` entry pinned nothing.
    The case "every reserved verb still answers" disabled the addon once and then
    dispatched the list in order. `enable` turns the addon back on, and `resetall`
    restores the default `enabled = true`, so every verb after `resetall`, which
    means `spells` and `profile`, went to an ENABLED addon. Dropping either verb
    from NS.EXTRA_LIVE_VERBS left every test_disabled.lua case green. That
    contradicts spec S3 step 4, slash-commands-§7 step 7 (each live verb
    dispatched while disabled) and testing-§12 (a pin that cannot go red is not
    a pin).

    The loop now calls setEnabled(inst, false) before each verb and asserts
    NS.MasterEnabled() is false before dispatching. The bare-/kcd check at the
    end is re-disabled the same way. Mutation-checked in a scratch copy: with
    `profile` dropped from NS.EXTRA_LIVE_VERBS the case goes red on
    "`/kcd profile` refused", and with `spells` dropped it goes red on
    "`/kcd spells` refused". The test count is unchanged (1216), so
    docs/test-cases.md and the badge stay as they are. No file:line citation
    points into the lines that moved.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit c2d58525a68acef74abd66a69e30f37bbb4a46f3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 13:07:02 2026 +0530

    SP-KC-02R: pin the profile row's NS.L read; re-point shifted citations

    The review found two defects in SP-KC-02.

    The `profile` locale case named "an English literal in COMMANDS" as its
    red-under mutation, but enUS's L returns the key, so a literal and the
    lookup are the same string on a stock load and the case stayed green
    (testing-§12). The runner's instance factory gains an `afterFile` option
    that runs a hook on NS right after a named TOC file loads; the case uses
    it to give the key a non-identity string after locales/enUS.lua and
    asserts the COMMANDS row carries it. Verified: the literal mutation now
    fails the case (1215/1). A key that names no TOC file raises, so a typo
    cannot leave the hook silently unfired.

    .luacheckrc cited SlashLib:New(d) at settings/Slash.lua:322; the
    re-vendor commit's added comment line moved it to 323. The run.lua edit
    also moved the mocks._G block that tests/test_source_style.lua cites
    (it was already stale at 83-97); now 99-108.

    Test count unchanged at 1216; docs/test-cases.md matches --list.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 0a25afa2e8215f23db599cca42942c664efe0c51
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 12:52:25 2026 +0530

    SP-KC-02: /kcd profile via CliProfile

    Adds the `profile` host verb (owner decisions D1-D3, spec S3). The behavior
    is LibKa0s-Slash-1.0 minor 17's CliProfile: bare lists the stored profiles
    with the current one marked; `profile <name>` switches to an existing profile
    only, with quotes stripped and case and inner spaces kept; an unknown name is
    refused with a did-you-mean and the list and never created; a switch in combat
    is refused. KickCD supplies the COMMANDS row (after resetall, NS.L
    description) and the descriptor's `profiles = function() return NS.db end`.

    `profile` joins NS.EXTRA_LIVE_VERBS beside `spells`: it is a host verb the
    library leaves off LIVE_VERBS, and a switch is a repair a disabled addon must
    still answer. It stays off NS.FEATURE_VERBS, so the degraded stub does not
    refuse it either (the stub's CliProfile prints the library-absent line). A CLI
    switch fires AceDB's OnProfileChanged, so Database:OnProfileChanged logs the
    one [Profile] line and rebuilds as for a Profiles-page switch.

    Tests first: new suite tests/test_slash_profile.lua (14 cases: pinned COMMANDS
    order and count, locale key, help row, list, switch plus handler trace and
    bus message, quotes and spaces, unknown creates nothing, did-you-mean, already
    current, combat, live-verb membership, disabled switch, degraded, degraded
    while disabled); the typed LIVE lists in test_slash and test_disabled gain
    `profile`.

    Docs: ARCHITECTURE slash table gains `profile` (and the missing
    `diagnostics` row) and the verb count moves 18 -> 19; slash-dispatch.md's
    command table and live-set judgment; profiles.md "Switching from the command
    line"; testing.md coverage bullet; README FAQ row. Citations re-pointed:
    .luacheckrc core/KickCD.lua:451 -> :468, common-tasks.md NS.COMMANDS
    core/KickCD.lua:199 -> :359. docs/test-cases.md and the README badge move to
    1216.

    Gate: 1216 passed / 0 failed; luacheck 0/0 in 113 files; lizard 0 over CCN 15.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

commit 0710ce8b981894f72b80dfcf418f170b0decdc30
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Sep 29 12:32:13 2026 +0530

    SP-KC-02: re-vendor LibKa0s v1.63.0

    LibKa0s payload from the local v1.63.0 tag (dd7a774): Slash 16 -> 17, the
    shared profile verb (profiles descriptor field, CliProfile, ProfileSwitch,
    ProfileNames, nine PROFILE_* strings). Every other file is unchanged and the
    test kit stays at revision 31. Both payloads copied whole; content diffs empty
    after the copy, nothing deleted.

    The copy alone turned the kit's by-name Slash surface-parity case red: the
    live instance now carries CliProfile and ProfileSwitch and the degraded stub
    did not. The stub in settings/Slash.lua gains both on route (b), printing the
    library-absent line for /kcd profile and switching nothing, with a new
    tests/test_slash.lua case pinning it. docs/slash-dispatch.md names them in the
    degraded-verbs list.

    CLAUDE.md provenance and docs/testing.md's version-now line roll to v1.63.0;
    docs/test-cases.md and the README Tests badge move to 1202. Bundle:
    docs/revendor/2026-09-29-v1.63.0/ (only the Slash minor 17 profile surface is
    adopted, by this item's next commit).

    Gate: 1202 passed / 0 failed; luacheck 0/0 in 112 files; lizard 0 over CCN 15.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01R83GGMfYm2GoXLBwdCsbUH

This mod has no additional files