AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Okhp3 Tradition Observance Calendar

skill-okhp3-skillz-okhp3-tradition-observance-calendar · by OKHP3

>

No reviews yet
0 installs
12 views
0.0% view→install

Install

$ agentstack add skill-okhp3-skillz-okhp3-tradition-observance-calendar

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-okhp3-skillz-okhp3-tradition-observance-calendar)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
16d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Okhp3 Tradition Observance Calendar? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

okhp3-tradition-observance-calendar

OverKill Hill P³ · overkillhill.com · github.com/OKHP3

Fetch, compute, and format religious observance calendars for the Abrahamic Reference Engine.

Covers Judaism (Hebcal API), Christianity (Computus algorithm -- Western and Orthodox), and Islam (AlAdhan API). All sources are free and anonymous. No API key. No cost. Zero runtime dependencies beyond fetch.

Execution contract

  • Accept a target year and optional tradition or denomination filter. Validate

the year before constructing provider URLs or date objects.

  • Normalize every source into ObservanceEvent and retain the source,

attribution, and caveat fields. Computed dates, provider dates, and missing dates must remain distinguishable.

  • Use Promise.allSettled for independent provider or month requests so one

outage does not discard successful results. Surface partial failure in the UI or return metadata rather than hiding it.

  • Do not replace the deterministic Christian Computus path with a paid,

credentialed, or unverified holiday API. Run the bundled Easter validator after algorithm changes.

  • Treat Islamic dates as calendar estimates. State the local moon-sighting

caveat, and never present an estimated date as universally authoritative.

  • Fetch Wikipedia descriptions lazily, cache only non-sensitive results, and

display the exact attribution string with the returned article URL.

  • Escape user- or provider-derived values before inserting them into .ics.

Follow the bundled RFC 5545 line-folding and date rules.


Bundled reference files

Read these on demand -- only the file(s) you actually need for the current task:

| File | When to read | |------|-------------| | references/api-reference.md | Full API schemas and field details for Hebcal and AlAdhan; use when you need the complete response shape or want to understand all available query parameters | | references/computus.md | Computus algorithm derivation, edge cases, century correction, and multi-century validation dates; use when troubleshooting Easter date accuracy | | references/holiday-data.md | Extended WIKIPEDIA_ARTICLE_MAP entries and supplementary AlAdhan display name notes; use when adding a holiday not covered by the map in this file | | references/ics-spec.md | ICS format specification, RFC 5545 line-folding rules, calendar client compatibility notes, and VTIMEZONE considerations |

The SKILL.md sections below are sufficient for most implementation tasks. Reach for the reference files when you need depth beyond what is documented here.


1. Scope Rules

A holiday is in scope if and only if it meets both criteria:

  1. Abrahamic lineage -- traces its roots to the Abrahamic covenant
  2. US population threshold -- practiced by a tradition representing ≥1% of the US population per Pew Research Center

| Tradition | US Share | In Scope | |---|---|---| | Christianity | ~63% | Yes -- five denominational lenses | | Judaism | ~2% | Yes | | Islam | ~1% | Yes | | Hinduism | ~1% | No (not Abrahamic) | | Buddhism | ~1% | No (not Abrahamic) | | Baha'i | ~0.1% | No (Abrahamic but below threshold) |

Source: Pew Research Center -- https://www.pewresearch.org/religion/religious-landscape-study/


2. Unified Event Type

All holiday sources normalize to this shared interface:

interface ObservanceEvent {
  id: string;           // "{tradition}-{rawName}-{year}-{startDateISO}"
  title: string;        // emoji-prefixed: "✡️ Rosh Hashanah"
  rawName: string;      // without emoji: "Rosh Hashanah"
  emoji: string;        // "✡️" | "✝️" | "☦️" | "☪️"
  tradition: 'judaism' | 'christianity' | 'islam';
  denomination: 'all' | 'catholic' | 'orthodox' | 'protestant' | 'evangelical' | 'restorationist';
  startDate: Date;
  endDate: Date;        // equals startDate for single-day events
  isMultiDay: boolean;
  hebrewName?: string;  // Jewish holidays only
  hijriDate?: string;   // Islamic holidays only, e.g., "1 Muharram 1448 AH"
  sourceUrl?: string;   // Hebcal permalink or Wikipedia URL
  source: 'hebcal' | 'aladhan' | 'algorithm';
  wikiArticle?: string; // Wikipedia article title for description fetch (Section 5)
}

3. Emoji Registry

export const TRADITION_EMOJI = {
  judaism:               '✡️',   // U+2721 U+FE0F  Star of David
  christianity_western:  '✝️',   // U+271D U+FE0F  Latin Cross
  christianity_orthodox: '☦️',   // U+2626 U+FE0F  Orthodox Cross
  islam:                 '☪️',   // U+262A U+FE0F  Star and Crescent
} as const;

Use ✝️ for Catholic, Mainline Protestant, Evangelical, and Restorationist events. Use ☦️ for Orthodox-specific events and dates.


4. Jewish Holidays -- Hebcal REST API

No API key. CC BY 4.0. Free.

4.1 Endpoint

GET https://www.hebcal.com/hebcal?v=1&cfg=json&year={year}&maj=on&min=off&nx=off&mf=off&ss=on&mod=on&i=off&lg=s&m=50

Parameters that matter:

  • maj=on -- major holidays (required)
  • ss=on -- special Shabbatot
  • mod=on -- modern Israeli holidays (Yom HaShoah, Yom HaAtzmaut)
  • i=off -- Diaspora rules (not Israeli rules -- ARE targets US audience)
  • min=off -- minor holidays off by default (expose as optional filter)

4.2 Fetch pattern

async function fetchJewishHolidays(year: number): Promise {
  const cacheKey = `are_hebcal_${year}`;
  const cached = sessionStorage?.getItem(cacheKey);
  if (cached) return JSON.parse(cached);

  const url = `https://www.hebcal.com/hebcal?v=1&cfg=json&year=${year}&maj=on&min=off&nx=off&mf=off&ss=on&mod=on&i=off&lg=s&m=50`;
  const res = await fetch(url);
  if (!res.ok) throw new Error(`Hebcal fetch failed: ${res.status}`);
  const data = await res.json();

  const items: HebcalItem[] = (data.items || []).filter(
    (item: HebcalItem) => item.category === 'holiday'
  );

  const events = normalizeHebcalItems(items, year);
  sessionStorage?.setItem(cacheKey, JSON.stringify(events));
  return events;
}

4.3 Response item shape

{
  "title": "Rosh Hashana 5787",
  "date": "2026-09-20",
  "hdate": "1 Tishrei 5787",
  "category": "holiday",
  "subcat": "major",
  "hebrew": "ראש השנה",
  "link": "https://www.hebcal.com/holidays/rosh-hashana-5787",
  "memo": "Jewish New Year"
}

4.4 Normalization rules

  • Strip Hebrew year suffix from title for display: "Rosh Hashana 5787""Rosh Hashana"
  • Detect multi-day events by grouping items with matching normalized base name across consecutive dates
  • Set endDate to the last consecutive day with the same name; isMultiDay = true when span > 1
  • Populate hebrewName from hebrew field
  • Populate sourceUrl from link field
  • Populate wikiArticle from WIKIPEDIA_ARTICLE_MAP[normalizedName] (see Section 5)
  • Set emoji = '✡️', tradition = 'judaism', denomination = 'all'

4.5 Attribution

Display in UI: "Calendar data via Hebcal.com (CC BY 4.0)" Link: https://www.hebcal.com


5. Islamic Holidays -- AlAdhan REST API

No API key. Free. GPL-3.0.

5.1 Strategy

AlAdhan embeds holiday data in each day of the Gregorian-to-Hijri calendar response. Fetch all 12 months in parallel; collect days where date.hijri.holidays is non-empty.

5.2 Endpoint (per month)

GET https://api.aladhan.com/v1/gToHCalendar/{month}/{year}

5.3 Fetch pattern

> WARNING -- use Promise.allSettled, NOT Promise.all. > AlAdhan occasionally drops individual month requests. > Promise.all fails fast and discards all 11 other successful months. > Promise.allSettled continues and collects partial results gracefully. > This is a hard requirement, not a suggestion.

async function fetchIslamicHolidays(year: number): Promise {
  const cacheKey = `are_aladhan_${year}`;
  const cached = sessionStorage?.getItem(cacheKey);
  if (cached) return JSON.parse(cached);

  const months = Array.from({ length: 12 }, (_, i) => i + 1);
  const responses = await Promise.allSettled(
    months.map(m =>
      fetch(`https://api.aladhan.com/v1/gToHCalendar/${m}/${year}`)
        .then(r => r.ok ? r.json() : Promise.reject(r.status))
    )
  );

  const allDays: AladhanDay[] = responses.flatMap(result =>
    result.status === 'fulfilled' ? result.value.data || [] : []
  );

  const events = normalizeAladhanDays(allDays, year);
  sessionStorage?.setItem(cacheKey, JSON.stringify(events));
  return events;
}

5.4 Response day shape (relevant fields)

{
  "gregorian": {
    "date": "20-03-2026",
    "year": "2026",
    "month": { "en": "March" },
    "day": "20"
  },
  "hijri": {
    "date": "01-09-1447",
    "year": "1447",
    "month": { "en": "Ramaḍān", "number": 9 },
    "day": "01",
    "holidays": ["Start of Ramadan"]
  }
}

5.5 Allowed holiday filter (US mainstream Sunni/general Islamic)

Only include days where at least one entry in holidays[] matches this allowed set:

const ALADHAN_ALLOWED: Set = new Set([
  "Arafat (Haj) Day",
  "Eid-ul-Adha",
  "Islamic New Year",
  "Ashura",
  "Mawlid al-Nabi",
  "Al Isra' Wal Mi'raj",
  "Start of Ramadan",
  "Laylat al Qadr",
  "Eid ul Fitr",
]);

Discard any holiday string not in this set. Discard days where holidays is empty.

5.6 Display name normalization

const ALADHAN_DISPLAY_NAMES: Record = {
  "Arafat (Haj) Day":    "Day of Arafah",
  "Eid-ul-Adha":         "Eid al-Adha",
  "Islamic New Year":    "Islamic New Year (Muharram 1)",
  "Ashura":              "Ashura",
  "Mawlid al-Nabi":      "Mawlid al-Nabi (Prophet's Birthday)",
  "Al Isra' Wal Mi'raj": "Isra and Mi'raj (Night Journey)",
  "Start of Ramadan":    "First Day of Ramadan",
  "Laylat al Qadr":      "Laylat al-Qadr (Night of Power)",
  "Eid ul Fitr":         "Eid al-Fitr",
};

5.7 Multi-day detection

Eid al-Adha and Eid al-Fitr may appear across 2–3 consecutive days. Group consecutive days with the same normalized display name into a single event. Set endDate to the last day; isMultiDay = true.

5.8 Moon sighting caveat

Always display alongside Islamic events: > "Islamic dates are calculated using the Umm al-Qura method. Actual observance may vary by one day based on local moon sighting."

5.9 Attribution

Display in UI: "Islamic calendar data via AlAdhan.com" Link: https://aladhan.com


6. Christian Holidays -- TypeScript Algorithm

No external API. Fully client-side. Zero dependencies.

6.1 Western Easter (Gregorian Computus)

function computeWesternEaster(year: number): Date {
  const a = year % 19;
  const b = Math.floor(year / 100);
  const c = year % 100;
  const d = Math.floor(b / 4);
  const e = b % 4;
  const f = Math.floor((b + 8) / 25);
  const g = Math.floor((b - f + 1) / 3);
  const h = (19 * a + b - d - g + 15) % 30;
  const i = Math.floor(c / 4);
  const k = c % 4;
  const l = (32 + 2 * e + 2 * i - h - k) % 7;
  const m = Math.floor((a + 11 * h + 22 * l) / 451);
  const month = Math.floor((h + l - 7 * m + 114) / 31);
  const day = ((h + l - 7 * m + 114) % 31) + 1;
  return new Date(year, month - 1, day);
}

Validation: 2026 → April 5 | 2027 → March 28

6.2 Orthodox Easter (Julian Computus + Gregorian offset)

function computeOrthodoxEaster(year: number): Date {
  const a = year % 4;
  const b = year % 7;
  const c = year % 19;
  const d = (19 * c + 15) % 30;
  const e = (2 * a + 4 * b - d + 34) % 7;
  const f = Math.floor((d + e + 114) / 31);
  const g = ((d + e + 114) % 31) + 1;
  // Julian result; add 13 days for 20th/21st century Gregorian conversion
  const result = new Date(year, f - 1, g + 13);
  return result;
}

Validation: 2026 → April 12 | 2027 → May 2

6.3 Holiday generation

Generate from the two Easter anchors, preserving denomination labels and stable event IDs. Read references/computus.md for the complete deterministic implementation, feast inventory, and validation dates.


7. Event Description -- Wikipedia REST API

No API key. Free. CC BY-SA 3.0. No external cost.

7.1 Endpoint

GET https://en.wikipedia.org/api/rest_v1/page/summary/{article_title}

7.2 Fetch pattern

Fetch on user interaction only and cache by article title. Read references/api-reference.md for the error-safe fetch pattern and references/holiday-data.md for the complete article map. Do not pre-fetch all descriptions on calendar load.

7.4 Attribution

Always display in UI: "Description via Wikipedia (CC BY-SA 3.0)" with link to the Wikipedia article URL returned by the API.


8. iCalendar (.ics) Generation

Generate client-side only. Preserve RFC 5545 all-day DATE semantics, use an exclusive end date, escape content, and include a stable UID. Read references/ics-spec.md for the full implementation and interoperability requirements.


9. Session Caching Strategy

| Data | Cache key | When to populate | When to invalidate | |---|---|---|---| | Hebcal annual result | are_hebcal_{year} | On first tab open for that year | Session end | | AlAdhan annual result | are_aladhan_{year} | On first tab open for that year | Session end | | Christian holidays | In-memory (computed) | On tab open | Never (deterministic) | | Wikipedia description | are_wiki_{articleTitle} | On first event click | Session end |

Use sessionStorage in browser contexts. In Node/agent contexts, use a simple in-memory Map.


10. Attribution Requirements

Always include the following when presenting output from this skill:

| Source | Attribution text | |---|---| | Hebcal | "Calendar data via Hebcal.com (CC BY 4.0)" | | AlAdhan | "Islamic calendar data via AlAdhan.com" | | Algorithm | "Christian holiday dates computed per ecclesiastical calendar" | | Wikipedia | "Description via Wikipedia (CC BY-SA 3.0)" |


11. Validation Reference

| Holiday | Year | Correct Date | |---|---|---| | Western Easter | 2026 | April 5 | | Western Easter | 2027 | March 28 | | Orthodox Easter | 2026 | April 12 | | Orthodox Easter | 2027 | May 2 | | Ash Wednesday | 2026 | February 18 | | Good Friday | 2026 | April 3 | | Pentecost | 2026 | May 24 | | Orthodox Christmas | any | January 7 | | Theophany | any | January 19 | | Rosh Hashanah | 2026 | September 20–21 | | Yom Kippur | 2026 | September 29 |


12. Usage Examples

Fetch all observances for 2026:

const [jewish, islamic] = await Promise.allSettled([
  fetchJewishHolidays(2026),
  fetchIslamicHolidays(2026),
]);
const christian = generateChristianHolidays(2026);

const allEvents: ObservanceEvent[] = [
  ...(jewish.status === 'fulfilled' ? jewish.value : []),
  ...(islamic.status === 'fulfilled' ? islamic.value : []),
  ...christian,
].sort((a, b) => a.startDate.getTime() - b.startDate.getTime());

Get description for a holiday:

const description = await getHolidayDescription('Rosh Hashanah');
if (description) {
  console.log(description.extract);   // Wikipedia text
  console.log(description.wikiUrl);   // Attribution link
}

Generate and download a full-year .ics:

const icsContent = generateICS(allEvents, 'ARE Observances 2026');
downloadICS(icsContent, 'ARE-Observances-2026.ics');

Filter by tradition:

const jewishOnly = allEvents.filter(e => e.tradition === 'judaism');
const orthodoxOnly = allEvents.filter(e => e.denomination === 'orthodox');

Validation script

A date-accuracy validation script ships with this skill:

node .agents/skills/okhp3-tradition-observance-calendar/scripts/validate-easter.js

Validates Western and Orthodox Easter computation against 11 known-correct dates each (US Naval Observatory / Ecumenical Patriarchate). Exit 0 = clean. Run after any change to the Computus algorithm.


About

Built by Jamie Hill · OverKill Hill P³ Published at

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.