---
name: construction-law-9c3ab0516872
description: Construction law analysis covering FIDIC (2017 suite), PSSCOC, SIA Conditions, NEC4, and JCT. Use when (1) analysing contract clauses, risk allocation, or obligations; (2) preparing or reviewing claims (delay, disruption, prolongation, EOT, loss & expense); (3) comparing contract forms or advising on procurement strategy; (4) drafting or reviewing notices, correspondence, or contract documents; (5) building obligations registers or notice calendars; (6) discussing dispute resolution (DAB/DAAB, adjudication, arbitration, mediation, CAB); (7) Singapore-specific construction law (SOP Act, BCA, SIArb); (8) MDB procurement frameworks (ADB, World Bank). NOT for: non-construction commercial contracts, pure property/real-estate conveyancing, or insurance law. Also assists with QS measurement checking (BOQ review, quantity verification, rate analysis, unit consistency).
---

# Construction Law Skill

> ## 🔒 Security & Safety
>
> **All Python scripts in this skill are safe, read-only template generators.**
>
> - ✅ **No network access** — no API calls, no HTTP requests, no telemetry
> - ✅ **No subprocess execution** — no shell commands, no external programs
> - ✅ **No filesystem traversal** — only writes to the user-specified `--output` path
> - ✅ **Read-only static reference data** — contract clauses bundled with the skill
> - ✅ **Verified clean:** VirusTotal Benign • ClawScan Benign
>
> The "Static analysis: Review" flag is auto-triggered because `excel_register.py` uses Python's standard `importlib` to compose sibling scripts in the same `scripts/` folder — this is benign and intentional.
>
> **Safe to install and use.** 🛡️

---

Analysis and advisory for international construction contracts, claims, and dispute resolution.

## Quick Reference — Contract Forms

| Form | Type | Design By | Key Feature |
|------|------|-----------|-------------|
| FIDIC Red | Measure & Pay | Employer | Employer bears quantity risk |
| FIDIC Yellow | D&B | Contractor | Single-point design + build responsibility |
| FIDIC Silver | EPC/Turnkey | Contractor | Maximum risk on contractor |
| FIDIC Gold | DBO | Contractor | Includes O&M phase |
| FIDIC Emerald | Underground | Varies | Tunnelling-specific risk sharing |
| NEC4 Option A | Activity Schedule | Varies | Lump sum with early warning mechanism |
| NEC4 Option C | Target Cost | Varies | Pain/gain sharing, Clause 10.1 good faith |
| PSSCOC | Government | Employer | Singapore public sector standard |
| SIA | Private | Employer | Singapore private sector standard |
| JCT | Various | Varies | UK standard forms |

## Workflow

### 1. Identify the Contract Form
**ALWAYS ask which edition/year of the contract form.** Many SG projects still use PSSCOC 2017 (7th Ed) even for new awards — don't assume the latest edition. Same applies to FIDIC (1999 vs 2017), SIA, NEC, and JCT.

Determine which standard form (or bespoke) applies. Check for amendments, particular conditions, and any deleted/modified clauses.

Common editions in active use:
- PSSCOC: 2017 (7th Ed) ← still widely used | 2020 (8th Ed)
- PSSCOC D&B: 2014 (6th Ed) | 2020 (7th Ed)
- FIDIC: 1999 (still common internationally) | 2017 (current)
- SIA: 9th Ed (2010) | 11th Ed
- NEC: NEC3 (still active) | NEC4 (current)

### 2. Clause Analysis
For any clause question:
- Quote the relevant clause number and edition
- Identify the obligation, right, or risk it creates
- Note any time-bars or notice requirements
- Cross-reference with related clauses
- Flag amendments that change the standard position

### 3. Claims Analysis Framework
For delay/disruption/EOT claims, follow this structure:

**Step 1 — Entitlement**: Identify the contractual basis (which clause?)
**Step 2 — Causation**: Establish cause-and-effect (what event → what delay?)
**Step 3 — Notice**: Verify notice requirements met (time-bar compliance)
**Step 4 — Substantiation**: Evidence and records supporting the claim
**Step 5 — Quantification**: Calculate time/cost impact

### 4. Notice Calendar
When building notice calendars, capture:
- Clause reference
- Trigger event
- Notice period (days)
- Recipient
- Consequence of non-compliance (time-bar? loss of entitlement?)

### 5. Risk Allocation Analysis
Risk should be allocated to the party best able to:
1. Identify that risk
2. Control that risk
3. Mitigate that risk
4. Absorb that risk

Incorrect allocation → pricing inflation, claims escalation, disputes.

## Reference Files

For detailed clause-by-clause analysis, load the relevant reference:

- **FIDIC analysis**: See [references/fidic.md](references/fidic.md) — Red, Yellow, Silver, Gold, Emerald clause guides, time-bars, notice requirements, DAAB procedures
- **Singapore contracts**: See [references/singapore.md](references/singapore.md) — PSSCOC, SIA Conditions, SOP Act, BCA regulatory framework, SIArb
- **Claims & EOT**: See [references/claims.md](references/claims.md) — Delay analysis methods (as-planned vs as-built, impacted as-planned, collapsed as-built, time impact analysis), disruption, prolongation, global claims, concurrent delay
- **Dispute resolution**: See [references/disputes.md](references/disputes.md) — DAB/DAAB, adjudication, arbitration, mediation, CAB, enforcement
- **Procurement & tendering**: See [references/procurement.md](references/procurement.md) — MDB frameworks, procurement strategy, evaluation methods, collaborative contracting

## Scripts (Premium Features)

Three automated tools for contract administration:

### Notice Calendar Generator
Generates a complete notice/obligations calendar for any supported contract form.
```bash
python3 scripts/notice_calendar.py --form fidic-red --format md
python3 scripts/notice_calendar.py --form psscoc --format csv --output notices.csv
```
Supported forms: `fidic-red`, `fidic-yellow`, `psscoc`, `sia`, `nec4`

### Claims Template Generator
Produces structured claim notices, EOT applications, variation claims, and interim payment templates.
```bash
python3 scripts/claims_template.py --list
python3 scripts/claims_template.py --form fidic-red --type notice-of-claim --output notice.md
python3 scripts/claims_template.py --form psscoc --type eot-application --output eot.md
```
Templates include: clause references, section structure, placeholder fields, reservation of rights.

### Obligations Register Generator
Creates a trackable register of Contractor and/or Employer obligations with priorities and categories.
```bash
python3 scripts/obligations_register.py --form fidic-red --party both --format md
python3 scripts/obligations_register.py --form psscoc --party contractor --format csv --output obligations.csv
```
Supported forms: `fidic-red`, `psscoc`, `sia`

### SOP Act Payment Timeline Calculator
Calculates all statutory deadlines from a payment claim date under Singapore's SOP Act.
```bash
python3 scripts/sop_calculator.py --claim-date 2026-06-30
python3 scripts/sop_calculator.py --claim-date 2026-06-30 --response-period 14 --format csv --output timeline.csv
```
Outputs: full timeline with critical deadlines, smash-and-grab warnings, time-bar alerts.

### FIDIC Contract Comparator
Side-by-side comparison of FIDIC Red, Yellow, Silver, and Emerald Books across 6 topics.
```bash
python3 scripts/fidic_comparator.py --forms red,yellow,silver --topic risk
python3 scripts/fidic_comparator.py --forms red,silver --topic all --format csv --output comparison.csv
```
Topics: `overview`, `risk`, `claims`, `disputes`, `payment`, `termination`, `all`

### Delay Analysis Calculator
Input delay events and get critical path impact analysis with EOT entitlement and LD exposure.
```bash
python3 scripts/delay_calculator.py --baseline-start 2026-05-11 --baseline-end 2030-05-10 \
  --add "Late access|2026-06-01|2026-06-30|employer|critical" \
  --add "Weather|2026-07-15|2026-07-25|neutral|critical"
python3 scripts/delay_calculator.py --baseline-start 2026-05-11 --baseline-end 2030-05-10 --events events.json --format json
```
Outputs: delay summary, EOT entitlement, LD exposure, concurrent delay detection, recommendations.

### Excel Register Generator
Exports obligations registers and notice calendars to formatted .xlsx with colour-coded priorities.
```bash
python3 scripts/excel_register.py --form fidic-red --type both --output contract_admin.xlsx --commencement 2026-05-11
python3 scripts/excel_register.py --form psscoc --type obligations --output obligations.xlsx
```
Requires: `openpyxl` (`pip3 install openpyxl`)

## Key Principles (Always Apply)

1. **Read the contract first** — standard form positions mean nothing if amended
2. **Time-bars are fatal** — always check notice periods before anything else
3. **Concurrent delay** — different jurisdictions treat this differently; state the applicable approach
4. **Good faith** — no general duty in English/Singapore law unless express (NEC Clause 10.1); mandatory in French law (Art. 1104)
5. **Fitness for purpose vs reasonable skill & care** — contractor design (Yellow/Silver) vs consultant design (White Book)
6. **Prevention principle** — employer cannot benefit from their own act of prevention; may override liquidated damages if no EOT mechanism exists


---
Source attribution: LeoYeAI
Original project: https://github.com/LeoYeAI/openclaw-master-skills/blob/e5199b56ae1ff72e141586c17695563486c46702/skills/construction-law/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Mega AI Hub.

## Upstream license notice

MIT License

Copyright (c) 2026 MyClaw.ai (LeoYeAI)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


## Additional upstream notices

construction-law-9c3ab0516872/scripts/notice_calendar.py

#!/usr/bin/env python3
"""
Notice Calendar Generator
Generates a notice/obligations calendar from a contract form selection.
Outputs CSV or Markdown table with all time-bars, notice periods, and key dates.

Usage:
    python3 notice_calendar.py --form fidic-red --format md
    python3 notice_calendar.py --form psscoc --format csv
    python3 notice_calendar.py --form sia --format csv --output notices.csv
    python3 notice_calendar.py --form fidic-yellow --commencement 2026-05-11 --completion 2030-05-10
"""

import argparse
import csv
import io
import sys
from datetime import datetime, timedelta

NOTICE_DATABASES = {
    "fidic-red": {
        "name": "FIDIC Red Book 2017 (Conditions of Contract for Construction)",
        "notices": [
            {"clause": "1.3", "event": "Contractor's Documents submission", "period": "As per Schedule", "recipient": "Engineer", "consequence": "Delay to programme", "category": "Administration"},
            {"clause": "4.12", "event": "Unforeseeable Physical Conditions encountered", "period": "As soon as practicable", "recipient": "Engineer", "consequence": "Loss of entitlement if not notified", "category": "Claims"},
            {"clause": "8.3", "event": "Programme submission", "period": "28 days from Commencement Date", "recipient": "Engineer", "consequence": "Payment may be withheld", "category": "Programme"},
            {"clause": "8.3", "event": "Revised programme submission", "period": "28 days from request/event", "recipient": "Engineer", "consequence": "Payment may be withheld", "category": "Programme"},
            {"clause": "8.4", "event": "EOT application", "period": "Under Clause 20.2 procedure", "recipient": "Engineer", "consequence": "Time-barred under 20.2", "category": "EOT"},
            {"clause": "13.3", "event": "Variation proposal response", "period": "As instructed by Engineer", "recipient": "Engineer", "consequence": "Engineer may instruct alternative", "category": "Variations"},
            {"clause": "14.3", "event": "Interim Payment Statement", "period": "Monthly (end of each month)", "recipient": "Engineer", "consequence": "Late payment", "category": "Payment"},
            {"clause": "14.6", "event": "Engineer issues IPC", "period": "28 days from receiving Statement", "recipient": "Contractor", "consequence": "Financing charges apply", "category": "Payment"},
            {"clause": "14.7", "event": "Employer payment due", "period": "56 days from Statement (if no IPC)", "recipient": "Contractor", "consequence": "Suspension/termination rights", "category": "Payment"},
            {"clause": "15.1", "event": "Notice to Correct", "period": "Reasonable period to correct", "recipient": "Contractor", "consequence": "May lead to termination", "category": "Default"},
            {"clause": "15.2", "event": "Termination by Employer", "period": "14 days notice after Notice to Correct", "recipient": "Contractor", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "16.1", "event": "Contractor's right to suspend", "period": "42 days after IPC due date unpaid", "recipient": "Employer", "consequence": "Works suspended", "category": "Payment"},
            {"clause": "16.2", "event": "Termination by Contractor", "period": "14 days notice", "recipient": "Employer", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "18.2", "event": "Exceptional Event notice", "period": "14 days from awareness", "recipient": "Other Party", "consequence": "Loss of entitlement", "category": "Force Majeure"},
            {"clause": "18.5", "event": "Optional termination (Exceptional Event >84 days)", "period": "7 days notice", "recipient": "Other Party", "consequence": "Contract terminated", "category": "Force Majeure"},
            {"clause": "20.2.1", "event": "Notice of Claim (Contractor)", "period": "28 days from awareness", "recipient": "Engineer", "consequence": "TIME-BARRED — claim lost", "category": "Claims"},
            {"clause": "20.2.4", "event": "Fully detailed claim submission", "period": "84 days from Notice of Claim", "recipient": "Engineer", "consequence": "Claim may be reduced", "category": "Claims"},
            {"clause": "20.2.7", "event": "Engineer notifies late notice", "period": "14 days from receiving late notice", "recipient": "Contractor", "consequence": "If Engineer fails to notify, time-bar may not apply", "category": "Claims"},
            {"clause": "20.1", "event": "Notice of Claim (Employer)", "period": "28 days from awareness", "recipient": "Contractor", "consequence": "TIME-BARRED — claim lost", "category": "Claims"},
            {"clause": "21.4", "event": "Referral to DAAB", "period": "28 days after Engineer's determination (or failure)", "recipient": "DAAB", "consequence": "Lose right to refer", "category": "Disputes"},
            {"clause": "21.4.4", "event": "Notice of Dissatisfaction (NOD)", "period": "28 days after DAAB decision", "recipient": "Other Party", "consequence": "Decision becomes FINAL & BINDING", "category": "Disputes"},
            {"clause": "21.6", "event": "Arbitration notice", "period": "After NOD + 28 days cooling off", "recipient": "Other Party", "consequence": "Must arbitrate or accept DAAB decision", "category": "Disputes"},
        ]
    },
    "fidic-yellow": {
        "name": "FIDIC Yellow Book 2017 (Conditions of Contract for Plant & Design-Build)",
        "notices": [
            {"clause": "5.1", "event": "Contractor's design documents submission", "period": "Per programme", "recipient": "Engineer", "consequence": "Delay to programme", "category": "Design"},
            {"clause": "5.1", "event": "Notify Engineer of errors in Employer's Requirements", "period": "As soon as discovered", "recipient": "Engineer", "consequence": "Contractor bears risk if should have discovered", "category": "Design"},
            {"clause": "8.3", "event": "Programme submission", "period": "28 days from Commencement Date", "recipient": "Engineer", "consequence": "Payment may be withheld", "category": "Programme"},
            {"clause": "13.3", "event": "Variation proposal response", "period": "As instructed by Engineer", "recipient": "Engineer", "consequence": "Engineer may instruct alternative", "category": "Variations"},
            {"clause": "14.3", "event": "Interim Payment Statement", "period": "Monthly", "recipient": "Engineer", "consequence": "Late payment", "category": "Payment"},
            {"clause": "20.2.1", "event": "Notice of Claim (Contractor)", "period": "28 days from awareness", "recipient": "Engineer", "consequence": "TIME-BARRED — claim lost", "category": "Claims"},
            {"clause": "20.2.4", "event": "Fully detailed claim submission", "period": "84 days from Notice of Claim", "recipient": "Engineer", "consequence": "Claim may be reduced", "category": "Claims"},
            {"clause": "20.1", "event": "Notice of Claim (Employer)", "period": "28 days from awareness", "recipient": "Contractor", "consequence": "TIME-BARRED — claim lost", "category": "Claims"},
            {"clause": "21.4", "event": "Referral to DAAB", "period": "28 days after Engineer's determination", "recipient": "DAAB", "consequence": "Lose right to refer", "category": "Disputes"},
            {"clause": "21.4.4", "event": "NOD", "period": "28 days after DAAB decision", "recipient": "Other Party", "consequence": "Decision becomes FINAL & BINDING", "category": "Disputes"},
        ]
    },
    "psscoc": {
        "name": "PSSCOC (Public Sector Standard Conditions of Contract — Construction Works)",
        "notices": [
            {"clause": "14", "event": "Variation order issued by SO", "period": "As instructed", "recipient": "Contractor", "consequence": "Must comply; dispute valuation later", "category": "Variations"},
            {"clause": "23(1)", "event": "EOT application", "period": "28 days from commencement of delay event", "recipient": "SO", "consequence": "May lose EOT entitlement", "category": "EOT"},
            {"clause": "23(1)", "event": "EOT application — particulars", "period": "Include cause, expected duration, mitigation measures", "recipient": "SO", "consequence": "Incomplete application may be rejected", "category": "EOT"},
            {"clause": "24", "event": "Delay certificate issued by SO", "period": "After completion date passed without EOT", "recipient": "Contractor", "consequence": "Liquidated damages apply", "category": "Delay"},
            {"clause": "25", "event": "Completion certificate application", "period": "When works substantially complete", "recipient": "SO", "consequence": "Delays DLP start and payment release", "category": "Completion"},
            {"clause": "27", "event": "Defects notification during maintenance period", "period": "During DLP (typically 12 months)", "recipient": "Contractor", "consequence": "Must rectify at own cost", "category": "Defects"},
            {"clause": "32", "event": "Interim payment valuation", "period": "Monthly", "recipient": "SO", "consequence": "Delays payment", "category": "Payment"},
            {"clause": "33", "event": "Final account submission", "period": "Within period stated in contract", "recipient": "SO", "consequence": "Delays final payment", "category": "Payment"},
            {"clause": "37", "event": "Determination by Employer — notice", "period": "Notice required before determination", "recipient": "Contractor", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "38", "event": "Determination by Contractor", "period": "Notice for non-payment/employer default", "recipient": "Employer", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "40", "event": "Dispute — mediation request", "period": "As per dispute resolution clause", "recipient": "Other Party", "consequence": "Proceed to arbitration if unresolved", "category": "Disputes"},
        ]
    },
    "sia": {
        "name": "SIA Conditions (9th Edition 2010)",
        "notices": [
            {"clause": "11", "event": "Variation instruction by Architect", "period": "As instructed", "recipient": "Contractor", "consequence": "Must comply", "category": "Variations"},
            {"clause": "23(1)", "event": "EOT application", "period": "Written notice required", "recipient": "Architect", "consequence": "May lose entitlement", "category": "EOT"},
            {"clause": "24(1)", "event": "Delay certificate", "period": "Architect certifies after completion date", "recipient": "Contractor", "consequence": "LDs apply from certificate date", "category": "Delay"},
            {"clause": "25", "event": "Completion certificate application", "period": "When substantially complete", "recipient": "Architect", "consequence": "DLP starts; retention release triggered", "category": "Completion"},
            {"clause": "27", "event": "Defects schedule", "period": "During DLP (typically 12 months)", "recipient": "Contractor", "consequence": "Must rectify at own cost", "category": "Defects"},
            {"clause": "30", "event": "Interim certificate by Architect", "period": "Monthly or as specified", "recipient": "Employer", "consequence": "Payment due within 30 days", "category": "Payment"},
            {"clause": "31", "event": "Final account submission", "period": "Within specified period after completion", "recipient": "Architect/QS", "consequence": "Delays final payment", "category": "Payment"},
            {"clause": "33", "event": "Determination by Employer", "period": "Notice required", "recipient": "Contractor", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "34", "event": "Determination by Contractor", "period": "Notice for non-payment", "recipient": "Employer", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "37", "event": "Arbitration notice", "period": "Per dispute resolution clause", "recipient": "Other Party", "consequence": "Dispute referred to arbitration", "category": "Disputes"},
        ]
    },
    "nec4": {
        "name": "NEC4 Engineering and Construction Contract",
        "notices": [
            {"clause": "15.1", "event": "Early warning notification", "period": "As soon as aware of matter that could affect cost/time/quality", "recipient": "Project Manager", "consequence": "Loss of entitlement to additional time/cost", "category": "Early Warning"},
            {"clause": "61.3", "event": "Compensation event notification", "period": "8 weeks from awareness", "recipient": "Project Manager", "consequence": "TIME-BARRED — event not notified", "category": "Claims"},
            {"clause": "62.3", "event": "Compensation event quotation", "period": "3 weeks from instruction to quote", "recipient": "Project Manager", "consequence": "PM may make own assessment", "category": "Claims"},
            {"clause": "64.1", "event": "PM response to CE quotation", "period": "2 weeks from receiving quotation", "recipient": "Contractor", "consequence": "Quotation deemed accepted", "category": "Claims"},
            {"clause": "50.1", "event": "Payment application", "period": "Per assessment dates in Contract Data", "recipient": "Project Manager", "consequence": "Delays payment", "category": "Payment"},
            {"clause": "91.2", "event": "Termination notice", "period": "Per termination table", "recipient": "Other Party", "consequence": "Contract terminated", "category": "Default"},
            {"clause": "W1/W2", "event": "Dispute referral to Adjudicator", "period": "4 weeks from notification of dispute", "recipient": "Adjudicator", "consequence": "Lose right to refer specific dispute", "category": "Disputes"},
        ]
    }
}

def generate_calendar(form, fmt, output=None, commencement=None, completion=None):
    if form not in NOTICE_DATABASES:
        print(f"Error: Unknown form '{form}'. Available: {', '.join(NOTICE_DATABASES.keys())}")
        sys.exit(1)

    db = NOTICE_DATABASES[form]
    notices = db["notices"]

    # Sort by category then clause
    notices.sort(key=lambda x: (x["category"], x["clause"]))

    if fmt == "csv":
        output_stream = open(output, 'w', newline='') if output else sys.stdout
        writer = csv.writer(output_stream)
        writer.writerow(["Contract Form", db["name"]])
        if commencement:
            writer.writerow(["Commencement Date", commencement])
        if completion:
            writer.writerow(["Completion Date", completion])
        writer.writerow([])
        writer.writerow(["Clause", "Event/Obligation", "Notice Period", "Recipient", "Consequence of Non-Compliance", "Category"])
        for n in notices:
            writer.writerow([n["clause"], n["event"], n["period"], n["recipient"], n["consequence"], n["category"]])
        if output:
            output_stream.close()
            print(f"CSV written to {output}")

    elif fmt == "md":
        lines = []
        lines.append(f"# Notice Calendar — {db['name']}")
        lines.append("")
        if commencement:
            lines.append(f"**Commencement Date:** {commencement}")
        if completion:
            lines.append(f"**Completion Date:** {completion}")
        lines.append(f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}")
        lines.append("")

        # Group by category
        categories = {}
        for n in notices:
            cat = n["category"]
            if cat not in categories:
                categories[cat] = []
            categories[cat].append(n)

        for cat, items in categories.items():
            lines.append(f"## {cat}")
            lines.append("")
            lines.append("| Clause | Event/Obligation | Period | Recipient | Consequence |")
            lines.append("|--------|-----------------|--------|-----------|-------------|")
            for n in items:
                lines.append(f"| {n['clause']} | {n['event']} | {n['period']} | {n['recipient']} | {n['consequence']} |")
            lines.append("")

        result = "\n".join(lines)
        if output:
            with open(output, 'w') as f:
                f.write(result)
            print(f"Markdown written to {output}")
        else:
            print(result)

def main():
    parser = argparse.ArgumentParser(description="Generate notice/obligations calendar for construction contracts")
    parser.add_argument("--form", required=True, choices=list(NOTICE_DATABASES.keys()),
                       help="Contract form")
    parser.add_argument("--format", default="md", choices=["md", "csv"],
                       help="Output format (default: md)")
    parser.add_argument("--output", "-o", help="Output file path (default: stdout)")
    parser.add_argument("--commencement", help="Commencement date (YYYY-MM-DD)")
    parser.add_argument("--completion", help="Completion date (YYYY-MM-DD)")
    args = parser.parse_args()
    generate_calendar(args.form, args.format, args.output, args.commencement, args.completion)

if __name__ == "__main__":
    main()


# Mega AI Hub resource metadata

Creator / publisher: LeoYeAI
Original project: https://github.com/LeoYeAI/openclaw-master-skills/blob/e5199b56ae1ff72e141586c17695563486c46702/skills/construction-law/SKILL.md
Attribution basis: Source repository record

Fields of work: Legal, Project & Program Management
Roles: Compliance Officer, Corporate Lawyer, Project Manager
Specialties: Specialty not specified
Tools: Tool not specified
Country applicability: Singapore
Classification basis: Source catalog labels
Instruction SHA-256: 5e019900895521df3d3db56446372cc783f862f318947cf92a1730c9cdac3c55
