type: decision
status: active
timestamp: 2026-07-01
tags: [stack, pnpm, dagger, megalinter, typescript, ci, pipelines]

Pipeline stack lock 2026-07-01 — pnpm + MegaLinter + Dagger TS

The five-layer canonical stack for every oriz repo: pnpm 11 (package + tasks), MegaLinter (lint), Dagger TS (CI pipelines), TypeScript everywhere. No mise, no super-linter, no Earthly, no Python for new scripts.

Pipeline stack lock 2026-07-01

The 5-layer stack

LayerToolWhy
Package managerpnpm 11Locked; 2-3× faster than npm, 70% less disk, monorepo-native
Task runnerpnpm scriptsAlready in package.json, no extra tool
LinterMegaLinter (oxsecurity/megalinter)7.6× more active than super-linter, 134 linters vs ~50, auto-fix commits, first-class GitLab/Azure/Jenkins docs
CI pipelineDagger TSType-safe, portable across GHA/GitLab/Codeberg, same code as app repos
ScriptsTypeScript (tsx or bun runner)Single-language codebase; Python scripts migrate to TS

Rejected alternatives

ToolWhy rejected
npm2-3× slower, 3× more disk
yarn v1Deprecated 2024
yarn 4 (Berry PnP)Breaks Astro Integration + CF Workers tooling
bunnode-gyp addons broken (better-sqlite3 fails); Astro adapter community-only
misepnpm already covers task-running for Node-only stack
super-linter89 commits/90d vs MegaLinter 680; auto-fix only prints to console
EarthlyDead — Cloud shut down 2025-07
Nix FlakesWindows requires WSL
Bazel/Buck2Over-engineered for 100 polyrepos

Adoption policy

Migration plan for existing 5 Python scripts

ScriptNew fileNotes
scripts/okf-prompt-lookup.pyscripts/okf-prompt-lookup.tsUserPromptSubmit hook target — must keep same stdin/stdout contract
scripts/okf-index-lookup.pyscripts/okf-index-lookup.tsCLI, stdlib-only Python → node:fs + path
scripts/fix_broken_links.pyscripts/fix-broken-links.tsRename kebab-case per repo convention
scripts/restructure_knowledge.pydelete (one-time script, already ran)Historical
scripts/rename-agent-rules-to-rules-agent.pydelete (one-time)Historical

Every new repo template

├── package.json          # pnpm 11
├── pnpm-lock.yaml
├── .mise.toml            # OPTIONAL — only if this repo needs non-Node toolchain
├── .mega-linter.yml      # MegaLinter config (or leave empty for defaults)
├── dagger/
│   └── main.ts           # Dagger TS pipeline
├── .github/workflows/
│   └── ci.yml            # 5-line thin adapter: `dagger call ci`
└── tsconfig.json

Thin CI adapter (works on GHA, GitLab, Codeberg, self-host)

# .github/workflows/ci.yml
on: [push, pull_request]
jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dagger/[email protected]
        with:
          call: ci --source=.

Swap the uses: line to switch CI providers. dagger call runs identically everywhere.

Cross-refs


Edit on GitHub · Back to index