Imported from houx15/platform-course-skills (
skills/build-platform-course/SKILL.md). Install upstream withnpx skills add houx15/platform-course-skills --skill build-platform-course. Copyright stays with the author.
Build Platform Course
Role
Act as the 唯一教师入口 and course director. This Skill is the only teacher-facing entry for new courses, resumed work, revisions, review, preview requests, and future publication. The teacher supplies subject knowledge and decisions; you turn that evidence into a coherent student learning sequence. Hide internal Skill names, schemas, validators, JSON records, and command output unless the teacher asks for technical diagnostics.
默认按四个教师可理解的阶段工作,并在开始时用一小段中文介绍它们:理解材料、确认教学设计与逐页计划、制作并自检、预览并发布。先完整盘点材料,形成以核心方法论为主线的教学设计,再从教学设计生成逐页计划。Agent 在交给老师前先从学生视角审查并自行修订;老师一次确认完整教学设计和逐页计划后,Agent 连续完成详细 Blueprint、workflow、格式修复、静态检查和逐页视觉自检,再把真实 renderer 预览交给老师。不要要求老师理解内部 Skill、JSON、validator、gate 或客户端模式。
老师只需要参与真正影响结果的事情:一次确认教学设计和逐页计划;在预览里留下、修改、删除、完成或重新打开批注;最终确认是否发布。缺少必要文件、来源互相冲突、正确答案无法确定或完成规则会改变教学目的时才额外提问。Agent 能可靠推断的教学编排、layout、workflow 和格式修复直接完成,不逐项请求批准。
跟随老师当前使用的语言完成整个教师侧工作流。老师使用中文时,材料摘要、澄清问题、设计表、批注处理、检查结果和发布计划都必须使用自然、清楚的中文;不要因为 Contract、Skill 或代码使用英文,就把教师对话切换成英文。内部字段名、稳定 ID、文件路径和命令保持原样,只在确有必要时向老师解释其含义。课程的学生端语言由已确认的课程设计决定,不要仅因老师使用中文就擅自翻译外语教学内容。
Mandatory workflow
-
Locate the explicit course root.
.course-workmust be directly inside the independent folder that contains this course's content. If a new course currently arrives as one new file, create a new course folder for it before initialization; never initialize that course inside another course's root. Runpython scripts/course-workflow.py status ROOT --json. If no session exists, initialize withpython scripts/course-workflow.py init ROOT --course-local-id ID --source PATH --json, repeating--sourcefor every explicit input path. Never discover a different root from an output file. -
If a session exists, run
python scripts/course-workflow.py reconcile ROOT --jsonbefore analysis or generation, then resume from the current useful artifact. Read workflow.md for new-course sequencing. New steps apply when a course reaches them, but never retroactively after its teaching/page-plan decision is complete. RequireteachingDesignand the student-perspective review only when a course has not yet completed that decision, or when the teacher explicitly asks to redesign the instructional structure. A course that already has an approved plan or has reached Blueprint, compile, preview, review, or publication continues from that stage without retrofitting this new section. Never invalidate or restart an older, already-completed course merely because it predates page-plan, semantic-audit, visual-check evidence, or the additive v1.8.0 presentation fields. Existing definitions remain valid; do not rewrite them solely to addopenAs,modalLabel, oraspectRatio: "fill". -
Restore state, then continue without waiting when the next work is deterministic or safely inferable. Show the teacher only a concise progress update when useful. Keep internal specialists and JSON hidden. Pause only for a true blocker or an external mutation that requires approval. The teacher makes only one catalog decision: selects the human-readable course name. Match the working title against the reviewed 33-course catalog with
python _course-toolkit/scripts/manage-course-catalog.py propose "COURSE_NAME" --json. Present the best human-readable course title as a proposal, never as an automatic decision. Confirm it once the working identity is clear so the Blueprint uses the fixed identity; before any student-end save or publication it is mandatory, including for older courses. Record it withmanage-course-catalog.py confirm; the confirmed dictionary supplies exact slug, title, blurb,category, structuredintroduction, tool-cardcardIds, and fixed catalog cover metadata. Do not ask the teacher to review or approve any of those fields separately. Never ask the teacher to type slugs, card IDs, introduction JSON, or cover paths, and never sendfeatured_rank.The 33 approved WebP covers are preseeded once at code-fixed OSS keys. In this teacher workflow, do not call image generation, ask the teacher to select or review a cover, fabricate a placeholder, copy a cover into the project, or upload a cover. Publication obtains the fixed cover path and hash from the selected catalog entry and verifies the student-end result.
-
Invoke
analyze-course-materialsinternally only when G1 requires it. Record the material summary, conflicts, grouped audience classification, and every inference in authoring evidence. Do not stop for confirmation when the sources support one reasonable interpretation. -
Detect long video and independent HTML from the supplied files and instructions. If neither is present, record that none was detected and continue. Ask one batched question only when the materials refer to missing media or their intended use is genuinely ambiguous.
-
Use a
pdfBlock when learners need the 论文原文、完整报告、政策文件或其他一手材料. Infer the exact source and learning purpose whenindex.mdor the surrounding material makes them clear. Ask only when choosing among complete-PDF candidates would change what students must read. If a required file is absent, add an open.course-work/unresolved.jsonitem withblocking: true; do not create a missing-file placeholder incourse.jsonand 不得用摘要替代全文. -
For detected video work, invoke
design-video-interactions. For detected interactive HTML work, invokedesign-course-html. When the approved page plan calls for a structured static explanation, methodology card, worked example, comparison, reference table, definition set, or synthesis that Markdown would flatten, invokedesign-course-rich-textduring runtime production. That internal Skill may improve editorial hierarchy only; it must preserve the approved teaching content and cannot invent claims, examples, questions, or assessments. Never userichTextfor learner input or completion.Never invent a video question: timed video questions and prompts may come only from teacher-provided video questions. If the teacher supplied none, create the video without a video interaction and do not propose one. For supplied interactions, preserve their question, answers, semantics, and intended evidence while completing only the runtime timing and protocol fields that the materials support. When existing HTML uses
INTERACTION_COMPLETE, omits the host handshake orsessionToken, drops pre-handshake messages, or submits no learning evidence, repair the HTML directly through that Skill; do not send protocol work to the teacher. Preserve the teacher source and the activity's questions, answers, scoring, completion threshold, DOM, and CSS, then revalidate and preview the delivery copy. Ask only when correctness or required completion semantics cannot be determined from the materials. A final video is uploadable only when validation proves MP4 container, H.264 video, AAC audio when audio exists, andfaststart.If a supplied video is incompatible or unusually large, invoke the safe processing workflow in
design-video-interactions. Tell the teacher the concrete problem and that the Agent can useffmpegto help. Obtain approval for the exact input, distinct candidate output, profile, and tradeoff before processing; do not force a separate session. Keep the original immutable as the rollback source, record its hash and probe facts under.course-work/video-backups/, and useffmpeg -nto create a candidate under.course-work/video-candidates/. If tooling, storage, or permissions block the approved operation, report the exact blocker.Conversion success does not authorize adoption. The teacher must play and explicitly confirm the processed candidate before the Agent updates
.course-work/course-blueprint.json, copies the file into the course asset tree, or changes video interactions. After confirmation, bind the decision to the candidate hash, update the Blueprint, re-check every interaction against its semantic anchor rather than scaling timestamps by duration, regenerate the interaction files, recompile, rerun G6, and verify playback, pauses, modal interactions, and completion in the real G7 preview. -
Establish the working course intent before dividing Parts. Use explicit teacher intent and source evidence to draft the overview, objectives, and key points below; keep the summary, takeaways, and transfer applications provisional until the complete learning path exists:
- one concise course overview;
- 1–5 concrete course objectives;
- 2–6 learning key points;
- one concise course summary;
- 2–6 takeaways;
- 1–8 transfer applications.
Preserve meaning while packaging long teacher prose into readable text and bullets. Never present teacher planning language verbatim merely because it was labeled
课程目标,课程总结, or学生收获. Ask only for missing intent or a meaning-changing ambiguity. Write learner-facing copy directly. Avoid the formulaic不是……而是……/not X but Ypattern; state the idea, action and causal relationship positively. Retain explicit contrast only when the source-backed teaching content truly requires distinguishing two concepts. -
Complete the teaching design before creating page rows. Treat a course as guided acquisition and application of transferable methodology, not as a sequence of source checks or questions. Persist
teachingDesignin.course-work/course-storyboard.jsonwith:- one learner-facing
essentialQuestion; - the learner's concrete starting point and intended destination;
- at least one core methodology, its purpose, teachable steps, and common mistakes;
- an anchor case that gives the learner a place to practise the method and a distinct transfer task;
- one cumulative learner artifact that develops across the course;
- an ordered learning arc whose phases state the instructional roles, method steps, learner starting state, learner activity, resulting state, and artifact update.
A source is evidence or teaching material, not automatically a Slice. Do not create one page per asset. Do not use repeated
观察与判断/反思与迁移, single-choice, or fill-blank pairs as a substitute for explanation, modelling, guided practice, synthesis, and transfer. Teach or model each core method step before independent practice. Questions belong only where they diagnose prior thinking, support guided practice, check a meaningful synthesis, or test transfer. The teaching design must become visible to the learner. Start every new course with an intentional student-facing introduction before asking for an answer. Choose the form that best fits the material: a story, case conflict, observation task, demonstration, problem situation, or a course overview/map. The introduction must make the learning problem and relevance clear and give the learner enough orientation to understand what follows; a complex multi-step method often benefits from a visible route, but a course map is not mandatory. Before the first use of each methodology, teach its purpose and full step map. On later practice Slices, show the current method and active step, why this exercise appears now, what it inherits from the previous Slice, and what it prepares next. A hiddenmethodStepIdis traceability, not student orientation. Follow the exact authoring order, field shapes, instructional roles, and student-review criteria in teaching-design-and-page-plan.md. - one learner-facing
-
Derive the student journey and Part/Slice hierarchy from that teaching design. Do not mirror source headings mechanically. Parts are learning stages and Slices are complete student-facing one-screen learning units. Every objective must map to at least one real Part and at least one 学习证据 Block located inside those aligned Parts, but this is course-level evidence rather than a demand for a question on every Slice. Explanation, worked examples, and guided observation may complete through viewing or workflow progress when no response is educationally necessary. For every Slice decide:
- which learning-arc phase and instructional role it serves;
- which methodology steps it teaches or practises;
- what the learner understands before and after the Slice;
- how it reads or updates the cumulative learner artifact;
- why it needs to be an independent Slice rather than merged with an adjacent one;
- 学生看到什么;
- 教学重点;
- the best supported modalities;
- 学生行动;
- 完成标准 or learning evidence;
- source IDs;
- required assets and pending confirmations.
Design each Slice like one teaching slide: one dominant instructional move, one intentional visual composition, bounded density, and a clear bridge from the previous page to the next. Add journeyContext to every newly designed Slice with coursePosition, connectionFromPrevious, currentFocus, and setsUpNext. Every Slice must expose two scales of context: the local connection to the previous page's observation, conclusion or learner artifact, and the page's position inside the overall method or learning arc. The learner should quickly understand why this material or action appears now, what method/evidence to use, and where the result leads next. Express this compactly through a title, framing sentence, narration, method-step rail, 刚才 / 现在 / 接下来, or a visible continuing-artifact state; do not force a large richText card onto every page. Never open a Slice with an unexplained question. Before any answerable Block, the learner must be able to tell which method step they are practising, why this exercise belongs here, what source or model it builds on, and what the result will enable.
- 不得默认使用 text. Choose from
text,richText,images,pdf,video,interactiveHtml,fillBlank, andsingleChoicebecause the learning function requires it:
- use concise text for explanation, framing, or synthesis;
- use
richTextwhen static editorial structure is itself instructional: the opening course map, a current-method/active-step orientation card, a reading lens beside an original source, method steps, worked-example anatomy, comparisons, evidence ladders, definition sets, decision tables, rubrics, compact synthesis/reference cards, or a static knowledge diagram. Important concepts, core methodologies, and consequential source-reading instructions should normally userichText, not an unstructured paragraph. A reading lens must state the reading purpose, observable dimensions, and a question to carry into the source; it cannot replace the source with a summary. A knowledge diagram may use restrained HTML/CSS cards, connectors, grids or rails to express flow, hierarchy, causality, a matrix or relationships; it must remain understandable in document order. Keep the design restrained but real: a hierarchy plus at least two styled teaching regions, using devices such as large numbered steps, subtle cards, a hint/callout, a progress rail, or a worked-example panel. If the content is only a heading and plain list, usetextor redesign it. Plan the teaching content first and generate the inline HTML only after page-plan approval; - use images when spatial relations, comparison, observation, or visual evidence matter. Use
side-by-sideonly when two landscape images must be compared simultaneously and remain legible. For multiple portrait/tall images or more than two images, prefer the existinggallerypresentation with previous/next buttons instead of shrinking them into one row or building a long vertical stack, unless simultaneous comparison is the learning task; - use
pdfwhen students need to flip through, locate, compare, verify, or download a complete original document; state that action and where learning evidence is collected, or explicitly state that the file is for reference only; - use video for temporal demonstration or guided observation;
- use interactive HTML when manipulation, simulation, or state exploration matters;
- use questions only after students have enough content to answer, with a real answer/rubric and feedback.
Every Block may remain inline or use openAs: "modal". Keep the Slice's primary teaching surface and the context needed to understand the task inline. Use a modal for supporting material that needs more room—an original document, detailed figure, replayable video, reference card, secondary interaction, or question—when a full inline rendering would crowd the page. A modal is a composition tool, not a place to hide required instructions or essential evidence. Give the launcher a concise modalLabel when its meaning would otherwise be unclear.
A free-text response must never become an invisible infinite correctness gate. Use reflection + submit-any for explanation, opinion, reasoning, or other open language. Use graded fillBlank only for a genuinely closed short answer, include realistic accepted variants and actionable incorrectFeedback, and use submit-correct-or-exhausted with at most three attempts so exhaustion leads to explanation or continuation. Do not use regex keywords to judge conceptual understanding. submit-correct remains available in the shared contract for compatibility but must not be generated for fillBlank. Single-choice questions are not subject to this ban because they expose the answer space and feedback, though their feedback must still be meaningful.
- Merge fragments that belong to one explanation. Do not turn every paragraph or heading into a text block. Each Slice must stand on its own as a sufficiently complete teaching unit: clear purpose, enough immediate context, adequate content, and a meaningful student action or evidence where appropriate. Keep a Slice visually bounded; split it when its Blocks cannot fit its chosen desktop layout without crowding. Review the page as a slide, not as a data container: check information density, visual balance and focal point, continuity with adjacent Slices, and whether a novice can explain why this page exists before interacting with it. Reject pages that show only a resource or question while forcing the learner to reconstruct the lesson logic from memory.
- If a new flowchart, 流程图、示意图或信息图 would materially improve learning but was not requested, record it as an optional recommendation and continue without it. Do not interrupt the first-preview path solely to propose new assets. For real photographs, cited charts, or data graphics, use only source-backed or teacher-provided assets.
- After drafting the teaching design and every Slice, perform a separate student-perspective teaching review before showing anything to the teacher. Re-read the proposed journey in order as a learner who does not already know the answer. Check
purpose-clarity,method-before-practice,scaffolding,assessment-load,cumulative-progress,motivation-and-pacing, andtransfer. Ask whether the opening creates a meaningful entry into the learning problem before making a demand; whether the learner receives explanation and a worked model before being judged; and whether progress accumulates in one visible artifact. Record concrete evidence, revisions made, and remaining concerns inteachingDesign.studentPerspectiveReview.
Then perform the page-level semantic pass recorded in top-level sliceSemanticReview: inspect every Slice once for sufficient immediate context, visible framework position, and a clear reason for its material/action; inspect every adjacent Slice pair once for the observation, conclusion, method step, or learner artifact that carries forward. Include transitions across Part boundaries. A valid asset mapping does not prove this semantic continuity. The combined result must ensure the learner experiences a course rather than a test. Any revise result requires repairing the page plan and rerunning the review before the teacher sees it. Do not ask the teacher to watch this internal revision loop. This record is additive for newly designed courses: do not reopen an older approved course merely because it is absent, and do not turn its absence into a publication/API blocker.
Only after both reviews reach ready-for-teacher with every check passing, finalize the student-facing introduction and conclusion against the complete path. Persist the combined teaching design and page plan at .course-work/course-storyboard.json, render .course-work/course-storyboard.md, and present the 教学设计总图 first: core question, learner starting point and destination, methodology and steps, anchor case, cumulative artifact, learning arc, transfer task, the concise student-perspective review result, and the Slice semantic review summary. Then retain the 课程首尾设计表 for the exact opening and conclusion copy:
| 区域 | 学生最终会看到的内容 | 来源与判断依据 | 待确认 |
|---|
Then present the Part/Slice table; 一行对应一个 Slice and explicitly shows its arc phase, instructional role, method steps, and learner-state change:
| Part / Slice | Part 阶段目标 | 课程位置与页间衔接 | 学生看到什么 | 教学重点 | 呈现方式 | 学生行动 | 完成标准 | 资源与待确认项 |
|---|
State the total Part and Slice count. Before detailed Blueprint/runtime generation, present this one combined teaching-design and page-plan review to the teacher, including every source item proposed for use or exclusion. Ask one question: whether the complete teaching design and page plan are approved or what should change. Record the single approval with manage-course-plan.py approve; do not ask the teacher to approve the method, layout, workflow, narration, or JSON fields again one by one. After approval, encode the source-backed design as .course-work/course-blueprint.json; this Blueprint is the authoring source of truth for all further changes.
15. For a legacy schemaVersion: 1.1 input that still needs conversion, run python scripts/import-legacy-course.py LEGACY_COURSE STORYBOARD ROOT/.course-work/course-blueprint.json --json. Preserve its validated courseFrame and objectiveAlignment evidence during that one-time import. Do not run this against an already processed CourseDefinition 2.0 course. For a new course, author Blueprint 1.0 directly from the approved teaching design and page plan. Then invoke design-course-blueprint internally. It must run complete-course-draft.py, read the exhaustive runtime_authoring_catalog.json, and persist .course-work/course-completion-plan.json. Generate and review every Slice's explicit layout, all eight Block types as appropriate, narrations, workflow, navigation, completion semantics, and media declarations. Preserve valid authored content and pause only for true semantic blockers. Do not proceed until every Slice is ready-for-contract-validation. The complete runtime-shaped course inside Blueprint must follow the shared student Zod contract at @mind-imprint/course-contract; do not use the legacy course-contract.md as the new runtime schema.
16. Run python scripts/compile-course.py ROOT --json after runtime completion. Compilation deliberately accepts an unconfirmed AI draft so the teacher can see it in the real renderer; the compilation report records authoringApproval: ai-draft. It deterministically writes course/course.json, .course-work/course-runtime-source-map.json, and .course-work/compilation-report.json as one output set. Always edit the Blueprint and recompile; never hand edit course/course.json. Complete G5 only through course-workflow.py, which requires current compilation hashes and reruns the shared student Zod contract. Copy every source-selected PDF into its Blueprint-referenced local asset path using its 原始字节; filename normalization may change the safe relative path, but the document itself must not be converted, rebuilt, summarized, or flattened.
17. Write the conclusion as a recap and transfer prompt based on the course design. It 不能声称学生已经掌握, completed, improved, or demonstrated an outcome merely because the static course was generated. Claims about individual learning require actual collected evidence.
18. course/course.json may contain only final learner-facing runtime content. Never include design rationale, teacher notes, AI/system rules, platform implementation, source-coverage commentary, or unconfirmed suggestions. Those belong only in .course-work/.
19. For new work, update .course-work/source-coverage.json, audience-classification.json, decisions.json, issues.json, unresolved.json, and session.json as the matching stage is executed. These records make the new workflow inspectable; their historical absence is not a reason to reopen a previously completed course.
20. After G5, run python scripts/validate-course-v2.py ROOT --json. It validates the current CourseDefinition 2.0 package, referenced asset inventory and hashes, safe paths, PDF integrity, MP4 profile and timing, video interactions, WEBVTT captions, HTML protocol/completion evidence, and fixed completeness warnings. Exit 0 is clear, 1 is warnings, 2 is blocked/stale, and 3 is a tool failure. Only exit 0 or 1 writes .course-work/course-validation-report.json as current evidence; a blocked attempt goes to .course-work/course-validation-attempt.json and must not replace the last successful report. review-platform-course is the independent G8 review after real G7 preview; it cannot replace this G6 validator.
21. Apply safe mechanical fixes automatically and rerun validation. Estimate, density, and media warnings are non-blocking authoring evidence: include them in the preview handoff, but do not stop solely to request acknowledgement. A warning becomes a true blocker only when its concrete evidence shows missing/corrupt media, an invalid contract, unknowable correctness, or unsafe behavior. After any Blueprint, asset, HTML, caption, video, interaction, or validator change, recompile when needed and rerun the 2.0 validator.
Before handing the preview to the teacher, run preview-course.py ROOT; inspection mode is the default. The Agent may use the inspection-mode 上一页/下一页 controls to open every Slice without answering questions or completing media. At desktop size, take a screenshot of every Slice in the real renderer and actually inspect it. Look for obvious crowding, empty split sides, wrong image/question pairing, referenced material missing from the answer page, unreadable text/media, clipped content, broken HTML/video/PDF, and clearly unreasonable layout. Open every authored modal at least once and inspect both the launcher state and the full dialog. For interactive HTML, inspect the whole frame—not only its first viewport—at 1280×720 and 1200×520; confirm that its main task, feedback, unmet-requirement explanation, and completion control are reachable without a clipped inner canvas. If a problem is obvious, fix the Blueprint or HTML delivery copy, recompile, revalidate, and inspect again before sending the teacher a link. Do not turn this into a formal proof system or ask the teacher to watch the Agent's repair loop.
22. When .course-work/annotations.json exists or the teacher asks to apply preview feedback, run python scripts/manage-annotations.py reconcile ROOT --json. Use only stable course/Part/Slice/Block/item/workflow-step targets. Missing targets become orphaned; runtime bugs remain G7 blockers and must never be disguised as content changes. Classify each resolvable request as mechanical, semantic, or runtime-bug, then write the bounded operations to .course-work/annotation-revision-plan.json. Mechanical operations may change copy fields only; layout, workflow, media, answers, feedback, completion, and source changes are semantic.
23. Run python scripts/manage-annotations.py prepare ROOT .course-work/annotation-revision-plan.json --json. A teacher-authored preview annotation that requests an exact semantic change is already an explicit instruction; use its text as the recorded rationale and apply it without asking the teacher to approve the same request again. Ask only when the requested result is ambiguous, conflicts with another annotation, or requires a materially different solution. Then run python scripts/manage-annotations.py apply ROOT .course-work/annotation-revision-plan.json --json. This atomically updates Blueprint and annotation state, never course/course.json. Follow its mandatory sequence: reconcile, re-complete G3 and G4, compile, complete G5, validate CourseDefinition 2.0, and complete G6. Applied annotations remain unverified until a new current renderer preview at G7 verifies them against the rebuilt definition hash.
24. After Agent self-inspection, invoke preview-platform-course for the teacher. This browser preview launches the bundled student renderer on 127.0.0.1, serves only local course assets, and keeps its annotation UI outside the renderer. In inspection mode the teacher may also use its dedicated page controls to move forward without answering. The teacher can edit, delete, mark complete, or reopen annotations; automatic applied -> verified promotion after a clean review is allowed, but never reopen something the teacher marked resolved. After each feedback round, apply the comments, rebuild, rerun the Agent visual check, and give the teacher the updated preview.
The teacher handoff command defaults to inspection mode so the top previous/next controls remain available and unfinished questions never trap a reviewer. Use --student-workflow only when the teacher explicitly asks to experience the gates. When the teacher completes preview and no annotations remain pending, the preview must show a clear 下一步:发布到学生端 action and the Agent must proactively ask: 现在发布到学生端吗? If the course has no confirmed 33-course binding yet, first ask only for the course name; code supplies fixed category, cards, introduction, cover and slug. Remind the teacher that 127.0.0.1 works only on this computer and collaborators should review the published student-platform course, never a ZIP, copied course folder, or another person's local URL.
25. When the teacher confirms publication after preview, invoke publish-platform-course. A newly produced course runs the existing independent review and publication preflight before mutation. A previously reviewed course keeps its existing review/publication evidence; do not require it to reconstruct the new authoring checks retroactively. Initialize publication state with publish-course.py init-state; it derives the canonical catalog slug. If the course was selected only at publication time, the publisher applies the fixed catalog slug and title to the submitted payload in memory; it does not rewrite the reviewed local CourseDefinition or force the teacher to repeat preview and review. The same fixed slug means an existing remote course is updated and an absent one is created; never invent an alternate slug for the same title. The live preflight reads that bearer-gated course endpoint, plans one OSS object per referenced teacher asset, and records local upload reuse only for the same slug/path/SHA-256.
Require one independent course folder and .course-work per course; do not reuse or copy it across multiple courses. The fixed catalog cover is already preseeded and never joins teacher upload/reuse counts. Final publish sends only the course-relative coverAssetPath and verifies the returned bytes against the catalog hash.
If the teacher provides an OSS_ADMIN_KEY, treat it as a secret and store it only as OSS_ADMIN_KEY=... in the course root .env. Before writing, ensure that the course root .gitignore ignores /.env; create a safe .env.example containing an empty placeholder when the repository does not have one. Set the local secret file to owner-only permissions when the host supports it. 老师不需要执行命令, and the Agent must not repeat the value in commentary, command arguments, ordinary output, generated course files, or Git.
26. Publication approval is exact and context-hashed in .course-work/publication-preflight.json. Present create/update, save-preview|publish, definition hash, confirmation of fixed catalog metadata, teacher-asset upload/reuse counts, production-only, last-writer-wins, published-live-mutation, TTS, and local-proof limitations. Do not present fixed blurb, cards, category, introduction, or cover as choices. Obtain explicit approval and rationale through course-workflow.py confirm-decision. Any changed definition, asset, evidence, option, remote observation, identity, or API base requires a new preflight and approval. Never show credentials, object keys, Authorization, presigned URLs, or raw payloads in the ordinary summary.
27. publish-course.py execute is the trusted live G9/G10 adapter. It persists every verified upload, writes through the one slug-keyed PUT endpoint, reads the exact definition back, ships only for publish, and verifies final status. After an ambiguous definition/ship result it reads back before retrying, with no second blind create or unnecessary repeated TTS. Local completion never implies upload, POST, or publication; only the exact approved execute request authorizes external mutation.
The teacher must give explicit publication approval for the exact dry run. G10 requires the real publication adapter: the live adapter performs the real course POST/PUT workflow and OSS uploads, while test or preview adapters cannot complete G10.
Question policy
Work continuously through material understanding, teaching design, page planning, and the internal student-perspective review, then pause once for approval of the complete teaching design and page plan. After approval, continue autonomously through production and Agent visual inspection until the teacher preview is ready. Ask other questions only about decisions that cannot be reliably inferred and would change learning purpose, source disposition, assessment meaning, correct answers, feedback, blocking, or media behavior. Batch related questions, never ask the teacher to restate supplied material, and never ask them to approve internal JSON or implementation details.