Use when creating or adapting carve-out schedules with strict quality gates, phase milestones, task dependencies, and XLSX/XML outputs.
Generate a project schedule as Excel workbook (XLSX) + MS Project XML from canonical script pattern. The XML generator (generate_msp_xml.py) requires a temporary CSV during generation, but no CSV is retained in the final output folder.
generate_msp_xml.py — canonical CSV→XML converter; do NOT duplicate logicgenerate_bravo_schedule.py) — format/structure reference ONLY; never copy task lists, dates, resources, or project-specific contentgenerate_{ProjectName}_schedule.py script from scratchactive-projects/{ProjectName}/XLSX_PATH and XML_PATH in output folder; use a temporary CSV path only for XML generationif __name__ == "__main__": call _generate_excel(), write the temporary CSV, subprocess generate_msp_xml.py, then remove the temporary CSV(ID, Outline Level, Name, Duration, Start, Finish, Predecessors, Resource Names, Notes, Milestone)
Dates & Calculations:
YYYY-MM-DD (ISO, unambiguous)date_plus_days(base, days) must use calendar days only: return base + timedelta(days=days)Task Details:
1 day duration, "Yes" in Milestone column"14,15,16,17")"KPMG + IT PM")"14;15") NOT supported — use commas onlyQG0 (Intake) → QG1 (Concept) → QG2&3 (Build & Test) →
QG4 (Pre-GoLive Check) → [Final Readiness] →
GoLive Day 1 → 90-day Hypercare → QG5 (Completion) → Closure
Each gate is a 1-day milestone (Milestone = Yes) that gates entry to next phase. Cannot be modified.
QG4 approval and GoLive cutover CANNOT be same calendar date.
Between QG4 and GoLive, insert mandatory Final Readiness & Open Item Closure phase (5 days minimum):
GoLive proceeds only after Final Readiness complete. This prevents critical gaps cascading to production.
Example:
Post-GoLive scope = STABILIZATION ONLY. Mandatory 90-day Hypercare contains:
Explicit prohibitions post-GoLive:
Hypercare = support + stabilization ONLY.
Generated via generate_msp_xml.py — do NOT hand-write XML.
| Element | Correct | Wrong (Causes Issues) |
|---|---|---|
<Duration> | PT{days*8}H0M0S (working hours) | P{days}D (calendar ISO — errors) |
<Start> | 20YY-MM-DDT08:00:00 | T00:00:00 (wrong time) |
<Finish> (normal) | 20YY-MM-DDT17:00:00 | T00:00:00 (wrong time) |
<Finish> (milestone) | 20YY-MM-DDT08:00:00 | T17:00:00 (wrong time) |
<DurationFormat> | 7 (on every task) | Missing (parsing fails) |
<Calendars> | Standard 5-day calendar | Missing (date drift) |
<Resources> | All assigned resources | Missing (import fails) |
<Assignments> | All assignments | Missing (unassigned) |
MS Project sets ALL durations to 0 on import if violated:
Never write <PredecessorLink> on summary tasks (level 1–2)
generate_msp_xml.py enforces: if is_summary: breakNever reference summary task ID as predecessor of detail task
generate_msp_xml.py enforces: if pred_id in summary_ids: continueFirst detail tasks of new phase → point to last DETAIL task of previous phase (not phase summary)
Gate milestones → reference last DETAIL task(s) of workstreams (not summaries)
Missing or mis-ordered elements cause silent date drift (e.g. GoLive months late).
<Task>
<UID>…</UID>
<ID>…</ID>
<Name>…</Name>
<TaskMode>1</TaskMode> <!-- MUST follow <Name> immediately -->
<Duration>PT…</Duration>
<DurationFormat>7</DurationFormat>
<ManualDuration>PT…</ManualDuration>
<Start>20YY-MM-DDT08:00:00</Start>
<ManualStart>20YY-MM-DDT08:00:00</ManualStart>
<Finish>20YY-MM-DDT…</Finish>
<ManualFinish>20YY-MM-DDT…</ManualFinish>
<OutlineLevel>…</OutlineLevel>
<Summary>…</Summary>
<Milestone>…</Milestone>
<ConstraintType>2</ConstraintType> <!-- Must Start On (non-summary only) -->
<ConstraintDate>20YY-MM-DDT08:00:00</ConstraintDate>
<CalendarUID>-1</CalendarUID>
</Task>
Critical Rules:
<TaskMode>1</TaskMode> anywhere other than immediately after <Name> is silently ignored<ManualStart> / <ManualFinish> are fields MS Project displays — <Start> / <Finish> alone insufficient<ConstraintType>2</ConstraintType> + <ConstraintDate> provides hard date pin<ConstraintType> — inherit from childrenTEMP_CSV_PATH = HERE / "active-projects" / PROJECT_NAME / f"{PROJECT_NAME}_Project_Schedule.tmp.csv"
# In main:
_generate_excel()
_write_temp_csv(TEMP_CSV_PATH)
result = subprocess.run([sys.executable, str(HERE / "generate_msp_xml.py"),
"--csv", str(TEMP_CSV_PATH), "--out", str(XML_PATH),
"--project", PROJECT_NAME], capture_output=True, text=True)
if result.returncode != 0:
print(f"✗ XML generation failed:\n{result.stderr}")
sys.exit(1)
TEMP_CSV_PATH.unlink(missing_ok=True)
Temporary CSV only — do not keep a CSV deliverable in the output folder after XML generation succeeds
| Row Type | Fill | Font | Bold |
|---|---|---|---|
| Header | #002147 (near-black blue) | White | Yes |
| Phase (L1) | #003B6E (dark Bosch blue) | White | Yes |
| Section (L2, non-milestone) | #0066CC (mid blue) | White | Yes |
| Milestone (any level) | #FFF2CC (amber) | Black | Yes |
| Detail (even) | #EFF4FB (light blue) | Black | No |
| Detail (odd) | White | Black | No |
Additional:
Schedule complete only when both final files exist:
active-projects/{ProjectName}/{ProjectName}_Project_Schedule.xlsx ← primary human-readable deliverableactive-projects/{ProjectName}/{ProjectName}_Project_Schedule.xml ← MS Project import fileSchedule must be generated BEFORE cost plan, risk register, charter, and dashboards.
Before marking schedule complete, verify:
Milestone = Yes)