init-config-file

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Init Config File

初始化配置文件

This skill is the single authoritative writer of
config.yaml
for a ***plain project. Anything that ends up in
config.yaml
should go through this skill. The renderer (
codeplain
) reads each key listed below into the same argparse namespace it uses for CLI flags — so a value set in
config.yaml
is exactly equivalent to passing the corresponding
--flag
on the command line.
此技能是*plain项目中
config.yaml
唯一权威编写者**。任何要写入
config.yaml
的内容都必须通过此技能。渲染器(
codeplain
)会将下面列出的每个键读取到与CLI标志相同的argparse命名空间中——因此在
config.yaml
中设置的值与在命令行中传递对应的
--flag
完全等效。

When to run

运行时机

  • End of
    forge-plain
    Phase 3 / start of Phase 4
    — after every test-script decision is locked in (unit tests, conformance tests, prepare-environment), before delegating to
    plain-healthcheck
    .
  • End of
    add-feature
    — only when Phase 3 of the feature touched the testing surface (new script generated, script removed, template directory introduced).
  • End of any single-skill workflow that finalizes a script or template — e.g. after
    implement-unit-testing-script
    ,
    implement-conformance-testing-script
    ,
    implement-prepare-environment-script
    ,
    add-template
    , or
    create-import-module
    .
  • On demand — when the user asks "rebuild my config", "what valid keys are there", or you discover the config file is hand-edited / inconsistent.
If you only fixed a typo inside a
.plain
file and the testing surface didn't move, you do not need to re-run this skill — go straight to
plain-healthcheck
.
  • forge-plain
    第三阶段结束/第四阶段开始时
    ——在所有测试脚本决策(单元测试、一致性测试、环境准备)确定后,在委托给
    plain-healthcheck
    之前。
  • add-feature
    结束时
    ——仅当功能的第三阶段涉及测试范围(生成新脚本、移除脚本、引入模板目录)时。
  • 任何完成脚本或模板的单技能工作流结束时——例如在运行
    implement-unit-testing-script
    implement-conformance-testing-script
    implement-prepare-environment-script
    add-template
    create-import-module
    之后。
  • 按需运行——当用户询问“重建我的配置”、“有哪些有效键”,或者你发现配置文件是手动编辑/不一致时。
如果你只是修复了
.plain
文件中的拼写错误且测试范围未改变,则无需重新运行此技能——直接运行
plain-healthcheck
即可。

What this skill does

此技能的功能

  1. Determines how many
    config.yaml
    files the project needs (one per part — see Per-part split).
  2. For each config, gathers the decided values from the current project state (existing scripts under
    test_scripts/
    , the template directory, the build/dest folder choices).
  3. Emits a clean, alphabetically-grouped
    config.yaml
    containing only keys that are actually in use, using the canonical key names from the Valid keys reference.
  4. Verifies that every
    *-script
    value points at a file that exists on disk under
    test_scripts/
    (or wherever the user placed it), using the same lookup rule the renderer uses: absolute path → path relative to the config file's directory → path relative to the renderer's directory.
  5. Hands off to
    plain-healthcheck
    for the full validation pass.
  1. 确定项目需要多少个
    config.yaml
    文件(每个部分一个——参见按部分拆分)。
  2. 针对每个配置,从当前项目状态(
    test_scripts/
    下的现有脚本、模板目录、构建/目标文件夹选择)中收集已确定的值。
  3. 生成一个整洁、按字母分组的
    config.yaml
    ,仅包含实际使用的键,使用有效键参考中的标准键名。
  4. 验证每个
    *-script
    值指向磁盘上
    test_scripts/
    (或用户放置的任何位置)中存在的文件,使用与渲染器相同的查找规则:绝对路径→相对于配置文件目录的路径→相对于渲染器目录的路径。
  5. 将任务委托给
    plain-healthcheck
    进行完整的验证。

What this skill does NOT do

此技能不具备的功能

  • It does not generate testing scripts. Use
    implement-unit-testing-script
    ,
    implement-conformance-testing-script
    , or
    implement-prepare-environment-script
    first; this skill only wires them in.
  • It does not decide whether the user wants conformance tests, a prepare-environment script, copy-build, etc. Those decisions belong to
    forge-plain
    Phase 3. This skill only records them.
  • It does not invent values for keys whose decisions weren't made — it leaves them out (the renderer falls back to its default) rather than guessing.
  • It does not write secrets.
    api-key
    belongs in the
    CODEPLAIN_API_KEY
    environment variable, never in
    config.yaml
    .
  • 不生成测试脚本。请先使用
    implement-unit-testing-script
    implement-conformance-testing-script
    implement-prepare-environment-script
    ;此技能仅负责将它们关联到配置中。
  • 不决定用户是否需要一致性测试、环境准备脚本、复制构建等。这些决策属于
    forge-plain
    第三阶段。此技能仅记录这些决策。
  • 不为未做出决策的键生成值——它会忽略这些键(渲染器会使用默认值),而不是猜测。
  • 不写入密钥
    api-key
    应放在
    CODEPLAIN_API_KEY
    环境变量中,绝不能放在
    config.yaml
    中。

Valid keys reference

有效键参考

The canonical list of keys is derived from the
codeplain
CLI argparse parser. Every key below corresponds to exactly one
--flag
and is read by the renderer through
update_args_with_config
. No other keys are valid — the renderer rejects unknown keys with
parser.error(f"Invalid argument: {key}")
.
YAML keys use the dashed form (e.g.
unittests-script
, not
unittests_script
) to mirror the CLI flag spelling. The only exception that has historically appeared with underscores is
template_dir
; prefer
template-dir
for new configs but accept either when reading an existing file.
标准键列表源自
codeplain
CLI的argparse解析器。下面的每个键都对应一个
--flag
,渲染器通过
update_args_with_config
读取这些键。其他所有键均无效——渲染器会通过
parser.error(f"Invalid argument: {key}")
拒绝未知键。
YAML键使用短横线形式(例如
unittests-script
,而非
unittests_script
)以匹配CLI标志的拼写。历史上唯一使用下划线的例外是
template_dir
;对于新配置,优先使用
template-dir
,但读取现有文件时两种形式都可接受。

Keys you typically include

通常需要包含的键

These keys reflect choices made in Phase 3 of
forge-plain
and are the bread and butter of a project's
config.yaml
:
KeyTypeDefaultWhen to include
unittests-script
path (string)Required. Every project gets a unit-test runner. Path resolves relative to the config file's directory (preferred) or the renderer directory.
conformance-tests-script
path (string)Include when the user opted into conformance testing in Phase 3.
prepare-environment-script
path (string)Include only when both (a) the user opted into a prepare-environment script and (b)
conformance-tests-script
is also set. Setting prepare without conformance is a hard
plain-healthcheck
failure.
test-script-timeout
int (seconds)
120
Include only when the user explicitly raised/lowered the default.
template-dir
path (string)Include whenever the project has an
import
module or a custom template directory (e.g.
template/
). Required for projects with shared templates.
logging-config-path
path (string)
logging_config.yaml
Points at a separate YAML file consumed by Python's
logging.config.dictConfig
. This is the only knob that lets the user actually change log levels for the renderer and its dependencies. See Logging configuration below. Include the key explicitly whenever the project ships a non-default logging config; leave it out only when the user is happy with the renderer's defaults (
INFO
root,
WARNING
for
git
,
ERROR
for
transitions
).
conformance-tests-folder
string
conformance_tests
Include only when the user picked a non-default folder name.
build-folder
string
plain_modules
Include only when the user picked a non-default folder name. Must differ from
build-dest
.
build-dest
string
dist
Always include with the value
dist
.
This skill pins the copy destination explicitly so every project's
config.yaml
has the same, predictable target folder for the post-render copy. Even though
dist
matches the renderer's default, we still write it out so the choice is visible in the file and protected against future default changes. Must differ from
build-folder
.
base-folder
stringInclude when the user wants build output rooted somewhere other than the project root.
这些键反映了
forge-plain
第三阶段做出的选择,是项目
config.yaml
的核心内容:
类型默认值包含时机
unittests-script
路径(字符串)必填项。每个项目都需要一个单元测试运行器。路径相对于配置文件目录(推荐)或渲染器目录解析。
conformance-tests-script
路径(字符串)当用户在第三阶段选择一致性测试时包含。
prepare-environment-script
路径(字符串)仅当(a)用户选择了环境准备脚本且(b)同时设置了
conformance-tests-script
时才包含。仅设置环境准备脚本而未设置一致性测试会导致
plain-healthcheck
直接失败。
test-script-timeout
整数(秒)
120
仅当用户明确修改默认值时包含。
template-dir
路径(字符串)当项目有
import
模块或自定义模板目录(例如
template/
)时包含。对于有共享模板的项目是必填项。
logging-config-path
路径(字符串)
logging_config.yaml
指向一个供Python的
logging.config.dictConfig
使用的独立YAML文件。这是用户实际更改渲染器及其依赖项日志级别的唯一控制项。请参阅下面的日志配置。当项目使用非默认日志配置时,显式包含此键;仅当用户满意渲染器的默认设置(根日志级别为
INFO
git
WARNING
transitions
ERROR
)时才忽略此键。
conformance-tests-folder
字符串
conformance_tests
仅当用户选择了非默认文件夹名称时包含。
build-folder
字符串
plain_modules
仅当用户选择了非默认文件夹名称时包含。必须与
build-dest
不同。
build-dest
字符串
dist
始终以
dist
为值包含
。此技能会在它编写的每个配置中明确固定复制目标,以便每个项目的
config.yaml
都有相同的、可预测的渲染后复制目标文件夹。即使
dist
与渲染器的默认值匹配,我们仍会将其写入文件,以便该选择在文件中可见,并防止未来默认值更改的影响。必须与
build-folder
不同。
base-folder
字符串当用户希望构建输出根目录不在项目根目录时包含。

Keys you occasionally include

偶尔需要包含的键

These are useful but the defaults are almost always fine. Only include them when the user explicitly changed the default during Phase 3:
KeyTypeDefaultNotes
copy-build
bool
true
The renderer copies the rendered code to
build-dest
after a successful render. Set to
false
only when the user doesn't want this.
copy-conformance-tests
bool
false
Requires
conformance-tests-script
to also be set.
conformance-tests-dest
string
dist_conformance_tests
Target folder for the conformance-test copy. Must differ from
conformance-tests-folder
.
log-to-file
bool
true
Disable only when the user explicitly does not want a log file. Controls whether logs are mirrored to disk — it does not set the log level (that's
logging-config-path
's job).
log-file-name
string
codeplain.log
If
log-to-file
is
false
, this key must be left out. Resolved relative to the
.plain
file directory.
render-machine-graph
bool
false
Include only when the user wants the state-machine graph rendered.
headless
bool
false
Include only when the project is meant to run in CI / non-interactive mode by default.
force-render
bool
false
Almost never belongs in
config.yaml
; prefer the CLI flag for one-off forced renders.
verbose
bool
false
Almost never belongs in
config.yaml
; prefer the CLI flag for one-off verbose runs.
api
URL (string)
https://api.codeplain.ai
Include only when the user is pointing at a non-default API endpoint.
这些键很有用,但默认值几乎总是适用。仅当用户在第三阶段明确修改默认值时才包含:
类型默认值说明
copy-build
布尔值
true
渲染器在成功渲染后会将渲染后的代码复制到
build-dest
。仅当用户不需要此功能时设置为
false
copy-conformance-tests
布尔值
false
需要同时设置
conformance-tests-script
conformance-tests-dest
字符串
dist_conformance_tests
一致性测试复制的目标文件夹。必须与
conformance-tests-folder
不同。
log-to-file
布尔值
true
仅当用户明确不希望生成日志文件时禁用。控制日志是否镜像到磁盘——它设置日志级别(这是
logging-config-path
的职责)。
log-file-name
字符串
codeplain.log
如果
log-to-file
false
,则必须忽略此键。相对于
.plain
文件目录解析。
render-machine-graph
布尔值
false
仅当用户希望渲染状态机图时包含。
headless
布尔值
false
仅当项目默认要在CI/非交互模式下运行时包含。
force-render
布尔值
false
几乎不应放在
config.yaml
中;对于一次性强制渲染,优先使用CLI标志。
verbose
布尔值
false
几乎不应放在
config.yaml
中;对于一次性详细运行,优先使用CLI标志。
api
URL(字符串)
https://api.codeplain.ai
仅当用户指向非默认API端点时包含。

Keys you must NEVER include

绝对不能包含的键

These flags are per-invocation or secret. Putting them in
config.yaml
is always wrong:
KeyWhy it doesn't belong
api-key
Secret. Belongs in the
CODEPLAIN_API_KEY
environment variable. Never in a file the user might commit.
dry-run
Per-invocation.
plain-healthcheck
runs the dry-run explicitly; pinning it in the config would make a real render impossible.
full-plain
Per-invocation preview. Mutually exclusive with
dry-run
.
render-range
Per-invocation. Selects a slice of functionalities to (re)render.
render-from
Per-invocation. Mutually exclusive with
render-range
.
replay-with
Internal / debugging flag.
config-name
Refers to the config file itself — the renderer ignores it when reading the config.
filename
The
.plain
file to render is always passed positionally on the CLI.
If the user asks to put any of these in
config.yaml
, refuse and explain why.
这些标志是每次调用专属保密的。将它们放在
config.yaml
中永远是错误的:
不能包含的原因
api-key
保密信息。应放在
CODEPLAIN_API_KEY
环境变量中。绝不能放在用户可能提交的文件中。
dry-run
每次调用专属。
plain-healthcheck
会显式运行dry-run;将其固定在配置中会导致无法进行实际渲染。
full-plain
每次调用预览。与
dry-run
互斥。
render-range
每次调用专属。选择要(重新)渲染的功能片段。
render-from
每次调用专属。与
render-range
互斥。
replay-with
内部/调试标志。
config-name
指向配置文件本身——渲染器读取配置时会忽略它。
filename
要渲染的
.plain
文件始终通过CLI位置参数传递。
如果用户要求将这些键中的任何一个放入
config.yaml
,请拒绝并解释原因。

Logging configuration

日志配置

Log levels are not controlled directly by
config.yaml
— they live in a separate YAML file that the renderer feeds to Python's
logging.config.dictConfig
. The
config.yaml
key
logging-config-path
is the pointer that wires the two together.
日志级别不由
config.yaml
直接控制——它们位于一个独立的YAML文件中,渲染器会将其传入Python的
logging.config.dictConfig
config.yaml
中的
logging-config-path
键是连接两者的指针。

How the renderer assembles logging

渲染器如何组装日志配置

From
setup_logging
in the
codeplain
source:
  1. The renderer first installs a set of baseline levels:
    • root logger →
      INFO
    • LOGGER_NAME
      (the renderer's own logger) →
      INFO
    • git
      WARNING
    • transitions
      ERROR
    • transitions.extensions.diagrams
      ERROR
  2. If
    args.logging_config_path
    resolves to an existing file on disk, the renderer loads that YAML and calls
    logging.config.dictConfig(...)
    on it. This overlays anything from step 1 — the user can raise, lower, or add levels for any logger they care about, add handlers, change formatters, etc.
  3. The renderer then attaches its own handlers (TUI handler unless
    headless
    , file handler if
    log-to-file
    , crash buffer otherwise). Whatever level the root logger ended up at after step 2 is the level those handlers respect.
In other words:
logging-config-path
is the only knob that changes the levels.
log-to-file
and
log-file-name
only control whether and where logs are written — not what gets written.
来自
codeplain
源码中的
setup_logging
  1. 渲染器首先安装一组基线级别
    • 根日志记录器 →
      INFO
    • LOGGER_NAME
      (渲染器自身的日志记录器) →
      INFO
    • git
      WARNING
    • transitions
      ERROR
    • transitions.extensions.diagrams
      ERROR
  2. 如果
    args.logging_config_path
    解析为磁盘上存在的文件,渲染器会加载该YAML并对其调用
    logging.config.dictConfig(...)
    。这会覆盖步骤1中的所有设置——用户可以提高、降低或添加任何他们关心的日志记录器的级别,添加处理器,更改格式化程序等。
  3. 然后渲染器附加自己的处理器(除非
    headless
    否则使用TUI处理器,如果
    log-to-file
    则使用文件处理器,否则使用崩溃缓冲区)。步骤2后根日志记录器最终的级别就是这些处理器遵循的级别。
换句话说:
logging-config-path
是更改日志级别的唯一控制项。
log-to-file
log-file-name
仅控制日志是否写入以及写入位置——而不是写入内容

Default behavior

默认行为

  • The CLI default value for
    logging-config-path
    is
    logging_config.yaml
    . If a file by that exact name exists in the current working directory, it will be loaded automatically — even without
    logging-config-path
    being set in
    config.yaml
    .
  • If the file does not exist, the renderer silently keeps the baseline levels from step 1 above (no warning).
  • If the file exists but fails to parse / apply, the renderer warns (
    Failed to load logging configuration from …
    ) and falls back to the baseline.
This means the mere presence of a
logging_config.yaml
file is itself a config decision.
When you assemble a project's
config.yaml
, you have three cases:
SituationWhat to do
The user is happy with the baseline levels and the project has no
logging_config.yaml
on disk.
Leave
logging-config-path
out of
config.yaml
.
The user wants custom levels and is fine with the file being named
logging_config.yaml
next to the
.plain
file.
Create that file (see Recommended logging config below). Leaving
logging-config-path
out of
config.yaml
is fine — the default points at it already — but explicitly setting
logging-config-path: logging_config.yaml
is also acceptable and makes the dependency visible to anyone reading the config.
The user wants the logging config file to live somewhere non-default (different filename or directory).Create the file at the chosen path and set
logging-config-path: <that path>
in
config.yaml
.
When in doubt, ask the user: "Do you want to change the default log levels (INFO for the renderer, WARNING for git, ERROR for transitions), or stick with the defaults?" Only generate / pin the file when they say yes.
  • logging-config-path
    的CLI默认值为
    logging_config.yaml
    。如果当前工作目录中存在同名文件,即使
    config.yaml
    中未设置
    logging-config-path
    ,也会自动加载该文件。
  • 如果文件不存在,渲染器会静默保留步骤1中的基线级别(无警告)。
  • 如果文件存在但解析/应用失败,渲染器会发出警告(
    Failed to load logging configuration from …
    )并回退到基线级别。
这意味着**
logging_config.yaml
文件的存在本身就是一个配置决策**。当你组装项目的
config.yaml
时,有三种情况:
情况处理方式
用户满意基线级别且项目磁盘上没有
logging_config.yaml
config.yaml
中忽略
logging-config-path
用户想要自定义级别且接受文件名为
logging_config.yaml
并放在
.plain
文件旁边
创建该文件(参见下面的推荐日志配置)。在
config.yaml
中忽略
logging-config-path
也可以——默认值已经指向它,但显式设置
logging-config-path: logging_config.yaml
也是可接受的,并且能让任何读取配置的人看到这个依赖关系。
用户希望日志配置文件放在非默认位置(不同文件名或目录)在选定路径创建文件,并在
config.yaml
中设置
logging-config-path: <该路径>
如有疑问,请询问用户:“你想要更改默认日志级别(渲染器为INFO,git为WARNING,transitions为ERROR),还是保持默认?”仅当用户同意时才生成/固定该文件。

Recommended logging config

推荐日志配置

When the user does want custom levels, write a minimal
dictConfig
-style YAML file. Example with two common knobs (verbose renderer logs, plus suppression of a chatty third-party logger):
version: 1
disable_existing_loggers: false
formatters:
  default:
    format: "%(levelname)s:%(name)s:%(message)s"
handlers:
  console:
    class: logging.StreamHandler
    formatter: default
    level: DEBUG
loggers:
  codeplain:
    level: DEBUG
  urllib3:
    level: WARNING
root:
  level: INFO
  handlers: [console]
Guidelines for what to put in this file:
  • Always set
    version: 1
    dictConfig
    requires it.
  • Set
    disable_existing_loggers: false
    unless the user explicitly wants to silence loggers that were created before
    dictConfig
    ran. The renderer creates several before it loads this file, and disabling them by default leads to confusing dead silence.
  • Only override levels the user actually asked about. Don't preemptively add every logger the codebase touches — that creates ongoing maintenance for no benefit.
  • Don't put the
    LoggingHandler
    /
    CrashLogHandler
    /
    FileHandler
    here — the renderer attaches those itself after
    dictConfig
    runs. Adding them here will cause duplicate log lines.
  • This file is not validated by
    plain-healthcheck
    . If you change it, ask the user to confirm by reading it back to them.
当用户确实需要自定义级别时,编写一个最小的
dictConfig
风格的YAML文件。以下是包含两个常用设置(详细的渲染器日志,以及抑制一个冗长的第三方日志记录器)的示例:
version: 1
disable_existing_loggers: false
formatters:
  default:
    format: "%(levelname)s:%(name)s:%(message)s"
handlers:
  console:
    class: logging.StreamHandler
    formatter: default
    level: DEBUG
loggers:
  codeplain:
    level: DEBUG
  urllib3:
    level: WARNING
root:
  level: INFO
  handlers: [console]
编写此文件的准则:
  • 始终设置
    version: 1
    ——
    dictConfig
    要求此设置。
  • 设置
    disable_existing_loggers: false
    ,除非用户明确希望静默
    dictConfig
    运行前创建的日志记录器。渲染器在加载此文件前会创建几个日志记录器,默认禁用它们会导致令人困惑的静默状态。
  • 仅覆盖用户实际要求的级别。不要预先添加代码库涉及的每个日志记录器——这会造成不必要的持续维护。
  • 不要在此处添加
    LoggingHandler
    /
    CrashLogHandler
    /
    FileHandler
    ——渲染器会在
    dictConfig
    运行后自行附加这些处理器。在此处添加会导致日志行重复。
  • 此文件不会
    plain-healthcheck
    验证。如果你更改了它,请让用户通过读回内容来确认。

Per-part split

按部分拆分

The rule, which mirrors what
forge-plain
Phase 3 already establishes, is one
config.yaml
per part of the system that has its own testing scripts
:
  • Single-stack project (e.g. one Python service) → one
    config.yaml
    at the project root.
  • Multi-part project (e.g. Python backend + React frontend) → one
    config.yaml
    per part, placed next to the part's top module (e.g.
    backend/config.yaml
    ,
    frontend/config.yaml
    ). Each config references only its own scripts; never mix stacks in a single config.
  • A part's split should follow the module boundaries from Phase 1 / Phase 2: if a module has its own language, framework, and test scripts, it gets its own
    config.yaml
    next to that module.
Before emitting anything, state the planned split to the user (e.g. "I'll emit
backend/config.yaml
and
frontend/config.yaml
") if there is more than one part.
规则与
forge-plain
第三阶段已确立的规则一致:每个拥有独立测试脚本的系统部分对应一个
config.yaml
  • 单栈项目(例如一个Python服务)→ 在项目根目录有一个
    config.yaml
  • 多部分项目(例如Python后端 + React前端)→ 每个部分对应一个
    config.yaml
    ,放在该部分的顶级模块旁边(例如
    backend/config.yaml
    frontend/config.yaml
    )。每个配置仅引用自身的脚本;绝不能在单个配置中混合不同栈
  • 部分的拆分应遵循第一阶段/第二阶段的模块边界:如果一个模块有自己的语言、框架和测试脚本,则在该模块旁边创建一个独立的
    config.yaml
在生成任何文件之前,如果项目有多个部分,请向用户说明计划的拆分方式(例如“我将生成
backend/config.yaml
frontend/config.yaml
”)。

Workflow

工作流程

Step 1 — Inventory

步骤1 — 盘点

  1. List every
    .plain
    file in the repo and identify the top modules (modules not
    requires
    -ed by anything else) — same procedure as
    plain-healthcheck
    Step 1.
  2. For each top module, determine which part it belongs to (single-stack → one part; multi-part → one part per top module).
  3. List every script under
    test_scripts/
    and group them by part (e.g.
    *_python.sh
    belongs to the backend part,
    *_js.sh
    belongs to the frontend part).
  4. Identify the template directory (typically
    template/
    ) and any custom resource directories (typically
    resources/
    ).
  5. Read any existing
    config.yaml
    in each part's directory — preserve any user-set fields not listed in Valid keys reference only with the user's explicit approval, and warn that unknown keys will be rejected by the renderer.
  1. 列出仓库中的所有
    .plain
    文件并确定顶级模块(不被其他模块
    requires
    的模块)——与
    plain-healthcheck
    步骤1的流程相同。
  2. 针对每个顶级模块,确定它属于哪个部分(单栈→一个部分;多部分→每个顶级模块对应一个部分)。
  3. 列出
    test_scripts/
    下的所有脚本并按部分分组(例如
    *_python.sh
    属于后端部分,
    *_js.sh
    属于前端部分)。
  4. 确定模板目录(通常为
    template/
    )和任何自定义资源目录(通常为
    resources/
    )。
  5. 读取每个部分目录中已有的
    config.yaml
    ——仅在用户明确批准的情况下保留有效键参考中未列出的用户设置字段,并警告用户未知键会被渲染器拒绝。

Step 2 — Assemble per-part values

步骤2 — 组装每个部分的值

For each part:
  1. Start from an empty key set.
  2. Add
    unittests-script: test_scripts/run_unittests_<lang>.<sh|ps1>
    — required. If the script doesn't exist yet, stop and tell the caller to run
    implement-unit-testing-script
    first.
  3. If the part has a conformance script on disk → add
    conformance-tests-script: …
    .
  4. If the part has a prepare-environment script on disk → first verify
    conformance-tests-script
    is also being added; if not, stop and surface this to the user (offer to either generate the missing conformance script via
    implement-conformance-testing-script
    or drop the prepare-environment script).
  5. If the project has shared templates → add
    template-dir: template
    (or whatever path the user used).
  6. Always add
    build-dest: dist
    .
    This skill pins the copy destination on every config it writes, regardless of what Phase 3 said about it. If Phase 3 explicitly asked for a different
    build-dest
    , stop and surface the conflict to the user — do not silently honor the override.
  7. For every other key in Valid keys reference, include it only if Phase 3 produced a non-default decision for that key.
  8. Cross-validate the assembled key set:
    • build-dest
      is set to
      dist
      .
    • build-folder
      build-dest
      (in particular,
      build-folder
      is never
      dist
      ).
    • conformance-tests-folder
      conformance-tests-dest
      .
    • copy-conformance-tests: true
      requires
      conformance-tests-script
      .
    • log-file-name
      is set ⇒
      log-to-file
      is not
      false
      .
    • All
      *-script
      paths resolve on disk (absolute → relative to config dir → relative to renderer dir).
    • No script path crosses stacks (e.g.
      backend/config.yaml
      must not reference
      run_unittests_js.sh
      ).
针对每个部分:
  1. 从空键集开始。
  2. 添加
    unittests-script: test_scripts/run_unittests_<lang>.<sh|ps1>
    ——必填项。如果脚本尚未存在,请停止并告知调用者先运行
    implement-unit-testing-script
  3. 如果该部分磁盘上有一致性脚本→添加
    conformance-tests-script: …
  4. 如果该部分磁盘上有环境准备脚本→首先验证是否也添加了
    conformance-tests-script
    ;如果没有,请停止并向用户说明此问题(提供两种选择:要么通过
    implement-conformance-testing-script
    生成缺失的一致性脚本,要么移除环境准备脚本)。
  5. 如果项目有共享模板→添加
    template-dir: template
    (或用户使用的任何路径)。
  6. 始终添加
    build-dest: dist
    。此技能会在它编写的每个配置中固定复制目标,无论第三阶段对此有何说明。如果第三阶段明确要求使用不同的
    build-dest
    ,请停止并向用户说明冲突——不要静默覆盖。
  7. 对于有效键参考中的其他每个键,仅当第三阶段做出了非默认决策时才包含它。
  8. 交叉验证组装的键集:
    • build-dest
      设置为
      dist
    • build-folder
      build-dest
      (特别是
      build-folder
      绝不能是
      dist
      )。
    • conformance-tests-folder
      conformance-tests-dest
    • copy-conformance-tests: true
      需要
      conformance-tests-script
    • 设置了
      log-file-name
      log-to-file
      不为
      false
    • 所有
      *-script
      路径在磁盘上都可解析(绝对路径→相对于配置目录的路径→相对于渲染器目录的路径)。
    • 脚本路径不跨栈(例如
      backend/config.yaml
      不得引用
      run_unittests_js.sh
      )。

Step 3 — Emit
config.yaml

步骤3 — 生成
config.yaml

For each part, write a clean YAML file:
  • One key per line, in the order they appear in Valid keys reference (script paths first, then template/build folders, then copy/log settings).
  • Use dashed key names. Quote string values only when YAML requires it.
  • No comments inside the file — keep it machine-parseable. If the user needs a comment, put it in the surrounding spec or README.
  • Idempotent: re-running this skill on an unchanged project produces a byte-for-byte identical file.
Example for a single-stack Python project with conformance testing and a prepare-environment script:
unittests-script: test_scripts/run_unittests_python.sh
conformance-tests-script: test_scripts/run_conformance_tests_python.sh
prepare-environment-script: test_scripts/prepare_environment_python.sh
template-dir: template
build-dest: dist
Example for a multi-part project (
backend/config.yaml
):
unittests-script: test_scripts/run_unittests_python.sh
conformance-tests-script: test_scripts/run_conformance_tests_python.sh
template-dir: ../template
build-dest: dist
针对每个部分,编写一个整洁的YAML文件:
  • 每行一个键,按有效键参考中的顺序排列(首先是脚本路径,然后是模板/构建文件夹,最后是复制/日志设置)。
  • 使用短横线形式的键名。仅当YAML要求时才对字符串值加引号。
  • 文件内无注释——保持机器可解析。如果用户需要注释,请将其放在相关规范或README中。
  • 幂等性:在未更改的项目上重新运行此技能会生成完全相同的文件。
以下是一个带有一致性测试和环境准备脚本的单栈Python项目示例:
unittests-script: test_scripts/run_unittests_python.sh
conformance-tests-script: test_scripts/run_conformance_tests_python.sh
prepare-environment-script: test_scripts/prepare_environment_python.sh
template-dir: template
build-dest: dist
多部分项目示例(
backend/config.yaml
):
unittests-script: test_scripts/run_unittests_python.sh
conformance-tests-script: test_scripts/run_conformance_tests_python.sh
template-dir: ../template
build-dest: dist

Step 4 — Hand off

步骤4 — 任务委托

Tell the caller exactly which file(s) were written and invoke
plain-healthcheck
to validate the project end-to-end. Do not declare success on your own —
plain-healthcheck
is the source of truth for "is this project ready to render?".
告知调用者确切生成了哪些文件,并调用
plain-healthcheck
来端到端验证项目。不要自行宣告成功——
plain-healthcheck
是“项目是否准备好渲染”的唯一权威。

Anti-patterns

反模式

  • Inventing values for keys the user never decided on. Leave them out and let the renderer use its default.
  • Mixing stacks in one config.
    backend/config.yaml
    referencing a JS script is always a bug — split into per-part configs instead.
  • Putting
    api-key
    ,
    dry-run
    ,
    full-plain
    ,
    render-range
    ,
    render-from
    ,
    replay-with
    ,
    config-name
    , or
    filename
    in
    config.yaml
    .
    All of these are per-invocation or secret; the renderer treats them as command-line concerns.
  • Emitting
    prepare-environment-script
    without
    conformance-tests-script
    .
    A prepare-environment script only makes sense in service of conformance tests; without one,
    plain-healthcheck
    will fail.
  • Hand-merging into an existing config.yaml without re-running this skill. If the user edited the config manually, re-run the skill to re-derive a clean canonical version (after confirming any custom fields with the user).
  • Reading the renderer's API key from a project file. Always rely on
    CODEPLAIN_API_KEY
    .
  • 为用户从未做出决策的键生成值。忽略这些键,让渲染器使用默认值。
  • 在一个配置中混合不同栈
    backend/config.yaml
    引用JS脚本永远是错误的——改为按部分拆分配置。
  • api-key
    dry-run
    full-plain
    render-range
    render-from
    replay-with
    config-name
    filename
    放入
    config.yaml
    。这些都是每次调用专属或保密的;渲染器将它们视为命令行相关的内容。
  • 在未设置
    conformance-tests-script
    的情况下生成
    prepare-environment-script
    。环境准备脚本仅在为一致性测试服务时有意义;如果没有一致性测试,
    plain-healthcheck
    会失败。
  • 不重新运行此技能就手动合并到现有
    config.yaml
    。如果用户手动编辑了配置,请重新运行此技能以重新生成整洁的标准版本(在与用户确认任何自定义字段后)。
  • 从项目文件中读取渲染器的API密钥。始终依赖
    CODEPLAIN_API_KEY

Validation Checklist

验证检查清单

  • One
    config.yaml
    exists per part of the system (single-stack → root; multi-part → per part).
  • Every
    config.yaml
    has at minimum
    unittests-script
    .
  • Every
    *-script
    value points at a file that exists on disk.
  • No
    config.yaml
    declares
    prepare-environment-script
    without also declaring
    conformance-tests-script
    .
  • No
    config.yaml
    mixes stacks (every script in it targets the same language).
  • build-dest
    is set to
    dist
    in every emitted
    config.yaml
    .
  • build-folder
    build-dest
    ;
    conformance-tests-folder
    conformance-tests-dest
    .
  • copy-conformance-tests: true
    only when
    conformance-tests-script
    is set.
  • log-file-name
    only when
    log-to-file
    is not
    false
    .
  • No forbidden keys (
    api-key
    ,
    dry-run
    ,
    full-plain
    ,
    render-range
    ,
    render-from
    ,
    replay-with
    ,
    config-name
    ,
    filename
    ).
  • template-dir
    set whenever the project has shared templates or import modules.
  • plain-healthcheck
    returned
    PASS
    after the config(s) were written.
  • 系统的每个部分都有一个
    config.yaml
    (单栈→根目录;多部分→每个部分对应一个)。
  • 每个
    config.yaml
    至少包含
    unittests-script
  • 每个
    *-script
    值都指向磁盘上存在的文件。
  • 没有
    config.yaml
    在未声明
    conformance-tests-script
    的情况下声明
    prepare-environment-script
  • 没有
    config.yaml
    混合不同栈(其中的所有脚本都针对同一种语言)。
  • 每个生成的
    config.yaml
    build-dest
    都设置为
    dist
  • build-folder
    build-dest
    conformance-tests-folder
    conformance-tests-dest
  • 仅当设置了
    conformance-tests-script
    时才设置
    copy-conformance-tests: true
  • 仅当
    log-to-file
    不为
    false
    时才设置
    log-file-name
  • 没有禁用的键(
    api-key
    dry-run
    full-plain
    render-range
    render-from
    replay-with
    config-name
    filename
    )。
  • 当项目有共享模板或导入模块时设置
    template-dir
  • 配置文件生成后
    plain-healthcheck
    返回
    PASS