Skip to content

skills/Telos/DashboardTemplate does not next build: 27 case-duplicate paths, a tsconfig missing DOM, and two type errors #1556

Description

@tzioup

Structured for machine parsing: claims are atomic, each carries the command that verifies it. Every command runs against a fresh clone of this repo — none depend on my machine, my install, or my configuration. Full reproduction at the bottom.

Summary

LifeOS/install/skills/Telos/DashboardTemplate is a 58-file Next.js 15 app shipped in the install payload and copied to <config>/skills/Telos/DashboardTemplate on install. next build fails on it, from a fresh clone, with no modifications.

Three independent causes. Fixing any one alone still leaves the build failing:

  1. 27 redundant paths differing only in directory-name case. git clone on a case-insensitive filesystem prints a collision warning and checks out only one variant per group. TypeScript then hard-fails, because this template sets forceConsistentCasingInFileNames: true. Verified on macOS; Windows untested.
  2. tsconfig.json declares "lib": ["ESNext"] with no DOM. In a React app this produces 28 type errors — Cannot find name 'window', Property 'files' does not exist on type 'DataTransfer', Cannot find name 'HTMLTableCellElement'.
  3. Two genuine type errors that survive both fixes: React.Node (not an exported member; React.ReactNode is) and an unchecked index access under noUncheckedIndexedAccess.

Claims and verification

git clone --depth 1 https://github.com/danielmiessler/LifeOS && cd LifeOS

C1 — 22 path groups in the repo collide under case-insensitive comparison, comprising 49 paths, i.e. 27 redundant. All 22 groups are inside DashboardTemplate; there are none anywhere else in the repo's 1,692 tracked files.

git ls-tree -r --name-only HEAD | awk '{print tolower($0)"\t"$0}' | sort \
  | awk -F'\t' '{if($1==p){print pf"\n"$2} p=$1; pf=$2}' | sort -u | tee /tmp/collisions.txt | wc -l
# 49
grep -cv 'skills/Telos/DashboardTemplate/' /tmp/collisions.txt
# 0

Group sizes: 17 pairs (e.g. app/page.tsx + App/page.tsx) and 5 triples (components/ui/card.tsx + components/Ui/card.tsx + Components/Ui/card.tsx).

C2 — every colliding group is byte-identical, so this is redundancy, not divergent content.

git ls-tree -r HEAD --format='%(objectname) %(path)' | grep DashboardTemplate \
  | awk '{print tolower($2)"\t"$1}' | sort | uniq -c | awk '$1>1' | awk '{print $2}' | sort -u | wc -l
# 22 groups, each resolving to a single blob hash

No content is lost by deleting the duplicates.

C3 — on macOS the checkout is incomplete: only the PascalCase variants land on disk.

ls -d LifeOS/install/skills/Telos/DashboardTemplate/*/
# App/  Components/  Lib/

Meanwhile all 52 internal imports in the template use lowercase:

git grep -h -oE 'from "@/[A-Za-z]+/' -- LifeOS/install/skills/Telos/DashboardTemplate | sort | uniq -c
#  29 from "@/components/
#  23 from "@/lib/

C4 — next build fails from the fresh clone, unmodified.

cd LifeOS/install/skills/Telos/DashboardTemplate && bun install && bunx next build
✓ Compiled successfully in 2.7s
Failed to compile.
Type error: Already included file name '.../DashboardTemplate/app/add-file/page.tsx'
differs from file name '.../DashboardTemplate/App/add-file/page.tsx' only in casing.
Next.js build worker exited with code: 1

tsconfig.json:3 sets "forceConsistentCasingInFileNames": true, which is what turns C1 from a warning into a build failure.

C5 — after lowercasing every directory, tsc reports 30 errors, 28 of which are missing DOM globals.

for d in App Components Lib; do l=$(echo $d|tr 'A-Z' 'a-z'); mv $d __t && mv __t $l; done
mv components/Ui __t && mv __t components/ui
bunx tsc --noEmit 2>&1 | grep -c 'error TS'
# 30

Sample:

components/sidebar.tsx(61,5): error TS2304: Cannot find name 'window'.
components/ui/table.tsx(69,3): error TS2552: Cannot find name 'HTMLTableCellElement'.
app/add-file/page.tsx(32,45): error TS2339: Property 'files' does not exist on type 'DataTransfer'.

Cause is tsconfig.json:5-7:

"lib": [
  "ESNext"
],

This is the bun init default tsconfig; a Next.js/React app needs DOM.

C6 — adding DOM to lib takes the error count from 30 to 2.

# change "lib": ["ESNext"] to "lib": ["ESNext", "DOM", "DOM.Iterable"]
bunx tsc --noEmit 2>&1 | grep 'error TS'
# app/layout.tsx(13,19): error TS2694: Namespace 'React' has no exported member 'Node'.
# app/file/[slug]/page.tsx(182,19): error TS2532: Object is possibly 'undefined'.

Both are real code errors: React.Node should be React.ReactNode, and line 182 indexes without a guard under noUncheckedIndexedAccess.

C7 — the sibling template in the same skill declares DOM, so the missing lib here is an outlier rather than a project convention.

grep '"lib"' LifeOS/install/skills/Telos/ReportTemplate/tsconfig.json
# "lib": ["dom", "dom.iterable", "esnext"],

ReportTemplate is also Next 15 / React 19, has zero case collisions, and is referenced from Telos/Workflows/WriteReport.md:612. It does not build either, but for an unrelated reason — filed separately.

Scope of the claim

  • The build failure in C4 was executed on macOS (case-insensitive APFS), which is where the collision bites. I did not test on a case-sensitive filesystem. On Linux both case variants check out as distinct real directories, so C4 may not reproduce there; C5 and C6 are filesystem-independent.
  • I have not tested next dev, only next build.
  • I make no claim about whether this template is intended to be built directly or only used as a source to copy from. See the companion issue on it being referenced by nothing.

Suggested fix

One PR, three steps, in this order:

  1. git rm the 27 redundant paths, keeping the lowercase variants (app/, components/, components/ui/, lib/).

    Worth flagging that this cuts against a stated convention rather than just fixing a slip. Packs/Telos/INSTALL.md (retired in 36119d2) described both templates as "full Next.js app with App/, Components/, Lib/" — PascalCase was the intended shape, consistent with the project's TitleCase sub-file rule in LifeosSystemArchitecture.md:322. The conflict is that Next.js resolves its App Router at app/ and TypeScript treats these paths as case-significant, so the framework's convention has to win inside this directory specifically. Keeping both cases is what produces the build failure; either single case is coherent, but only lowercase also satisfies Next.js.

  2. tsconfig.json: "lib": ["ESNext", "DOM", "DOM.Iterable"].

  3. app/layout.tsx:13 React.NodeReact.ReactNode; guard the index access at app/file/[slug]/page.tsx:182.

I verified steps 1 and 2 locally and can open the PR if that's useful.

Reproduction

git clone --depth 1 https://github.com/danielmiessler/LifeOS && cd LifeOS
# the clone itself prints the collision warning listing all 49 paths
cd LifeOS/install/skills/Telos/DashboardTemplate
bun install && bunx next build   # fails

Related: #1555 asks whether this template is wired at all — if the answer there is "remove it", this build fix is moot. Filed separately per one-fix-per-issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions