santifer/career-ops · warning
web/ not present in this checkout — skipping the pdf…
Error message
web/ not present in this checkout — skipping the pdf write-scope freeze (#2185)
What it means
A warning from test-all.mjs's pdf write-scope freeze check (#2185) when the entire web/ directory is absent from the checkout. The freeze verifies that web/src/lib/worker-capabilities.mjs never grants the web 'pdf' agent write access (the backend writes all files). Without web/, the check is intentionally skipped — expected for a data-only install where web/ is in no SYSTEM_PATHS entry. It is only a problem if you expected the web layer to be present.
Solutions
- If the data-only install is intentional, do nothing — the warning documents an expected skip.
- If the pdf write-scope freeze must run, clone/copy the web/ directory into the repo root so web/src/lib exists.
- In CI, ensure the checkout step includes web/ (no sparse-checkout exclusion) when web tests should run.
- If web/ is permanently gone from your fork, delete or gate the freeze section so the log isn't noisy.
Example fix
// CI before
- uses: actions/checkout@v4
with:
sparse-checkout: modes scripts
// after — include web so the freeze runs
- uses: actions/checkout@v4 Defensive patterns
Strategy: fallback
Validate before calling
const hasWeb = existsSync(join(ROOT, 'web', 'src', 'lib')); const checks = hasWeb ? fullSuite : coreOnlySuite;
Prevention
- Document data-only vs full installs in CI and gate web checks on a hasWeb flag.
- Ensure CI checkout includes web/ when web tests are required.
- Treat this warning as informational noise on data-only installs rather than a failure.
When it happens
Trigger: Running the root test suite on a data-only install (no web/ directory cloned); running it from a shallow or partial checkout; running it after deleting web/; CI jobs that checkout only core paths.
Common situations: Deploying career-ops as a data-only workspace without the web UI; sparse git checkouts; contributors running tests before cloning submodules/web assets; a cleanup step removing web/ from a server install.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- web/ not present in this checkout — skipping the…
- Cannot import generate-pdf.mjs
- ⚠️ : skipping
- web/src/lib/career-ops.ts not found — web layer moved?…
AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16).
Data as JSON: /api/errors/662c3f721d5c7c3a.
Report an issue: GitHub.
Appendix: source
Thrown at test-all.mjs:16249
// The web's "pdf" agent tailors content and nothing else: it emits the CV
// through a <<cv-html>> envelope and the BACKEND writes every file. A write
// grant here would be unscoped, so a prompt injection in a posting or report
// (both enter that agent's context) could redirect it at cv.md.
//
// Asserted on VALUES — the built argv and the built prompt. FIVE source-text
// versions of this guard were defeated by rewriting route.ts around them (see
// web/src/lib/claude-invocation.mjs's header). The one structural rule left is
// that route.ts may not spell a tool flag itself, which is what stops an inline
// argv from hiding beside a legitimate claudeCliArgs() call.
//
// In the REQUIRED suite on purpose: web-ci.yml is informative-only, so asserting
// this only there would gate nothing. Importing is safe — these are
// dependency-free ESM modules and the root suite runs on Node >= 18.
const webLib = join(ROOT, 'web', 'src', 'lib');
const runRoutePath = join(ROOT, 'web', 'src', 'app', 'api', 'run', 'route.ts');
if (!existsSync(webLib)) {
// Expected for a data-only install: web/ is in no SYSTEM_PATHS entry.
warn('web/ not present in this checkout — skipping the pdf write-scope freeze (#2185)');
} else {
// web/ IS here, so a missing file means a move, not an absence — fail rather
// than skip, because a skip is how this freeze would silently stop guarding.
const required = {
'claude-invocation.mjs': join(webLib, 'claude-invocation.mjs'),
'worker-capabilities.mjs': join(webLib, 'worker-capabilities.mjs'),
'cv-envelope.mjs': join(webLib, 'cv-envelope.mjs'),
'run-prompts.mjs': join(webLib, 'run-prompts.mjs'),
'api/run/route.ts': runRoutePath,
};
const missing = Object.entries(required).filter(([, f]) => !existsSync(f)).map(([name]) => name);
if (missing.length > 0) {
fail(`web/ exists but ${missing.join(', ')} is missing — the #2185 write-scope freeze cannot verify (was it moved?)`);
} else {
let invocation;
let capabilities;
let prompts;
try {View on GitHub (pinned to e7abd431fc)