pythia-apply

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Applying PL/SQL Changes

应用PL/SQL变更

Announce at start: "Using pythia-apply — I'll preview the change first."
DDL in Oracle commits itself. There is no transaction to roll back — the snapshot pythia takes before writing is the only undo that exists. This skill exists so that safety net is always used, and used honestly.
开始时告知: "正在使用pythia-apply —— 我会先预览变更内容。"
Oracle中的DDL会自动提交事务,没有回滚机制——pythia在写入前创建的快照是唯一的撤销手段。本技能的存在就是为了确保这一安全网被始终、如实地使用。

The Iron Law

铁律

NO WRITE THE DEVELOPER HAS NOT SEEN AND APPROVED
Applies to every write: new objects, fixes, restores, batch runs. No exceptions for "trivial" changes — a one-line change can invalidate twelve dependents.
Three moves are FORBIDDEN for agents, and the CLI enforces the first two (no terminal attached → refusal):
  • --yes
    — it is the developer's flag, never yours.
  • pythia policy set <group>
    to anything LOOSER — loosening policy is the developer's decision; hand them the exact command to run themselves.
  • Passing
    --confirm
    in the same turn as the preview. The preview ends your turn; the token is only used after the developer's approval arrives as a NEW message.
NO WRITE THE DEVELOPER HAS NOT SEEN AND APPROVED
适用于所有写入操作:新对象、修复、恢复、批量执行。即使是“微小”变更也不例外——一行代码的变更可能会导致十二个依赖项失效。
以下三种操作对Agent是严格禁止的,且CLI会强制执行前两项(无终端连接则拒绝执行):
  • --yes
    —— 这是开发者专属的参数,绝不能由Agent使用。
  • 使用
    pythia policy set <group>
    将策略设置为更宽松的级别——调整策略是开发者的决策,应将精确的命令交给开发者自行执行。
  • 在预览的同一轮操作中传递
    --confirm
    参数。预览结束即完成当前轮次,仅当开发者的确认以新消息形式送达后,才能使用令牌执行操作。

When the change will NOT go through apply

无需通过apply执行变更的场景

Sometimes the developer runs the file themselves — a DBA executes it, a release process owns it, or policy denies the group. The preview still ran, so a rollback file for the version currently live already exists at
.pythia/journal/<entry>/restore.sql
. Never let a change leave your hands for manual execution without naming that path in the same message as the .sql file.
pythia history <OBJECT>
lists every captured version.
有时开发者会自行运行文件——比如由DBA执行、归发布流程管控,或策略拒绝该组执行。此时预览仍会运行,因此当前线上版本的回滚文件已存在于
.pythia/journal/<entry>/restore.sql
。绝不能让变更脱离你的管控进行手动执行,必须在发送.sql文件的同一条消息中指明该路径。
pythia history <OBJECT>
会列出所有已捕获的版本。

The Workflow

工作流程

Before step 1: if this conversation has not yet seen a standalone impact analysis for this object, run
pythia-impact
first. The
impact:
line inside apply's preview is confirmation of a number you already knew — if it is the first time anyone sees it, a step was skipped.
  1. Preview. Run
    pythia apply <file>
    . This writes nothing: it snapshots, computes impact, prints a diff, a warning block, and a confirm token.
  2. Relay the preview to the developer — verbatim. Show the diff, the
    impact:
    line, and any
    !
    warning exactly as printed. Do not summarize the diff away; the developer approves what they see, not your paraphrase.
  3. Wait for an explicit yes. A yes is an instruction to proceed with THIS preview: "yes, apply it", "go ahead", "looks good — do it". Not a yes: a compliment without a go-ahead, a question, silence, or an approval that was given for an earlier preview. If the developer changes the file instead, start over at step 1.
  4. Apply by running the exact
    To apply:
    command pythia printed (it contains the token). If pythia says the token is stale, the file or the database changed since the preview — go back to step 1, never "retry". If the fresh preview's before-side no longer matches what you last saw, say so explicitly: someone else may have changed the object on this shared database, and the developer must know that before approving.
  5. Read the exit code — it is the verdict. Never through a pipe:
    apply … | tail
    returns tail's code, always 0. Unpiped, or
    ${PIPESTATUS[0]}
    .
    ExitMeaningWhat you must do
    0applied, compiled clean, nothing newly INVALIDreport done, mention the restore id
    1refused (policy, classification, stale token)relay the printed reason and its fix; do not work around it
    3written but broken — compile errors or other objects now INVALIDsee below
  6. On exit 3, never report success. Say plainly that the change went in and broke something, show the compile errors (line:col) and the list of newly INVALID objects, and offer the
    To undo:
    command pythia printed. Fixing forward is allowed only after the developer sees this state.
步骤1之前: 如果本次对话尚未针对该对象进行独立的影响分析,请先运行
pythia-impact
。apply预览中的
impact:
行是对已知数值的确认——如果这是首次出现该数值,则说明跳过了某个步骤。
  1. 预览:运行
    pythia apply <file>
    。此操作不会写入任何内容:它会创建快照、计算影响、打印差异、警告块以及确认令牌。
  2. 将预览内容原封不动传达给开发者:完整展示差异、
    impact:
    行以及所有
    !
    警告信息。不要总结差异内容——开发者确认的是他们看到的内容,而非你的转述。
  3. 等待明确的确认:确认需明确指示执行本次预览的变更:"是的,执行它"、"继续"、"看起来没问题——执行吧"。以下情况不算确认:无执行指令的赞美、问题、沉默,或针对之前预览的确认。如果开发者修改了文件,请回到步骤1重新开始。
  4. 执行:运行pythia打印的精确
    To apply:
    命令(包含令牌)。如果pythia提示令牌已过期,说明自预览以来文件或数据库已发生变更——回到步骤1,绝不要“重试”。如果新预览的前置状态与你上次看到的不一致,请明确告知开发者:可能有其他人在这个共享数据库上修改了该对象,开发者必须在确认前知晓这一点。
  5. 读取退出码——这是最终结果。绝不要通过管道读取:
    apply … | tail
    返回的是tail的退出码,始终为0。应直接运行,或使用
    ${PIPESTATUS[0]}
    获取pythia的退出码。
    退出码含义必须执行的操作
    0已应用,编译无错误,无新增失效对象报告完成,并提及恢复ID
    1被拒绝(策略、分类、令牌过期)传达打印的原因及修复方法;不要绕过规则
    3已写入但存在问题 —— 编译错误或其他对象现在失效见下文
  6. 若退出码为3,绝不要报告成功:明确告知开发者变更已部署但引发了问题,展示编译错误(行:列)以及新增失效对象的列表,并提供pythia打印的
    To undo:
    命令。只有在开发者看到当前状态后,才能进行后续修复。

Restores

恢复操作

pythia journal restore <id>
is itself a write and goes through the same six steps and the same gate: preview the reverse diff to the developer, wait for yes, then confirm. Note: restoring an object that did not exist before means DROP — policy will refuse it under
structural: deny
, and that refusal is correct; relay it instead of forcing a way around.
pythia journal restore <id>
本身属于写入操作,需遵循相同的六步流程和把关机制:向开发者预览反向差异,等待确认后再执行。注意:恢复之前不存在的对象意味着执行DROP操作——策略会在
structural: deny
规则下拒绝该操作,这种拒绝是合理的,应传达给开发者而非强行绕过。

Batch mode

批量模式

--yes
skips the pause, not the preview — output and journal are identical. Use it only when the developer explicitly asked for unattended application ("apply all of these"). A frustrated "stop asking" grants
--yes
for the task at hand, not from now on: confirm the scope once ("this batch, or standing?") and default to this-batch-only. A standing
--yes
never extends to restores. Rules for a batch:
  • Stop at the first exit 3. Never keep applying onto a broken state.
  • Afterwards report: one line per success, full detail (errors, newly INVALID, restore command) for the failure, and the exact list of files that were NOT applied because the batch stopped.
--yes
参数会跳过等待环节,但不会跳过预览——输出和日志内容与正常模式一致。仅当开发者明确要求无人值守部署时(如“全部应用这些变更”)才能使用该参数。如果开发者不耐烦地说“别再问了”,仅授予当前任务的
--yes
权限,而非永久权限:需确认一次范围(“仅本次批量任务,还是永久生效?”),默认仅适用于本次批量任务。永久的
--yes
权限绝不扩展到恢复操作。批量任务规则:
  • 遇到第一个退出码3时立即停止:绝不要在已有问题的状态下继续部署。
  • 之后报告:每个成功项用一行说明,失败项需提供完整详情(错误信息、新增失效对象、恢复命令),并列出因批量任务停止而未应用的文件的精确列表。

Never bypass the write path

绝不要绕过写入路径

When
pythia apply
is available, do not write through anything else — not SQLcl MCP
run-sql
, not
sqlplus
, not a driver script. Those paths have no snapshot, no impact preview, no verify, no journal. If apply refuses a statement, that refusal is information for the developer, not an obstacle to route around.
pythia apply
可用时,不要通过其他方式写入——不要使用SQLcl MCP
run-sql
sqlplus
或驱动脚本。这些路径没有快照、影响预览、验证和日志功能。如果apply拒绝某条语句,这种拒绝是给开发者的信息,而非需要绕过的障碍。

Is rollback real? Be honest about it

回滚是否真的可行?请如实告知

GroupIs rollback real?
plsql_source
Yes — completely. The source is recoverable from
ALL_SOURCE
.
data_dml
No. After commit only Flashback Query remains, and only within undo retention.
structural
Almost never.
DROP COLUMN
is permanent; a dropped table may be in the Recycle Bin.
grants
Yes, but by hand.
session
Not needed.
Never promise "we can always roll back" — that sentence is only true for the first row, and saying it generally misleads the developer at the exact moment the stakes are highest.
分组回滚是否可行?
plsql_source
完全可行。可从
ALL_SOURCE
恢复源代码。
data_dml
不可行。提交后仅能通过闪回查询恢复,且仅在 undo 保留期内有效。
structural
几乎不可行
DROP COLUMN
是永久操作;被删除的表可能存在于回收站中。
grants
可行,但需手动操作。
session
无需回滚。
绝不要承诺“我们总能回滚”——这句话仅对第一行的分组成立,泛泛而谈会在风险最高的时刻误导开发者。

Red Flags — STOP if you catch yourself thinking

危险信号——如果你有以下想法,请立即停止

ThoughtReality
"It's a tiny change, skip the preview"Tiny changes invalidate dependents too. Preview.
"The dev approved something like this earlier"Approval is per-preview, not per-topic. Ask again.
"Exit 3, but my part compiled — report done"Something is broken that was not. That is not done.
"Token is stale, I'll just take the new one"The content changed. The developer must see the new preview.
"apply refused it; run-sql will take it"The refusal is the product working. Relay it.
"I'll restore quietly to clean up my mistake"Restores are writes. Same gate, same visibility.
"
$?
said 0 after I piped to tail"
That was tail's 0. Read pythia's own words, or its unpiped code.
"The dev said 'stop asking' once"That covered that task, not forever. Re-confirm scope on the next one.
想法实际情况
"这是个微小的变更,跳过预览吧"微小变更也会导致依赖项失效。必须预览。
"开发者之前已经批准过类似的变更了"确认是针对每次预览的,而非针对主题。必须再次询问。
"退出码是3,但我负责的部分编译成功了——报告完成"某些原本正常的内容现在失效了,这不算完成。
"令牌过期了,我直接用新的就行"内容已发生变更。开发者必须查看新的预览。
"apply拒绝了它;用run-sql应该能行"拒绝是工具正常工作的表现。应传达该信息。
"我悄悄恢复来清理自己的错误"恢复属于写入操作。需遵循相同的把关机制和可见性要求。
"我用管道输出到tail后,
$?
显示0"
那是tail的退出码0。应查看pythia的输出内容,或直接运行获取其退出码。
"开发者说过一次‘别再问了’"那仅适用于当时的任务,而非永久生效。下次任务需重新确认范围。

When NOT to use this skill

无需使用本技能的场景

  • Reading or exploring — use
    pythia-explore
    .
  • Judging blast radius before editing — use
    pythia-impact
    (always run it before proposing a change; apply's preview is confirmation, not discovery).
  • Editing files the developer has not asked to land on the database yet.
Invocation note: examples say
pythia ...
; run it however this project provides it (for example
python scripts/pythia.py ...
). Every pythia output prints follow-up commands in the correct form — prefer pasting those.
  • 读取或探索数据库——使用
    pythia-explore
  • 在编辑前评估影响范围——使用
    pythia-impact
    (提出变更前必须运行;apply的预览是确认,而非发现)。
  • 编辑开发者尚未要求部署到数据库的文件。
调用说明:示例中使用
pythia ...
;请根据项目的实际提供方式运行(例如
python scripts/pythia.py ...
)。每个pythia输出都会以正确格式打印后续命令——优先粘贴这些命令。