{"record":{"id":"3a5028ce8516f3f7","repo":"ruvnet/ruflo","slug":"flywheel-anchor-manifest-requires-path-and-sha256","errorCode":null,"errorMessage":"flywheel anchor manifest requires path and sha256","messagePattern":"flywheel anchor manifest requires path and sha256","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/services/harness-project-anchor.ts","lineNumber":173,"sourceCode":"  if (!!options.anchorPath !== !!options.anchorHash) {\n    throw new Error('anchorPath and anchorHash must be supplied together');\n  }\n  if (options.anchorPath && options.anchorHash) {\n    return toSelection(containedPath(root, options.anchorPath), options.anchorHash);\n  }\n\n  const manifestCandidate = options.manifestPath ?? DEFAULT_PROJECT_ANCHOR_MANIFEST;\n  const manifestPath = isAbsolute(manifestCandidate)\n    ? manifestCandidate\n    : resolve(root, manifestCandidate);\n  if (existsSync(manifestPath)) {\n    const containedManifest = containedPath(root, manifestPath);\n    const manifest = JSON.parse(readFileSync(containedManifest, 'utf8')) as ProjectAnchorManifest;\n    if (manifest.schemaVersion !== PROJECT_ANCHOR_MANIFEST_SCHEMA) {\n      throw new Error(`unsupported flywheel anchor manifest schema: ${manifest.schemaVersion}`);\n    }\n    if (typeof manifest.path !== 'string' || typeof manifest.sha256 !== 'string') {\n      throw new Error('flywheel anchor manifest requires path and sha256');\n    }\n    // Manifest-relative paths are easier to relocate while remaining\n    // repository-contained; project-relative paths remain supported.\n    const manifestRelative = resolve(dirname(containedManifest), manifest.path);\n    const requested = existsSync(manifestRelative) ? manifestRelative : resolve(root, manifest.path);\n    return toSelection(containedPath(root, requested), manifest.sha256);\n  }\n\n  if (isRufloRepository(root) || process.env.RUFLO_FLYWHEEL_ALLOW_BUILTIN_ANCHOR === '1') {\n    const frozen = loadFrozenHumanEval();\n    return {\n      version: frozen.version,\n      anchorRef: FROZEN_HUMAN_EVAL_HASH,\n      source: 'ruflo-built-in',\n      tasks: frozen.tasks.map((task) => ({\n        id: task.id,\n        input: { id: task.id, q: task.q },\n        expected: task.labels,","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/ruvnet/ruflo/blob/2602b642d92234c710ffbe96bfb33007d481ceab/v3/@claude-flow/cli/src/services/harness-project-anchor.ts#L155-L191","documentation":"Beyond the schema version, the manifest must carry `path` (string) and `sha256` (string) — the location of the tasks file and its pinned content hash. Missing or non-string fields throw before any filesystem access, because a manifest without both keys cannot pin an anchor and downstream selection would be unverified.","triggerScenarios":"A manifest with only `path` (hash forgotten), only `sha256`, either field non-string (`path: null`, a numeric hash), or an empty JSON object at the manifest location.","commonSituations":"Hand-authored manifests; generators omitting fields they treat as optional; partial config merges; hashes stored as raw hex without the `sha256:` prefix in `sha256` fields of other tools pasted in.","solutions":["Add both fields: `\"path\": \".claude/eval/tasks.json\"` (project- or manifest-relative) and `\"sha256\": \"sha256:<64 hex>\"`","Compute the hash from the tasks file with the exported `humanEvalHash` helper (it emits the `sha256:` prefix and tolerates normalization downstream)","Validate the manifest JSON in CI before the harness runs"],"exampleFix":"// before\n{ \"schemaVersion\": \"ruflo.flywheel-anchor-manifest/v1\", \"path\": \".claude/eval/tasks.json\" }\n\n// after\n{ \"schemaVersion\": \"ruflo.flywheel-anchor-manifest/v1\", \"path\": \".claude/eval/tasks.json\", \"sha256\": \"sha256:6096e48e…\" }","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs';\n\nfunction manifestFieldsOk(file: string): boolean {\n  const m = JSON.parse(readFileSync(file, 'utf8'));\n  return typeof m.path === 'string' && typeof m.sha256 === 'string' && m.path.length > 0 && m.sha256.length > 0;\n}","typeGuard":"interface AnchorManifest { schemaVersion: string; path: string; sha256: string; }\n\nfunction hasManifestFields(v: unknown): v is AnchorManifest {\n  if (typeof v !== 'object' || v === null) return false;\n  const o = v as Record<string, unknown>;\n  return typeof o.path === 'string' && typeof o.sha256 === 'string';\n}","tryCatchPattern":"try {\n  return loadEffectiveFlywheelAnchor(root, opts);\n} catch (e) {\n  if (e?.message === 'flywheel anchor manifest requires path and sha256') {\n    throw new Error(`Manifest at ${manifestFile} must set \"path\" (tasks file location) and \"sha256\" (its pinned content hash).`);\n  }\n  throw e;\n}","preventionTips":["Generate the manifest: write the tasks file, then emit path + humanEvalHash(tasks) together","Validate manifest JSON in CI before the harness runs","Keep sha256 in the canonical 'sha256:<64 lowercase hex>' form"],"tags":["schema","validation","anchor","manifest","required-field"],"backgroundTag":"schema-validation-failed","analyzedSha":"2602b642d92234c710ffbe96bfb33007d481ceab","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}