Convert natural-language and LaTeX quantum field theory calculation requests into Package-X Mathematica code (`.wl` files). Supports analytic calculations for tree-level diagrams and one-loop Feynman integrals. Trigger when the user mentions Package-X, one-loop calculations, one-loop, loop integral, tree diagram, tree-level, Feynman integral, Lagrangian, LoopIntegrate, LoopRefine, Spur, DiracMatrix, FermionLine, Projector, Contract, Passarino-Veltman, self-energy, vacuum polarization, vertex correction, anomalous magnetic moment, decay rate, decay width, form factor, scattering cross section, Wilson coefficient, or Dirac trace.
Installation
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Benchmark Isolation Hard Constraint. Literature formulas, known limits, and
numerical test points in model/benchmarks.json may only be used for
after-the-fact validation in Step 4.7. They must not be used as the source for
generating coreResult, finalResult, or result-python.py, and must not be
read before the first draft of result.wl is complete. If current Package-X
support boundaries force the use of a literature formula or manual limiting
formula, calculation_provenance must be marked as
literature_formula_imported or manual_tree_algebra, not as
package_x_derived, and this must be stated explicitly in provenance_notes
and result-summary.md.
In batch reruns, unless the current user message or orchestrator call explicitly
requests "use the literature/benchmark formula as a fallback backend", the
fallback must not be written as a usable backend; instead output
calculation_provenance = "blocked" and translation_status = "failed".
allow_formula_fallback=true in a hep-numerics scan-config only permits
numerics to run an existing fallback backend; it does not authorize
package-scribe to generate a fallback backend.
Static derivation evidence is necessary but not sufficient. A
package_x_derived result must bind the final result.wl and
result-python.py bytes, the executable Package-X-to-result-symbol dataflow,
and the Python function interface in result-meta.json.derivation_evidence.
Method names in prose, comments, strings, or dead If[False, ...] branches are
not evidence. Phase 0 can validate this structure statically, but it cannot
mechanically prove that the Wolfram result was executed and translated into the
Python backend without substitution. Consequently a reproduction comparator
must conservatively classify even a statically valid package_x_derived
result as unknown with reason derivation_evidence_not_runtime_verified and
cap a positive comparison at needs_human_review. Do not describe static
validation alone as an independent reproduction.
Generated code uses full \[Name] forms (not notebook glyphs) and English comments.
Work step by step. Do not jump directly to code. Execute the steps below in
order, moving to the next step only after the current step is complete.
Workflow
Step 0 — Determine Delivery Mode (batch vs interactive)
Before Step 1, determine whether this invocation is batch mode or
interactive mode. Classification rule (scheme A, explicitly triggered by
task_id):
batch mode: the user message or orchestrator call explicitly specifies
a task_id (for example, "run task-001", "execute task-002 in
calc-tasks.json", or the orchestrator passes task_id=task-001). When entering
batch mode, the current working directory should be under a
workspace/projects/{project-name}/ so the relative path
model/calc-tasks.json resolves.
interactive mode: the user did not specify task_id; follow the original
interactive flow.
If interactive mode -> jump to Step 1 and follow the original flow. Later,
Step 4.5 also uses the interactive branch (output under
workspace/package-scribe/package-resultNNN/).
If batch mode -> execute the Step 0 substeps below, then jump to Step 2
(skipping the interactive questions in Step 1). Step 4.5 also uses the batch
branch.
Step 0.1 — Read The Task Definition
Read model/calc-tasks.json from the current project workspace and find the
entry in tasks[] matching task_id. If no entry is found, immediately report
the error to the user/orchestrator and exit (without creating any output
directory).
Read and remember the following fields from that task object as this
calculation's "requirements":
type (tree / loop) and loop_order
process (natural-language process description)
lagrangian_terms (list of interaction terms)
external_particles (incoming / outgoing / virtual_boson / mediator; each
entry contains particle and momentum)
on_shell (boolean, determines whether to write on-shell replacements in the
.wl code)
convention_overrides (if present, applies only to this task; otherwise use
the global conventions from model-spec)
notes (background information only; does not affect code generation)
The "calculation type / target / external lines / kinematics / result level"
that Step 1 would normally ask the user about is now read entirely from this
task object; do not ask again.
Step 0.2 — Read Model Context
Read from model/model-spec.json in the same project:
conventions (gauge / momentum_flow / gamma5_scheme / metric_signature) ->
unless the current task has convention_overrides, these are the global
conventions used for this calculation. Write these conventions explicitly
into the "conventions / assumptions used" section of request.md.
fields[]: for non-standard SM particle names appearing on task external
lines or inside loops (for example Zp), look up spin /
quantum_numbers / mass_parameter / propagator_note in fields[]; use
them for propagators and mass variables in the .wl code.
interactions[]: for each interaction term in task lagrangian_terms, match
the corresponding entry in interactions[] and read lorentz_structure /
chirality / coupling / feynman_rule_note. feynman_rule_note is a
natural-language description of the vertex factor (for example
"vertex factor: -i g' gamma^mu"), used as the starting point and cross-check
for deriving Feynman rules in Step 2.
parameters[]: collect the canonical name and LaTeX form of every parameter
that will appear in this .wl code for code-variable naming; parameter names
must remain canonical names and must not be rewritten.
Note: interactions and fields in model-spec.json provide semi-structured
model information, not fully mechanized Feynman rules. package-scribe still uses
its own Step 2 logic (and for custom Lagrangians, the
references/custom-lagrangian-validation.md flow) to derive complete Feynman
rules. The role of model-spec.json is to provide enough context for
package-scribe to skip asking the user.
Step 0.3 — Record Benchmark Availability (if any)
Only check whether model/benchmarks.json exists in the same project and
whether it contains an entry for the current task_id; do not read that entry's
formula_latex, formula_description, known_limits, numerical_test_point,
sources, or notes. If the file does not exist, record
benchmark_available = false and continue (Step 4.7 will set
benchmark_status = "no_benchmark" accordingly).
If the file exists, only find the task_id-matching entry in benchmarks[] and
record:
Found and has_benchmark = true -> benchmark_available = true
Found but has_benchmark = false -> benchmark_available = false
No matching task_id -> benchmark_available = false
Do not keep the benchmark entry in context for Step 2 through Step 4.6.
Step 4.7 re-reads the concrete benchmark formula and numerical point only after
the first drafts of result.wl, result-python.py, and result-meta.json are
complete. This ensures that literature formulas cannot leak into the
calculation backend.
Step 0.4 — Determine Output Directory
In batch mode, the output directory is fixed to calculations/{task_id}/
(relative to workspace/projects/{project-name}/) and
scripts/next_package_result_dir.py is not called.
If that directory already exists (for example when rerunning a task), use this
policy:
If the directory already has result-meta.json and its
depends_on.model_version matches the current manifest active_model_version
-> treat this as recomputation, but preserve it unchanged as the last-good
result until the replacement attempt is complete and validated
If the version does not match -> report staleness to the user/orchestrator
before creating the replacement attempt and proceed only after confirmation
Never generate or edit batch artifacts directly in this canonical directory.
Step 4.5 allocates a private owned attempt; Step 4.7.4 validates and atomically
publishes the complete task tree together with its manifest status/history
update. A generation, validation, or publication failure leaves the canonical
task directory and manifest at their prior coherent generation.
Batch mode does not use the independent-mode numbering mechanism under
workspace/package-scribe/package-resultNNN/.
After completing Step 0 -> jump to Step 2 (get Feynman rules).
Step 1 — Understand The Request And Classify Tree / Loop
Confirm the following information item by item:
Calculation type: tree diagram or one-loop?
Tree signals: decay width, scattering cross section, "tree-level",
"leading order", no loop diagram described
Calculation target: decay width? cross section? form factor? self-energy
function? or only an intermediate structure / Package-X output?
Theory framework: QED / QCD / Standard Model / Yukawa / user-defined?
External particles: which particles, on-shell or off-shell?
Kinematic conditions: on-shell conditions for external momenta (p² = m²?
p² = 0? general p²?)
Result level: does the user want coreResult (intermediate structure),
finalResult (final physical quantity), or both?
Delivery mode: ordinary result generation, or verification/comparison
mode?
Ordinary result generation signals: the user asks for code, amplitude, cross
section, decay width, form factor, or final result
Verification/comparison signals: the user explicitly says "verify", "check",
"compare", "compare with expected result", "pass/fail", or "compare with a
tutorial/literature result"
Default delivery-mode rules:
If the user did not explicitly request verification/comparison:
Default to "ordinary result generation mode"
Do not proactively perform an independent analytic comparison, tutorial
comparison, literature comparison, or repository-example comparison
Do not organize an extra verification branch for this
Only if the user explicitly requests verification/comparison:
Enter "verification/comparison mode"
Then comparison checks, pass/fail judgments, or similar verification outputs
are allowed
If the wording is ambiguous: first interpret it as ordinary result generation;
switch to verification/comparison mode only when the user clearly makes a
"comparison check" part of the deliverable target
Additional items to confirm for loop diagrams (skip for tree diagrams):
Loop particles: which propagators are in the loop? What are their masses?
Gauge choice: Feynman gauge (ξ=1) is the default; keep ξ if the user asks
for a general covariant gauge
Final form: analytic expression? numerical evaluation? series expansion?
If information is insufficient, ask first; do not assume.
After classification, enter the corresponding branch:
Decide the source of Feynman rules according to the theory framework:
Case A — Standard theories (QED / QCD / SM / Yukawa):
-> First read the "validation boundary" table at the beginning of
references/standard-theories.md, then read the matching section:
After reading, first determine which support level the request falls into:
Validated by examples -> may continue generating code, but first
explicitly state the default convention used in the analysis
Formula written clearly, no end-to-end example yet -> do not generate
directly without notice; first tell the user your recommended default
convention, continue after confirmation, and mark in the output that
repository-level end-to-end validation has not been performed
This file does not fully specify the complete formula -> do not
continue based only on standard-theories.md; first tell the user the current
documentation is not closed enough, and stop at clarification unless the user
supplies an explicit Lagrangian / vertex convention
Syntax-level support -> suitable only for generating structural scaffolding
or tree-level / four-dimensional intermediate results; for scheme-sensitive
one-loop calculations, do not automatically generate directly
Default recommended conventions (offer as the suggested option when the user
has not specified):
Feynman gauge
All vertex momenta are incoming by default
External lines are on-shell according to the problem statement; if unclear,
first warn and confirm
Coupling constants, the overall i, closed-fermion-loop -1, and color
factors are factored out separately and not hidden inside the Package-X
numerator
For the SM electroweak sector, default to the field definitions and overall
sign conventions documented in references/standard-theories.md
If flavor structure exists but the user has not specified it, first use the
simplest consistent choice (such as diagonal CKM or relevant element set to 1)
and state it explicitly
Cases where you must ask and provide a recommended option:
\[Gamma]5 / regularization scheme
Whether to include Goldstone / ghost diagrams in a general R_\[Xi] gauge
Whether flavor / CKM should keep off-diagonal elements
Whether external lines are strictly on-shell
Whether to keep a general gauge parameter \[Xi] or set Feynman gauge directly
Wording requirements when asking the user:
Do not merely ask "Which convention do you want?"
Directly give your recommended default option
Recommended wording: If you have no special preference, I suggest proceeding
with {recommended convention}; if you agree, I will generate the code with
that convention; if you want a different convention, I will switch
Case B — User-defined Lagrangian:
-> Do not readstandard-theories.md
-> First read references/custom-lagrangian-validation.md
-> First provide a short validation summary:
Validation verdict + Scope + Assumptions I will use + Warnings + Can proceed with
-> If BLOCKED: close with Why blocked / What I need from you; if there is an
obviously reasonable default path, add Suggested default if you want me to proceed
-> If not BLOCKED: then read references/packagex-reference.md §5
(custom-theory translation rules)
-> Derive Feynman rules from the Lagrangian:
Expand interaction terms in the Lagrangian
For each vertex: read particle content, Lorentz structure, chiral
structure, and coupling constants
Decide whether this request really needs propagator / quadratic-term
information for new particles
Translate to Package-X input format
Explicitly state every continuing assumption in the analysis
Case C — Standard theory + new-physics correction:
-> Read standard-theories.md for the standard part (again first checking the
"validation boundary" table)
-> For the new-physics part, first read references/custom-lagrangian-validation.md
-> Continue with the Case B translation method only if the new-physics part is
not BLOCKED
Step 3A — Tree Diagram: Determine Calculation Strategy
The core of tree-level calculation is Spur (Dirac trace) and Contract
(index contraction).
Typical tree-level workflow:
Write the amplitude iM (applying Feynman rules)
Compute |M|²:
Sum final-state spins -> replace spinor bilinears with completeness
relations
Average over initial-state spins/helicities
Sum polarization vectors: massive bosons use -g_μν + k_μk_ν/m²; massless
bosons use -g_μν (Feynman gauge)
Obtain the Dirac trace -> compute it with Spur
Use Contract to contract remaining Lorentz indices
Apply on-shell conditions (/. rules)
Use LoopRefine to safely take d -> 4 (do not manually replace d -> 4)
Substitute kinematics and compute the decay width or cross section
Read examples/tutorial-examples.md §0 (Z→ff̄ tree example) as a reference.
For electroweak left-handed-current tree diagrams (such as Wff'), also read
examples/electroweak-minimal-examples.md §EW1.
For electroweak neutral-current tree diagrams (such as the A/Z s-channel in
e^+ e^- -> \mu^+ \mu^-), also read
examples/electroweak-minimal-examples.md §EW2.
Step 3B — Loop Diagram: Choose The Dirac Algebra Method
Decision flow (in order; stop at the first match):
Fermions involved?
├── No → construct the integrand directly and jump to Step 4
└── Yes
├── Closed loop (trace)?
│ └── Yes → Spur
└── Open line
├── External fermions on-shell?
│ ├── No → DiracMatrix + FermionLineExpand
│ └── Yes
│ ├── Need to extract form factors?
│ │ └── Yes → Projector ("F1", "F2", "G1", "G2", etc.; see §1.7)
│ └── No → FermionLine (u/v spinors)
Case
Function
Typical calculation
Reference example
Closed fermion loop
Spur
Vacuum polarization, H→gg
examples/tutorial-examples.md §1, §2
Off-shell open fermion line
DiracMatrix
Self-energy
examples/tutorial-examples.md §3
On-shell open fermion line
FermionLine
QCD vertex correction
examples/tutorial-examples.md §5
Form-factor extraction
Projector
g-2
examples/tutorial-examples.md §4
Pure bosonic loop
none (write directly)
Scalar self-coupling
—
Step 4 — Write Code
Read references/packagex-reference.md to confirm syntax and common output
objects, section by section:
Organize code using the "Code Output Templates" structure below. Unless the user
explicitly says not to provide code, default to delivering a complete runnable
.wl file rather than only reporting formulas or numbers.
Step 4.5 — Create The Result Directory For This Request
For every new package-scribe request, save the artifacts under a determined
result directory before giving the final response. The exact directory is
classified by the Step 0 mode into two cases:
Step 4.5 (batch mode)
Step 0 has fixed the final output directory as
workspace/projects/{project-name}/calculations/{task_id}/, but generation
must occur only in a new owned attempt directory.
Creation procedure:
Do not create, initialize, or edit "$taskDir" directly.
Run the initializer in JSON mode:
allocation=$(python3 scripts/init_package_result_files.py --task-dir "$taskDir" --format json).
It atomically reserves an attempt below the project-local
.hep-workflow-package-attempts/ root without changing "$taskDir".
Parse path as resultDir and attempt_id as attemptId without eval,
using the same python3 -c 'import json,sys; ...' pattern as the interactive
branch below. All Step 4 through Step 4.7 edits and executions use this
private resultDir.
If the current conclusion is BLOCKED, instead use
python3 scripts/init_package_result_files.py --task-dir "$taskDir" --blocked --format json.
A blocked attempt is diagnostic-only and must not be finalized over a prior
good task result.
In batch mode, do not call next_package_result_dir.py
In the batch branch, the "original user request" section of request.md is
generated from the task object: write the task title, process,
lagrangian_terms, external_particles, and target_quantity, and note at the
beginning: Batch mode: task_id = {task_id}. The "conventions / assumptions
used" section must list the global conventions read in Step 0.2 (and
convention_overrides, if this task overrides them).
Step 4.5 (interactive mode)
Allocate a new numbered directory under
workspace/package-scribe/package-resultNNN/ in the current repository:
First run the allocator in JSON mode:
allocation=$(python3 scripts/next_package_result_dir.py --format json "$PWD").
Read both path and attempt_id from that JSON; do not discard the ownership
token. For shell execution, parse them without eval, for example:
resultDir=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["path"])' "$allocation")
and
attemptId=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["attempt_id"])' "$allocation").
Then run
python3 scripts/init_package_result_files.py "$resultDir" --attempt-id "$attemptId"
to initialize
the request.md / result-summary.md / run-instructions.md skeletons
If the current conclusion is BLOCKED, instead use
python3 scripts/init_package_result_files.py "$resultDir" --attempt-id "$attemptId" --blocked
Here "$PWD" may be the repository root or the root of the workspace project
currently being processed; next_package_result_dir.py walks upward to locate
the repository root and always writes under workspace/package-scribe/
Do not overwrite existing result directories
A failed allocator-owned initialization may be resumed only with the same
attempt token. Missing/corrupt reservation metadata remains occupied; never
infer ownership from an empty directory.
Step 4.5 Common Part (shared by both modes)
After all result files are completed and before the final user response, run
the script in the current skill directory. In interactive mode run
python3 scripts/check_package_result_placeholders.py "$resultDir". In batch
mode the finalizer in Step 4.7.4 performs the placeholder check after it
mechanically replaces the temporary input-provenance sentinel; do not run
the standalone checker against the pre-finalization sentinel.
The initialization script copies skeletons from templates/*.tmpl and
pre-fills deterministic information such as generated at, result directory
paths, and default run commands
To use a Wolfram executable that is not available as wolframscript on
PATH, set WOLFRAMSCRIPT_BIN to its exact executable path before running
the initialization script. Do not include flags or shell syntax.
Every result directory should contain at least:
request.md
Original user request (task-object summary in batch mode)
Conventions / assumptions used for this request
For custom Lagrangians: validation verdict
For standard theories: support status / verification boundary
result.wl
Complete runnable Package-X code
result-summary.md
Physics analysis
coreResult / prefactor / finalResult
If the main output is not the final physical quantity, clearly state what is
still missing
In batch mode, append an additional ## Benchmark Verification section
(see Step 4.7)
run-instructions.md
A shlex.join-rendered command for POSIX sh / bash / zsh copy/paste
The structured execution contract
[wolframscript_executable, "-file", result_wl_path]
Additionally required in batch mode:
result-python.py
result-meta.json
If Wolfram was actually executed, also try to add:
wolfram-output.txt
Key runtime output, verification result, or error information
Default Wolfram execution behavior (applies to both modes):
In both modes, attempt by default to execute wolframscript -file result.wl
and write key output into wolfram-output.txt. If the environment does not have
the wolframscript command (or execution fails), record the failure reason in
wolfram-output.txt (or represent it by that file's absence) and do not stop
the flow. In batch mode this causes Step 4.7 numerical comparison to degrade to
benchmark_status = "skip" with the reason stated in notes.
Any process/tool execution must pass
[wolframscript_executable, "-file", result_wl_path] as an argv array with no
shell. Never concatenate executable and file paths into a command string. Only
run-instructions.md renders the same argv with shlex.join, and that display
is POSIX-specific rather than a PowerShell or cmd.exe contract.
Even if the current conclusion is BLOCKED, still create the result directory
and write at least:
request.md
result-summary.md
In the final response to the user, explicitly state which directory stores this
result.
Step 4.6 — Generate result-python.py And result-meta.json (batch mode only)
In batch mode, after Step 4.5 creates the result directory and writes .wl, but
before entering the Step 5 self-check, two additional files must be generated:
result-python.py and result-meta.json. They are the machine interface used by
downstream hep-numerics to read this task's result.
Step 4.6.0 — Expand Passarino-Veltman Functions On The Wolfram Side First When Needed
Before Python translation, first check whether finalResult in the .wl code
(or coreResult, if the task delivery level stops at coreResult) still contains
unexpanded PV functions:
PVA, PVB, PVC, PVD, ScalarC0, ScalarD0, DiscB, etc.
(object definitions are in references/packagex-reference.md §1.9).
If unexpanded PV functions remain, expand them first on the Wolfram side
using the rules below, so the target expression translated into Python contains
only elementary functions (log, dilog, algebraic expressions):
Object
Expansion function
Prerequisite
Standard scalar cases such as PVA[0, m^2] / PVB[0, 0, m1^2, m2^2]
Usually already expanded by LoopRefine; if not, manually substitute the closed forms from §1.9
No special prerequisite
ScalarC0[...]
C0Expand[expr, expansion_variable -> small_quantity] or LoopRefine[..., ExplicitC0 -> Automatic]
Needs a suitable small parameter / mass hierarchy / kinematic limit
No special prerequisite; gives closed forms on different branches of s relative to thresholds
Expansion strategy:
If the physical setup of the current task naturally corresponds to a small
parameter (for example the heavy-Z' limit m_mu^2 / M_Zp^2 -> 0 in muon g-2,
or a light-quark limit), prefer expanding in that small parameter by
appending to the end of the .wl code:
Then use finalResultExpanded as the source object for Python translation.
If there is no natural small parameter but the result only contains DiscB,
use DiscExpand directly.
If expansion requires a specific limit but the task itself does not restrict
the limit (for example, the task requests an analytic expression over the full
parameter space), do not force an expansion. Keep the symbolic form and
treat it as translation_status = "partial" in Step 4.6.1.
After expansion, Print the new expression and preserve it in
wolfram-output.txt.
Implementation location: append the expansion code to the end of
result.wl (after Print["finalResult = ", ...]) rather than rewriting the
original finalResult definition. This preserves both forms for human checking.
Step 4.6.1 — Generate result-python.py
The base template is templates/result-python.py.tmpl.
The initialization script (the Step 4.5 --task-dir call) has already copied
this file's template skeleton into the result directory. You only need to use
str_replace / file-editing tools to replace each {{...}} placeholder with
actual content. Do not overwrite the whole file with create_file, because that
would lose the template structure.
Copy from the template, then fill it according to these rules:
File-header docstring: record Task ID, Process, model_version (read
from the manifest), and generation time.
Parameter block: iterate over the parameters read in Step 0.2 that are
actually used in this calculation, writing one comment line per parameter:
# m_mu: muon mass [GeV] (role=fixed, value=0.10566)# M_Zp: Z' mass [GeV] (role=scan, range=[1, 5000])# g_prime: U(1)' coupling (role=scan, range=[1e-4, 1])
Parameter names must be strictly equal to parameters[].name in
model-spec.json (canonical name), and must not be rewritten for display
prettiness (for example, do not write M_Zp as m_zp).
Main function: the function name equals the natural mapping from the task's
target_quantity (for example, if target_quantity = "form_factor_F2" and the
observable is muon g-2 -> function name delta_a_mu; or directly use
target_quantity). Function parameters are listed by canonical name.
Expression translation: translate the (expanded) finalResult produced by
Step 4.6.0 from Mathematica to Python. Core mapping table:
Write the translation as a pure function body. Use Python local variables for
intermediate quantities, with canonical-name style naming.
Rules for deciding translation_status (determines meta fields in Step 4.6.2):
Case
status
finalResult has been expanded to pure elementary functions and fully translated successfully
"complete"
Overall translation succeeded but one or more PV functions remain (for example because the task naturally has no small parameter)
"partial"
Expression is too complex (Mathematica structure nested too deeply, contains hard-to-translate structures such as HoldForm / Condition, or contains unknown symbols)
"failed"
partial and failed are diagnostic attempt states. The current authoritative
calculation manifest has only task-complete/revised publication semantics, so
neither state may replace calculations/{task_id}/ or enter
calculations.completed_tasks. Preserve the owned attempt and report the
translation limitation instead.
Handling for "partial": write at the relevant location in the Python file:
# TODO: PV function not yet translated# Mathematica expression: ScalarC0[0, 0, 0, m_mu^2, M_Zp^2, 0]# Suggested translation: use pylooptools / pysecdec, or provide a hand-coded expansionraise NotImplementedError("PV function translation pending")
The remaining pure-elementary-function part is still translated normally.
and include the complete Mathematica expression in comments for manual
translation.
translation_status only describes Python translation status, not the source of
the physics derivation. Even if a literature formula can be fully translated
to Python and therefore receives translation_status = "complete", it must
still use calculation_provenance to indicate that it was not derived by
Package-X.
Step 4.6.2 — Generate result-meta.json
The base template is templates/result-meta.json.tmpl.
The initialization script (the Step 4.5 --task-dir call) has already copied
this file's template skeleton into the result directory. You only need to use
str_replace / file-editing tools to replace each {{...}} placeholder with
actual content. Do not overwrite the whole file with create_file, because that
would lose the template structure.
Fill every field according to these rules:
task_id: equals the current task_id (string, such as "task-001")
observable: equals return_value.name (below), and also equals the task's
target_quantity (or a natural naming mapping from it)
python_function: function name written in Step 4.6.1
python_file: fixed to "result-python.py"
parameters[]: iterate over the actual parameter list of the Step 4.6.1
function; fill canonical_name (read from model-spec), role (read from
model-spec parameters[].role: scan / fixed / derived), and unit (read from
model-spec)
return_value: {"name": ..., "unit": ..., "description": ...}; unit
corresponds to the task target_quantity (for example form_factor_F2 is
dimensionless, delta_a_mu is dimensionless, cross section is GeV^-2 or pb,
etc.)
translation_status: determined by the table in Step 4.6.1
translation_notes: if translation_status = "partial", list the remaining
PV function names and their arguments; if "failed", fill the failure reason
source_wl: fixed to "result.wl"
calculation_provenance: must explicitly state the source of finalResult:
"package_x_derived": finalResult comes from the Package-X calculation
chain in result.wl; loop diagrams usually include LoopIntegrate /
LoopRefine / Projector; tree diagrams usually include Spur /
Contract / LoopRefine
"manual_tree_algebra": a tree-level or pure-algebra task was derived by
manual algebra, with no claim of a Package-X backend
"literature_formula_imported": a literature formula, benchmark formula,
known limit, or manual closed-form result was directly used as the backend
"blocked": current information or support boundaries are insufficient, so
no usable calculation backend was generated
benchmark_used_as_input: normally must be false. It may be true only when
the user explicitly requests using a benchmark / literature formula as a
fallback backend; in that case calculation_provenance must not be
"package_x_derived". Existing allow_formula_fallback=true in scan-config
is not package-scribe fallback authorization; it only constrains whether
hep-numerics may consume an existing fallback backend. If a batch rerun cannot
produce a real Package-X backend and this invocation has no explicit fallback
authorization, write "blocked" / "failed" and make the Python placeholder
raise NotImplementedError. Keep that attempt as diagnostic evidence; the
finalizer rejects blocked/partial/failed generations and preserves any prior
canonical result and manifest state.
package_x_methods: list the Package-X methods that actually participate in
the first draft of result.wl, such as ["LoopIntegrate", "LoopRefine", "Projector"] or ["Spur", "Contract", "LoopRefine"]. For non-Package-X
backends, write []
derivation_evidence: required when calculation_provenance is
"package_x_derived"; remove this template object for other provenance
values. Fill it only after all Step 4.7 edits are complete:
source_wl_sha256 and python_file_sha256 are lowercase SHA-256 values in
sha256:<64 hex> form for the final current files
wolfram_result_symbol names the symbol whose assignment is transitively
data-dependent on an executable declared Package-X call
observable and python_function exactly repeat the corresponding
top-level metadata fields
package_x_methods exactly repeats the top-level nonempty unique list
the declared Python function must exist, parse, and return a value
data-dependent on its function inputs
A declaration in comments/strings, an unused Package-X call, a constant
Python return, stale hashes, or metadata mismatch invalidates the evidence.
provenance_notes: one sentence explaining the calculation source; if it is
not "package_x_derived", explain why it is not Package-X-derived and whether
it can be used by downstream numerical scans
depends_on.model_version: read active_model_version from the current
project's manifest.json
depends_on.model_checksum: read artifacts.model.checksum from the current
project's manifest.json (for example "sha256:...")
input_provenance: keep the template's
{{input_provenance_status}} sentinel unchanged during the first draft. The
entire object is replaced only by the verified exact-byte graph in Step
4.7.4, after every graph-bound output has reached its final bytes. Never fill
only the status string or hand-author dependency entries or hashes.
benchmark_status: placeholder null first; Step 4.7 fills the final value
In batch mode, the package finalizer owns the calculation manifest merge. It
publishes the complete task directory and writes manifest.json last in the
same transaction. For a new task it emits calc_task_{task_id}_complete (for
example calc_task_task-001_complete); for a recomputation or manual revision
it emits calc_task_{task_id}_revised. The orchestrator validates and reports
the returned state but must not perform a second manifest read-modify-write.
calculations_updated remains only for a separately authorized legacy/manual
aggregate update spanning multiple tasks, with a note naming those tasks.
Canonical-name hard constraint: Every parameters[].canonical_name must
match ^[A-Za-z_][A-Za-z0-9_]*$, must not be Python hard keywords, and
exactly reuse a model-spec.json.parameters[].name; aliases and case
transformations are forbidden. See
docs/contracts/canonical-name-convention.md. The orchestrator rejects a
violating result-meta.json before manifest write.
Step 4.6 Self-Check
Before entering Step 5, confirm:
result-python.py has been written into the result directory
result-meta.json has been written into the result directory
Python function parameter names exactly match canonical names in
model-spec.json
The translation_status field matches the actual state of the Python file
The calculation_provenance field matches the actual derivation path in
result.wl
If calculation_provenance = "package_x_derived", benchmark_used_as_input
is false, package_x_methods is non-empty, and
the derivation_evidence structure is prepared for the executable
Wolfram dataflow, observable, Python function, and exact method list;
hashes are finalized only after the last Step 4.7 edit
If provenance is not package_x_derived, the package-X-only
derivation_evidence template object was removed rather than populated
with misleading placeholders
If a literature formula or benchmark formula was used as the backend,
calculation_provenance is not "package_x_derived", and the provenance
downgrade is stated explicitly in the summary
depends_on.model_version equals the current active_model_version
The input_provenance sentinel is still present at this draft stage; it
will be replaced by a mechanically built verified graph only after all
Step 4.7 edits
If PV expansion was done on the Wolfram side -> expansion code has been
appended to the end of result.wl, and wolfram-output.txt contains the
expanded finalResultExpanded
In batch mode, after completing the Python translation in Step 4.6 and before
entering Step 5, execute benchmark verification and write the result into
result-summary.md and result-meta.json.
Step 4.7.0 — Quick Dispatch
Only now read the complete benchmark entry for the current task (formula_latex
/ known_limits / numerical_test_point / sources / notes). Before reading
it, first confirm that first drafts of result.wl, result-python.py, and
result-meta.json already exist and that
result-meta.json.benchmark_used_as_input = false, unless the user explicitly
requested a literature-formula fallback. Decide whether to actually verify
according to the Step 0.3 state:
Step 0.3 state
Action
benchmark_status
benchmarks.json does not exist
Skip verification and write a one-line placeholder explanation
"no_benchmark"
This task is absent from benchmarks.json
Same as above
"no_benchmark"
Entry exists and has_benchmark = false
Quote the fallback suggestion from notes in the summary; do not compute
"no_benchmark"
Entry exists and has_benchmark = true
Continue Step 4.7.1 through 4.7.3
Determined by later steps
Step 4.7.1 — Numerical Comparison (hard decision)
Execute only when the benchmark has numerical_test_point.
Read numerical_test_point.inputs (parameter-value dictionary with canonical
names as keys), numerical_test_point.expected_value, and
numerical_test_point.tolerance
Execute numerical substitution, preferring this order:
If Step 4.6.1 has translation_status = "complete" and Python can run ->
load result-python.py by file path in the result directory, substitute
inputs, and compute computed_value. Recommended command:
python3 - <<'EOF'
import importlib.util
from pathlib import Path
result_python = Path("result-python.py").resolve()
spec = importlib.util.spec_from_file_location("rp", result_python)
if spec is None or spec.loader is None:
raise RuntimeError(f"Cannot load module from {result_python}")
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
inputs = { <canonical-name -> value dictionary read from benchmark> }
print(getattr(m, "<python_function>")(**inputs))
EOF
If this path errors with ModuleNotFoundError (for example missing
numpy / scipy), module-load failure, or function-execution failure, this
is an expected Python-path degradation case. Record the failure reason and
automatically move to the Wolfram numerical comparison path; do not treat it
as the benchmark's final FAIL.
Otherwise (partial / failed / no Python environment) -> if Wolfram is
available, append to result.wl:
(n of order 2-3 is generally enough. For limits such as M_Zp >> m_mu,
usually use Series[finalResult, {m_mu, 0, 2}] or
Series[..., {r, 0, 2}] with r = m_mu^2 / M_Zp^2.)
Execute Wolfram and extract the LaTeX form (TeXForm) or InputForm of
limitExpanded
Append this limit to the ## Benchmark Verification section of
result-summary.md:
### Limit: {limit}
Benchmark (from {source}):
$$ {approximate_result_latex} $$
This work (expanded to {n} order):
$$ {TeXForm of limitExpanded} $$
Benchmark in Python form:
{approximate_result_code}
Verdict: REQUIRES_HUMAN_REVIEW
Do not try to use Simplify[diff] === 0 for symbolic equivalence
decisions; it can easily produce false negatives. Leave responsibility for
this check to the user's human review.
If the result-summary.md template contains the marker
<!-- batch mode: replace this marker with a ## Benchmark Verification section -->
prefer replacing that marker with the complete ## Benchmark Verification
section. If the marker is absent, append the section to the end of the file.
Step 4.7.3 — Aggregate benchmark_status Decision
Decide the final benchmark_status (written to the benchmark_status field of
result-meta.json) by this priority:
Condition
benchmark_status
Step 4.7.1 numerical comparison PASS (regardless of limit-expansion status)
"pass"
Step 4.7.1 numerical comparison FAIL
"fail"
Neither 4.7.1 nor 4.7.2 can execute (no numerical point, no usable limit, Wolfram unavailable)
"skip"
No benchmark (Step 4.7.0 dispatch)
"no_benchmark"
Note: the standard flow uses numerical comparison only to decide pass/fail;
limit expansion is display-only and does not downgrade a numerical PASS to FAIL
by itself. If the user wants a stricter decision, they decide after manually
reviewing the side-by-side limit expansion.
Note: benchmark_status = "pass" only means the current backend agrees with the
benchmark numerical point. It does not prove that the backend was derived by
Package-X. Whether it is Package-X-derived is determined only by
calculation_provenance, benchmark_used_as_input, and package_x_methods.
Step 4.7 Write Location Summary
Append a ## Benchmark Verification section to the end of result-summary.md
(including sources, numerical comparison verdict, and side-by-side expressions
for each limit)
Change the benchmark_status field in result-meta.json from null to the
final value
If Step 4.7.1 or 4.7.2 appended code on the Wolfram side, append the
corresponding code to the end of result.wl and preserve the output in
wolfram-output.txt
After the last append or edit, recompute
derivation_evidence.source_wl_sha256 and
derivation_evidence.python_file_sha256. Never retain hashes from the first
draft.
Step 4.7.4 — Finalize And Verify Exact-Byte Input Provenance
Run this step only after the final Step 4.7 edit to request.md,
result-summary.md, result.wl, and result-python.py, and after finalizing
the derivation-evidence hashes. A graph built from an earlier draft is stale
even when the scientific expression did not change.
From the repository root, run
python3 scripts/sync_skill_mirrors.py --check. A mirror mismatch is a hard
error because the calculation graph binds both mirrored skill trees and all
routed Package-Scribe references, examples, templates, and validation
scripts.
Leave the template's complete temporary input_provenance object in the
attempt; do not hand-author entries or copy hashes from manifest fields. Run
the mechanical finalizer from the Package-Scribe skill directory:
The finalizer verifies the ownership token and the originally captured
last-good task identity, copies the complete candidate into private
same-filesystem transaction staging, rejects missing/empty/symlink/special
paths and unresolved placeholders, calls build_dependency_graph over the
exact calculation_dependency_specs set from a candidate overlay, replaces
the entire temporary provenance object, and then calls
verify_dependency_graph with
expected_specs=calculation_dependency_specs( and allow_legacy=False.
Result schema, derivation evidence, benchmark data, and every live exact-byte
dependency must all validate before publication.
While holding the project publication lock, the finalizer merges the current
manifest v2 calculation state, emits the task-scoped event with a unique
event_id, marks dependent current numerics stale on a changed revision,
schema-validates the manifest candidate, and publishes the complete task
tree, attempt outcome, and manifest (last) through one journaled CAS
transaction. Any failure blocks the history update and restores the complete
prior task/manifest generation. Do not retry when the finalizer explicitly
reports cleanup_pending=true; the authoritative publication already
committed and only private recovery cleanup remains.
If the calculation aggregate was explicitly stale, this successful task
starts a new current generation: the finalizer resets the current registry,
records only this task as completed, leaves every other currently declared
task pending, and binds the aggregate to the active model. Untouched task
directories remain historical evidence and are not silently promoted.
After success, treat "$taskDir" as the result directory for reporting and
downstream use. Do not edit it or any graph-bound attempt file after
finalization. A blocked, partial, or failed attempt remains diagnostic-only
and cannot replace the canonical result or enter completed_tasks.
Every newly produced or recomputed result-meta.json must therefore end with
input_provenance.version = "sha256-bytes-v1",
input_provenance.verification_status = "verified", a nonempty canonical
entries list, and its recomputed root_sha256. The
legacy-unverified representation is reserved for explicitly migrated
historical artifacts; package-scribe must never emit it for a new or recomputed
result, including a fallback backend.
Step 4.7 Self-Check
result-summary.md contains a ## Benchmark Verification section
result-meta.json.benchmark_status is set to one of pass / fail / skip /
no_benchmark (not null)
If benchmark_status = "pass" or "fail" -> the summary section contains
the concrete numbers from the numerical comparison
If the benchmark has known_limits -> the summary section contains the
benchmark expression and this-work expanded expression side by side for
each limit
For package_x_derived, derivation-evidence hashes match the final files
after all benchmark-verification edits
input_provenance is a mechanically built verified graph over the
complete calculation_dependency_specs set; verification passed with
allow_legacy=False after the placeholder check
No graph-bound file changed after the final dependency verification
Step 5 — Self-Check + Output
Before writing the final .wl file, go through the checklist below item by
item. If any item fails, return to Step 4 and fix it.
Common Self-Check (tree diagrams + loop diagrams)
All Lorentz indices are contracted in pairs (no dangling μ, ν)
If using Contract -> each Lorentz index appears at most twice; do not
expect Contract to enter DiracMatrix / FermionLine and contract
internal indices for you
Matrix multiplication inside Spur is comma-separated, with additions
inside a single argument
Scalar constants inside Spur (mass m, etc.) are multiplied by the identity
matrix \[DoubleStruckOne]
All characters use \[Name] form
No formatted variable names (do not use subscripts; in Package-X,
Subscript[m, H] is parsed as the H component of four-vector m)
Dot products use LDot[p, q], not p.q (. in .wl scripts is
Mathematica Dot, not LDot)
Use LoopRefine to take d->4; never manually replace
\[ScriptD] -> 4
Additional Tree-Diagram Self-Check
Polarization-vector sum form is correct (massive vs massless bosons)
Spin sum/average factors are correct (initial state divided by 2s+1,
color divided by N_c, etc.)
On-shell conditions are applied before LoopRefine
If rewriting Zff from gL/gR to gV/gA -> explicitly checked the
convention used (recommended:
\gamma^\mu(gV \[DoubleStruckOne] - gA \[Gamma]5))
Additional Loop-Diagram Self-Check
Number of propagators matches loop topology (2-point -> 2, 3-point -> 3)
Propagator mass is the mass, not mass squared: {k + p, m}, not
{k + p, m^2}
Repeated propagators use the third element for the power: {k, 0, 2},
not repeated {k, 0}, {k, 0}
Feynman slash: LDot[k, \[Gamma]]
If explicitly calling FermionLineExpand -> input contains only one of
DiracMatrix / FermionLine / FermionLineProduct, and is strictly
linear in it
On-shell conditions are applied beforeLoopRefine (unless covariant
decomposition must be done first)
Longitudinal/Transverse projections are called beforeLoopRefine
Explicitly set Apart -> True only when partial fractions are truly
needed; otherwise keep the LoopIntegrate default
If using general R_\[Xi]W/Z propagators -> the (1 - \[Xi]V) factor
before the longitudinal term is not missing, and it has been split into
{k, MV} and {k, Sqrt[\[Xi]V] MV}
UV pole structure matches power-counting expectations
If γ₅ appears -> confirmed that dimensional-regularization
inconsistencies have been handled
If ghost vertices are involved -> explicitly stated whether ghost or
antighost momentum flows inward by convention
If using Projector -> removable singularities are eliminated with
Simplify before substituting kinematic limits
If using Projector -> target name corresponds term by term to the
standard decomposition formula in §1.7 (for example EDM -> G2,
anapole -> G1)
If using Projector and the physical momentum transfer is time-like
(decay / production process) -> checked according to §1.7 whether the
projector sees q = p2 - p1 as the negative of the physical transfer
Additional Custom-Lagrangian Self-Check
First gave PASS / PASS_WITH_ASSUMPTIONS / BLOCKED according to
references/custom-lagrangian-validation.md
If not BLOCKED -> user-facing output uses the more natural summary
format Validation verdict / Scope / Assumptions I will use / Warnings / Can proceed with
If BLOCKED -> closed with Why blocked / What I need from you, rather
than mechanically outputting empty sections
If BLOCKED and there is an obviously reasonable default continuation ->
added Suggested default if you want me to proceed
If complex couplings or chirality-off-diagonal terms exist -> checked
Hermiticity / h.c.
Every interaction term that continues to be used is a Lorentz scalar and
has closed indices
If this request needs internal propagators or loop diagrams for new
particles -> mass, spin, and propagator structure have been specified
If field mixing / non-canonical kinetic terms / non-diagonalized mass
matrices exist -> did not continue silently; explicitly stated assumptions
or blocking reasons
If \[Gamma]5, Majorana, higher-spin, complex derivative operators, or
nonminimal gauge-fixing / ghost structures are involved -> explicitly
stated current support boundaries
Output Format Self-Check
(interactive mode only) Created a new
workspace/package-scribe/package-resultNNN/ directory for this new
request
request.md and result-summary.md have been written into the result
directory
If code can be generated for this request -> result.wl has been written
into the result directory
If run instructions were provided -> run-instructions.md has been
written into the result directory
If Wolfram was actually executed -> key output has been saved to
wolfram-output.txt
Interactive: ran check_package_result_placeholders.py and it passed;
batch: the owned-attempt finalizer completed its equivalent placeholder,
schema, provenance, and atomic manifest-publication checks
File header contains a physics-analysis comment block
Every code block has English comments explaining the physics meaning
For loop-diagram results, normalization factors are clearly stated in
comments
If the code computes intermediate quantities first -> explicitly organized
as coreResult / prefactor / finalResult
If prefactor contains an overall minus sign or normalization mapping
(not merely positive multiplicative factors) -> its source is clearly
stated
If the user did not specify result level -> by default show coreResult /
prefactor / finalResult together
The main result shown to the user exactly corresponds to the physical
quantity level requested by the user
Unless the user explicitly requests "verification / comparison with
theory result / check / comparison with expected result / pass-fail
check", this deliverable outputs only the solved result and does not need
comparison checks against independent analytic results, public theory
results, or literature
If the main output is not finalResult -> explicitly state which
prefactor / phase-space / averaging factors are still missing
There are Print or Export output statements
Unless the user explicitly says not to provide code -> output complete
.wl code
(batch mode only) Output directory is calculations/{task_id}/, not
workspace/package-scribe/package-resultNNN/
(batch mode only) Generated result-python.py, with parameter names
exactly matching canonical names in model-spec.json
(batch mode only) Generated result-meta.json, with the
translation_status field matching the actual state of the Python file
(batch mode only) Generated result-meta.json, with
calculation_provenance / benchmark_used_as_input / package_x_methods
fields truthfully reflecting the derivation source
(batch mode only) Generated result-meta.json, with a newly built
exact-byte input_provenance graph whose status is verified; it is not
a legacy-unverified compatibility record
(batch mode only) If calculation_provenance = "package_x_derived":
- The loop task result.wl contains a real Package-X loop chain
(such as LoopIntegrate / LoopRefine / Projector)
- The tree task result.wl contains a real tree-algebra chain
(such as Spur / Contract / LoopRefine)
- benchmark_used_as_input = false
- derivation_evidence contains final artifact hashes, the result symbol,
matching observable/function/method fields, executable Package-X calls,
and a transitive dataflow from those calls to the result symbol
- The Python function's return value is data-dependent on its inputs
(batch mode only) Static derivation checks are not reported as proof of
runtime-verified independence; until runtime cross-language evidence is
implemented, reproduction comparison remains unknown /
needs_human_review
(batch mode only) If a literature formula, benchmark formula, or known
limit was used as the backend: calculation_provenance has been
downgraded to literature_formula_imported or manual_tree_algebra, and
the summary does not use wording like "Package-X-backed"
(batch mode only) result-meta.json.depends_on.model_version equals the
current active_model_version
(batch mode only) If finalResult originally contained PV functions ->
completed the expansion on the Wolfram side with one of C0Expand /
D0Expand / DiscExpand (or marked translation_status = "partial" and
explained why)
(batch mode only) result-summary.md contains a
## Benchmark Verification section; result-meta.json.benchmark_status
is set to one of pass/fail/skip/no_benchmark
(batch mode only) If benchmark_status = "fail" -> the summary section
states expected / computed / abs diff / tolerance
After all checks pass, output in this order:
Physics analysis (concise and clear)
Result directory path (interactive mode:
workspace/package-scribe/package-result007/; batch mode:
calculations/task-001/)
Complete .wl code
POSIX run instructions plus the no-shell structured argv contract
If the user asks for a plot: add numerical export and Python/matplotlib
plotting instructions
Code Output Templates
Tree-Diagram Template
(* ================================================================ *)
(* {Calculation title} *)
(* ================================================================ *)
(* Type: Tree diagram *)
(* Process: {e.g. Z -> f fbar} *)
(* Method: Spur + Contract *)
(* On-shell conditions: {list all p.p -> m^2, etc.} *)
(* Generated at: {date} *)
(* ================================================================ *)
(* --- Load Package-X --- *)
<< X`
(* --- Parameter definitions --- *)
(* {physical meaning of each parameter} *)
(* --- On-shell conditions --- *)
onShell = {LDot[k, k] -> mZ^2, LDot[p1, p1] -> mf^2, ...};
(* --- Squared amplitude: Dirac trace + polarization sum --- *)
(* |M|^2 = polarization factor x Tr[...] x (polarization tensor) *)
trace = Spur[
LDot[p2, \[Gamma]] + mf \[DoubleStruckOne],
LTensor[\[Gamma], \[Mu]],
gV \[DoubleStruckOne] - gA \[Gamma]5,
LDot[p1, \[Gamma]] - mf \[DoubleStruckOne],
gV \[DoubleStruckOne] + gA \[Gamma]5,
LTensor[\[Gamma], \[Nu]]
];
(* --- Contract polarization vectors --- *)
ampSquared = Contract[
trace (-LTensor[g, \[Mu], \[Nu]]
+ LTensor[k, \[Mu]] LTensor[k, \[Nu]] / mZ^2)
];
(* --- Apply on-shell conditions and take d -> 4 --- *)
coreResult = ampSquared /. onShell // LoopRefine;
(* --- Restore coreResult to the physical quantity delivered by this code --- *)
(* prefactor may include couplings, color factors, spin averages, phase space,
and, if needed, an overall minus sign or form-factor normalization map. *)
prefactor = ...;
finalResult = prefactor coreResult;
Print["coreResult = ", coreResult];
Print["prefactor = ", prefactor];
Print["finalResult = ", finalResult];
(* Save this complete code as:
- interactive mode: workspace/package-scribe/package-resultNNN/result.wl
- batch mode: calculations/{task_id}/result.wl
and write result-summary.md / run-instructions.md in the same directory *)
Loop-Diagram Template
(* ================================================================ *)
(* {Calculation title} *)
(* ================================================================ *)
(* Type: One-loop *)
(* Process: {e.g. QED electron self-energy} *)
(* Method: {Spur / DiracMatrix / FermionLine / Projector / direct} *)
(* Propagators: *)
(* {k + p, me} -- electron (mass me) *)
(* {k, 0} -- photon (massless, Feynman gauge) *)
(* On-shell conditions: {p.p -> me^2, or "off-shell: keep general p^2"} *)
(* UV structure: {expected divergence structure} *)
(* Normalization: LoopIntegrate omits i/(16 pi^2) and -gamma_E+ln(4 pi)*)
(* Generated at: {date} *)
(* ================================================================ *)
(* --- Load Package-X --- *)
<< X`
(* --- Parameter definitions --- *)
(* --- Construct integrand --- *)
(* {Feynman diagram description} *)
numerator = ...;
(* --- Loop integral --- *)
amplitude = LoopIntegrate[
numerator,
k, (* loop momentum *)
{k + p, me}, (* propagator 1 *)
{k, 0} (* propagator 2 *)
];
(* --- On-shell conditions (if applicable) --- *)
amplitude = amplitude /. {LDot[p, p] -> me^2};
(* --- Simplification --- *)
coreResult = LoopRefine[amplitude];
(* --- Result extraction --- *)
(* prefactor may include couplings, i/(16 pi^2), closed-fermion-loop -1, and
color factors. If a Projector result still needs an extra minus sign or
normalization map before it becomes the physical quantity, write it here. *)
prefactor = ...;
finalResult = prefactor coreResult;
(* --- Verification (if applicable) --- *)
Print["coreResult = ", coreResult];
Print["prefactor = ", prefactor];
Print["finalResult = ", finalResult];
(* Save this complete code as:
- interactive mode: workspace/package-scribe/package-resultNNN/result.wl
- batch mode: calculations/{task_id}/result.wl
and write result-summary.md / run-instructions.md in the same directory *)
Package-X Code Conventions
The following rules must be followed strictly.
Characters And Symbols
Use full \[Name] forms: \[Mu], \[Nu], \[Gamma], \[Epsilon]
Common glyph mapping (full mapping in references/packagex-reference.md §2):
Never use subscripted variable names. Package-X parses Subscript[m, H]
as LTensor[m, H] (the H component of four-vector m), producing completely
wrong results
Correct: mH, me, mZ
Incorrect: m_H, Subscript[m, H]
Dot Products And Four-Vectors
In .wl scripts, explicitly write LDot[p, q]
Package-X remaps . to LDot in notebooks, but .wl scripts do not remap it
p.q in .wl is Mathematica Dot (matrix inner product), not a Lorentz dot
product
Self-energy exception: perform covariant decomposition first (collect the
p-slash coefficient), then apply on-shell replacement, and finally LoopRefine.
Removable Singularities From Projector
When using Projector to extract form factors, removable singularities may
appear in the numerator (such as 1/(q²(q²-4m²)²)). This is a mathematical
artifact of the projection operation. Handle it as follows:
Call LoopIntegrate normally (default Cancel -> Automatic handles this
automatically)
Use Simplify (or Cancel/Factor) on the result to remove the removable
singularity
Substitute the kinematic limit (such as q² -> 0) only after confirming the
singularity has been removed
Normalization (loop diagrams only)
LoopIntegrate/LoopRefine output omits
iexp(-gamma_Eepsilon)/(4pi)^(d/2). Equivalently, it omits i/(16pi^2), and the 1/epsilon pole is
not paired with -γ_E + ln(4π). Code comments must state what must be multiplied
back to recover the complete physical result.
Numerical Stability
Large scale separation -> use arbitrary-precision numbers, such as
21.540, and set WorkingPrecision -> 40`
LoopRefine[..., ExplicitC0 -> None] keeps ScalarC0 unexpanded and is more
numerically stable
LoopRefineSeries can produce analytic approximations to avoid numerical
issues
Seeing DiscB / ScalarC0 / ScalarD0 remain in the result is usually
normal; for explicit expansion, see references/packagex-reference.md §1.9
Reference File Routing (section-exact)
Task
File to read
Section to read
Dirac trace (tree or loop diagram)
references/packagex-reference.md
§1.4
Contract indices
references/packagex-reference.md
§1.8
LoopIntegrate
references/packagex-reference.md
§1.1 + §3
LoopRefine
references/packagex-reference.md
§1.2
Recognize common output objects
references/packagex-reference.md
§1.9
Identify C0/D0/Disc expansion functions
references/packagex-reference.md
§1.9
Taylor expansion
references/packagex-reference.md
§1.3
Off-shell fermions
references/packagex-reference.md
§1.5
On-shell fermions
references/packagex-reference.md
§1.6
Form-factor projection
references/packagex-reference.md
§1.7
Custom Lagrangian input validation
references/custom-lagrangian-validation.md
§1-§7
Custom Lagrangian translation
references/packagex-reference.md
§5
γ₅ issues
references/packagex-reference.md
§6
Common pitfalls
references/packagex-reference.md
§7
QED Feynman rules
references/standard-theories.md
§1
QCD Feynman rules
references/standard-theories.md
§2
Electroweak Feynman rules
references/standard-theories.md
§3
Yukawa Feynman rules
references/standard-theories.md
§4
Tree-diagram examples
examples/tutorial-examples.md
§0
Electroweak minimal tree diagram (Wff')
examples/electroweak-minimal-examples.md
§EW1
Electroweak neutral-current tree diagram (\[Gamma]ff + Zff)
examples/electroweak-minimal-examples.md
§EW2
Vacuum polarization/H→gg
examples/tutorial-examples.md
§1, §2
Self-energy
examples/tutorial-examples.md
§3
g-2 (Projector)
examples/tutorial-examples.md
§4
QCD vertex (FermionLine)
examples/tutorial-examples.md
§5
Routing rule: any QFT calculation -> this file triggers automatically.
Standard theories -> read the corresponding section in standard-theories.
Custom Lagrangian -> read custom-lagrangian-validation.md first, then
reference §5. If examples are needed -> choose the section by type.