# description
Per-tutorial-following attestation envelope binding {tutorial-source, follower-identity, executed-steps, deviations, success-criteria-met} to a cryptographic chain. Closes SYNTHESIS-acquisition Round 20 P3 [[ai-training-and-education]] T1 ship-first action. NINETEENTH JSON Schema in IntelligencePro's catalog. The anti-hallucination anchor for the tutorial-following class: an AI agent claiming 'I followed the official tutorial' can now PROVE the claim against the tutorial's canonical bytes at the time of following. Recompute tutorialSha256 against the published tutorial URL; verify each stepSha256 matches the source; check deviation count + success-criteria-met. Designed for the AI-training + education + cookbook ecosystem: LangChain Academy (LangChain) + DeepLearning.AI Short Courses (Andrew Ng; 130+ courses by 2026-Q1 including 'AI Agents in LangGraph', 'Multi-AI-Agent Systems with crewAI', 'Building Agentic RAG with LlamaIndex') + Hugging Face Learn (NLP Course + Audio Course + Deep RL Course + Open-Source AI Cookbook + Agents Course Mar-2025) + Fast.ai (Practical Deep Learning + Deep Learning Foundations + LLM-from-scratch) + Coursera (Andrew Ng + DLAI specializations) + Udacity (AI for Robotics + Generative AI nanodegree) + edX (MIT 6.034 + Harvard CS50 AI) + AWS SkillBuilder (AI Practitioner cert + Generative AI cert) + Microsoft Learn (AI Engineer pathway + Azure AI cert + Build AI Agents using GitHub Models) + Google Cloud Skills Boost (Generative AI learning path + Vertex AI cert) + GitHub Learning Lab + Anthropic Cookbook (claude-cookbooks repo; new 2026-Q1 multi-agent + tool-use sections) + OpenAI Cookbook (cookbook.openai.com; ~700 recipes by 2026-Q1) + Cohere Notebooks + LangChain Cookbook + LangGraph templates + LlamaIndex Notebooks + Stable Diffusion workflow tutorials (ComfyUI + Automatic1111) + Replicate Cog tutorials + Lightning AI Studios + Modal docs + NVIDIA NIM tutorials + **NVIDIA NCA (NVIDIA-Certified Associate) — Generative AI LLMs cert + NCA-AIIO + NCP-AIO; current promo ends 2026-05-31, ~15-day deployment window from this commit**. Composes UPSTREAM with ip.attestation.event.v1 wire row. Composes DOWNSTREAM with ip.review.attestation.v1 (cycle 316) + ip.support.resolution.attestation.v1 (cycle 320) via citedEvidenceShaArray[] — code-review attestations cite tutorial-citations to prove the suggested fix follows the documented pattern; support resolutions cite tutorial-citations to prove KB-walkthroughs were actually executed.

# $comment
Discovery: https://ip.tekton.cc/.well-known/ip-knowledge.json (full descriptor) | Badge: https://ip.tekton.cc/api/badge/v1/attestation/tutorial.citation.attestation.v1/<subjectSha256> (shields.io endpoint) | Free dry-run: POST https://ip.tekton.cc/api/credentials/dry-run with body {kind:"tutorial.citation.attestation.v1", body:<candidate>} (no auth required, validates against this schema) | Verification recipe: https://ip.tekton.cc/docs/verification-recipe.md (3-layer trust model + curl trail) | Revocation: https://ip.tekton.cc/credentials/status/v1 (W3C BitstringStatusList v1.0; check bit at credentialStatus.statusListIndex)

# properties.schemaVersion.description
Semver of this schema. Bumps to 2.0.0 land at /credentials/tutorial-citation/v2 — v1 stays immutable (see /docs/schema-versioning.md for the cycle-726 canonical bump-mechanics + soft-change-detection contract).

# properties.citationId.description
Unique RFC 4122 UUID v4 or v7 — this tutorial-citation attestation's canonical identifier.

# properties.tutorialSha256.description
Sha256 of the canonical bytes of the tutorial at followedAt time. For markdown / HTML tutorials: sha256 of UTF-8. For Jupyter notebooks: sha256 of the canonical notebook bytes. For video tutorials: sha256 of the transcript bytes (NOT the video itself — transcripts are deterministic; video re-encoding produces different bytes). For multi-file tutorials (LangChain Academy module, HF Agents Course unit): sha256 of the JCS-encoded manifest listing each file's sha. THIS is the load-bearing anti-staleness anchor — a tutorial edited after the agent followed it surfaces as a sha mismatch on the follower's audit.

# properties.tutorialVersionTag.description
Optional human-readable version tag (e.g., 'lesson-3-v2', 'agents-course-unit-2-2026-03-15', 'nca-cert-prep-2026-q2'). Helps human auditors locate the version even when sha256 alone is opaque.

# properties.tutorialPublisherDid.description
Optional DID of the tutorial publisher (did:web:deeplearning.ai, did:web:huggingface.co, did:web:cookbook.openai.com, did:web:anthropic.com, did:web:nvidia.com, did:web:learn.microsoft.com). Lets a downstream verifier cross-check that the cited tutorial is published by the claimed source — defeats the typo-squat-tutorial class (a malicious mirror serves modified code under a similar URL).

# properties.tutorialKind.description
Tutorial format. 'code-walkthrough' = step-by-step code (LangChain Cookbook recipe). 'notebook-following' = Jupyter notebook execution. 'cert-exam-prep' = certification course material (NVIDIA NCA / AWS / Microsoft Learn). 'cookbook-recipe' = recipe-style snippet collection. Different kinds carry different evidentiary weight — a cookbook-recipe is shorter and easier to verify cell-by-cell than a multi-hour video-course-lesson.

# properties.stepsFollowed.items.properties.stepIndex.description
0-indexed step number within the tutorial.

# properties.stepsFollowed.items.properties.stepLabel.description
Optional human-readable step label (e.g., 'Install langchain-anthropic', 'Run the toolnode').

# properties.stepsFollowed.items.properties.stepSha256.description
Sha256 of the canonical step bytes (code block + prose). Lets a downstream verifier confirm THIS step's content matched what the agent executed.

# properties.stepsFollowed.items.properties.deviationFromCanonical.description
How the agent's execution differed from the canonical step. 'none' = exact match. 'minor-edit' = whitespace / formatting. 'renamed-variable' = identifier rename. 'version-bump' = updated dependency version. 'skipped' = step omitted entirely (often legitimate — e.g., skipping a credential-export step the agent doesn't need). 'substituted' = replaced with equivalent. 'added-step' = inserted a new step not in the canonical tutorial. Pinning deviations lets a downstream verifier filter trustable executions vs. ones that wandered far from the source.

# properties.stepsFollowed.items.properties.deviationNotes.description
Optional human-readable notes on the deviation.

# properties.stepsFollowed.items.properties.executionOutcome.description
Outcome of executing this step. 'error' on a no-deviation step signals a tutorial-rot bug (the canonical tutorial itself is broken).

# properties.stepsFollowed.description
Ordered array of steps the agent followed. Empty array is VALID when the attestation is for a tutorial-read-only event (the agent consulted the tutorial without executing). For a full agent walk-through: every step the tutorial documents SHOULD appear in this array. Defeats the 'I followed the tutorial' class of self-reported claims.

# properties.deviationsCount.description
Total count of non-'none' deviations across stepsFollowed. Pre-computed for fast triage (a downstream verifier can filter for 'deviationsCount == 0' to find perfect-follower executions). MUST equal len([s for s in stepsFollowed if s.deviationFromCanonical != 'none']).

# properties.successCriteriaSha256.description
Optional sha256 of the canonical bytes of the success-criteria rubric (often embedded in the tutorial; for cert-exam-prep this is the exam objectives). Pinning the criteria defeats the 'we relaxed acceptance to declare success' class — a vendor cannot retroactively soften the bar to make a previously-failing run pass.

# properties.successCriteriaMet.description
Whether the agent met the tutorial's stated success criteria. For cookbook-recipe + quickstart: did the agent produce the expected output? For cert-exam-prep: did the agent pass the exam mock? For code-walkthrough: did the final assertion / test pass?

# properties.outcomeScore.description
Optional numerical outcome score [0..1]. For multi-criteria tutorials: weighted sum across success criteria. For cert-exam-prep: normalized score (0.8 = 80% on the exam).

# properties.followerAgentVersionSha256.description
Optional sha256 of the canonical agent-version artifact. Pins WHICH agent build followed the tutorial — defeats the silent-agent-update class (an agent vendor OTAs a new policy between attestation and consumption).

# properties.executionEnvironmentSha256.description
Optional sha256 of the canonical bytes of the execution environment manifest (Python version + package manifest + OS + hardware). Tutorials often specify environment requirements (e.g., 'requires CUDA 12.3 + PyTorch 2.4 + transformers 4.50'); pinning lets a verifier check the canonical-env-match condition.

# properties.followedAt.description
Epoch milliseconds when the agent started following the tutorial.

# properties.completedAt.description
Optional epoch milliseconds when the agent finished. completedAt >= followedAt.

# properties.runnerDid.description
DID of the entity that ran the follower agent + emitted this attestation. did:web for institutional runners (did:web:cursor.sh, did:web:github.com for Copilot Agents, did:web:replit.com); did:key for individual / OSS-self-hosted. The DID resolves to a JWKS that verifies the signature. LOAD-BEARING: runnerDid SHOULD NOT equal tutorialPublisherDid (a tutorial publisher cannot solely self-attest that an agent followed their tutorial correctly — that would defeat the peer-attestation property).

# properties.ipAttestationEventId.description
Optional: UUID of the ip.attestation.event.v1 wire row that envelopes this attestation for transport.

# properties.signature.description
Ed25519 signature (128 hex = 64 raw bytes) over the canonical-JSON bytes of (citationId ⊕ tutorialUri ⊕ tutorialSha256 ⊕ tutorialVersionTag? ⊕ tutorialPublisherDid? ⊕ tutorialKind? ⊕ stepsFollowed? ⊕ deviationsCount? ⊕ successCriteriaSha256? ⊕ successCriteriaMet? ⊕ outcomeScore? ⊕ followerAgentId? ⊕ followerAgentVersionSha256? ⊕ executionEnvironmentSha256? ⊕ followedAt ⊕ completedAt? ⊕ runnerDid ⊕ ipAttestationEventId?). Verify against the publicKey published in the runnerDid's JWKS. RFC 8037 + JCS (RFC 8785). ⚠ INTEGRITY GAP (aa-824-P0-1, cycle 848 honest disclosure): `chain.*` and `extra` are presently OUTSIDE this signature pre-image. A wire-path or post-hoc rewrite of `chain.parentSha256` / `chain.parentKind` / `chain.parentAttestationId` does NOT invalidate this `signature`. Offline verifiers using `signature`+`publicKey` (the documented embedded-verification path) MUST treat `chain.*` as ADVISORY pointer-shape, NOT cryptographically bound to this attestation. For full-integrity verification including chain pointers, fetch the W3C DataIntegrityProof envelope from /credentials/<sha>/v1 and verify against the proof.cryptosuite=eddsa-jcs-2022 signature (which signs the FULL canonical-JSON body including chain). Cycle-484 added the chain block; cycles 778-784 swept it; the signature pre-image was not re-derived. Migration target: v2 schema slug ($id pin per cycle-462). See cycles 825-829 (5/5 wedge-tier ring) + cycle 830 (verification-recipe.md dual-path teaching) for the canonical write-up; cycle 848 fans this disclosure to the 12 remaining chain-bearing leaf schemas in one batch.

# properties.publicKey.description
Ed25519 public key (32 raw bytes = 64 hex) corresponding to the signature.

# properties.chain.properties.parentSha256.description
Sha256 of the canonical-JSON bytes of the parent attestation. For a tutorial.citation.attestation the typical parent is the ip.experiment.receipt.v1 that minted the model the tutorial walks through (the tutorial cites a SPECIFIC model checkpoint, so the receipt is the canonical upstream), OR the ip.pipeline.facet.v1 attesting the upstream dataset / training corpus when the tutorial cites a dataset rather than a model. ⚠ Cycle 493 honest-disclosure (adversarial-auditor AA-485-P2-4): the platform does NOT verify parent-existence at issuance. A syntactically-valid 64-hex sha256 satisfies this pattern but the bytes may not resolve in any attestation store. Consumers walking the chain MUST resolve parentSha256 against their own attestation registry (the platform exposes no by-sha lookup as of cycle 493); see /docs/verification-recipe.md for the canonical walk. A dangling parentSha256 is an UNVERIFIED chain link, NOT a verified absence.

# properties.chain.properties.parentKind.description
Kind identifier of the parent attestation. tutorial.citation typically points at experiment-receipt (the model the tutorial demonstrates against) or pipeline-facet (the upstream dataset / corpus). The tutorial substrate is leaf-of-leaves: cite WHAT the recipe runs against, then verify-walks land at raw bytes.

# properties.chain.properties.parentAttestationId.description
Optional UUID of the parent attestation — convenience for consumers that index by id rather than by sha256.

# properties.chain.description
Cycle 779 (sc-772-P0-1 partial close, second of N): uniform upward chain link per the cycle-484 substrate. Pre-cycle-779 ip.tutorial.citation.attestation.v1 had no chain.parentSha256, so a verifier walking up from a tutorial-citation footer (the cycle-769 ip-tutorial-attested killer-feature anchor at /docs/wedge.md L74) could not mechanically reach the upstream experiment-receipt or pipeline-facet without out-of-band correlation. The block is OPTIONAL (not in required[]) so back-compat preserved.