Update to FactIQ
Snapshot Oct 28, 2026 · 12:25 UTC · version 0.41.1
Package or technical metadata updated
Package or technical metadata updated
Observed in package metadata. These changes alone do not establish a new customer-facing feature.
Up to 10 plugins free · no card required.
All fields and original values.
These are saved file metadata. Open a changed file to read its text edits.
Package file
Sep 30, 2026 · 23:07 UTC
{"sha256":"34235df105b1fcd3e30dacd9793ed81848078adc18bed0df6fd01837e0473b42","size":127}
Oct 28, 2026 · 12:25 UTC
Not present
Package file
Sep 30, 2026 · 23:07 UTC
Not present
Oct 28, 2026 · 12:25 UTC
{"sha256":"49fb6b53e79d5715aa9a9a093a0bf8d7f3dbd8b9a9328bb9ae21b336aa88cf49","size":610}
Package file
Sep 30, 2026 · 23:07 UTC
Not present
Oct 28, 2026 · 12:25 UTC
{"sha256":"dec61fe1e1790fd335e220e1c54c16120e2e7632e16e044fe32f010d58d9c36e","size":927}
Package file
Sep 30, 2026 · 23:07 UTC
40992ee953af3848c3a0f65115d97dea99dcb6e0cd84aad7ae5539b6173ef4b3
Oct 28, 2026 · 12:25 UTC
add8506ef8caab254eb8e3518555c6a398af5aea31b7e1089d38ff02d4ea2cf9
Compare saved observations
Download comparison JSONChanged files
Choose a file to see its text changes. Binary or large files show metadata only.
.claude-plugin/marketplace.json →
LICENSE →
SETUP.md →
evals/bilateral-trade-sql/graders/one-hs-level-only.md →
evals/bilateral-trade-sql/graders/partner-code-is-numeric.md →
evals/bilateral-trade-sql/graders/used-the-bundled-generator.md →
evals/bilateral-trade-sql/graders/value-series-only.md →
evals/bilateral-trade-sql/prompt.md →
evals/filings-duplicate-line/graders/figure-is-not-doubled.md →
evals/filings-duplicate-line/graders/figure-is-the-first-line.md →
evals/filings-duplicate-line/graders/no-invented-filing-links.md →
evals/filings-duplicate-line/graders/source-link-is-the-filing.md →
evals/filings-duplicate-line/prompt.md →
evals/latest-value-direct-answer/graders/answers-in-prose.md →
evals/latest-value-direct-answer/graders/no-chart-file-written.md →
evals/latest-value-direct-answer/prompt.md →
evals/mocks/factiq/_tools.json →
evals/mocks/factiq/describe_dataset.md →
evals/mocks/factiq/fixtures/LNS14000000.json →
evals/mocks/factiq/fixtures/PKG.json →
evals/mocks/factiq/get_data_catalog.md →
evals/mocks/factiq/get_series.md →
evals/mocks/factiq/get_style_guides.md →
evals/mocks/factiq/run_sql.md →
evals/mocks/factiq/search_company_filings.md →
evals/mocks/factiq/search_datasets.md →
evals/mocks/factiq/search_earnings_transcripts.md →
evals/mocks/factiq/search_series.md →
evals/quick-chart-of-a-trend/graders/answer-states-gap-and-source.md →
evals/quick-chart-of-a-trend/graders/chart-file-written.md →
evals/quick-chart-of-a-trend/graders/missing-month-is-not-filled-in.md →
evals/quick-chart-of-a-trend/graders/spec-is-a-valid-chartspec.md →
evals/quick-chart-of-a-trend/graders/title-makes-a-claim.md →
evals/quick-chart-of-a-trend/prompt.md →
evals/quote-and-source-discipline/graders/analyst-framing-is-not-management.md →
evals/quote-and-source-discipline/graders/link-fy2025q2-is-the-supplied-one.md →
evals/quote-and-source-discipline/graders/link-fy2026q4-is-the-supplied-one.md →
evals/quote-and-source-discipline/graders/link-fy2027q1-is-the-supplied-one.md →
evals/quote-and-source-discipline/graders/missing-link-is-declared.md →
evals/quote-and-source-discipline/graders/no-invented-source-links.md →
evals/quote-and-source-discipline/graders/quotes-are-verbatim.md →
evals/quote-and-source-discipline/prompt.md →
evals/unrelated-coding-request/graders/answers-the-python-question.md →
evals/unrelated-coding-request/graders/no-catalog-lookup.md →
evals/unrelated-coding-request/graders/no-factiq-skill-invoked.md →
evals/unrelated-coding-request/graders/no-series-fetch.md →
evals/unrelated-coding-request/graders/no-sql-call.md →
evals/unrelated-coding-request/prompt.md →
evals/yoy-across-a-missing-month/graders/missing-month-is-stated.md →
evals/yoy-across-a-missing-month/graders/yoy-values-are-date-matched.md →
evals/yoy-across-a-missing-month/prompt.md →
evals/yoy-without-a-server-hint/graders/missing-month-is-stated.md →
evals/yoy-without-a-server-hint/graders/yoy-values-are-date-matched.md →
evals/yoy-without-a-server-hint/mocks/factiq/fixtures/LNS14000000.json →
evals/yoy-without-a-server-hint/mocks/factiq/get_series.md →
evals/yoy-without-a-server-hint/mocks/factiq/run_sql.md →
evals/yoy-without-a-server-hint/prompt.md →
references/data/satellite.md →
references/data/sql-guide.md →
references/output/chart-spec.md →
references/output/report-spec.md →
references/report-patterns/README.md →
references/report-patterns/bilateral-economic-policy.md →
references/report-patterns/bilateral-trade.md →
references/report-patterns/business-formation-statistics.md →
references/report-patterns/earnings-intelligence.md →
references/report-patterns/fiscal-policy-revenue.md →
references/report-patterns/interview-step.md →
references/report-patterns/media-intelligence.md →
references/report-patterns/monetary-policy.md →
scripts/__pycache__/term_chart.cpython-312.pyc →
scripts/data/hs_names.json.gz →
scripts/data/trade_partners.json →
tests/__pycache__/test_directory_submission_readiness.cpython-311-pytest-9.1.1.pyc →
tests/__pycache__/test_earnings_docs.cpython-311-pytest-9.1.1.pyc →
tests/__pycache__/test_earnings_docs.cpython-312-pytest-8.4.0.pyc →
tests/__pycache__/test_media_docs.cpython-311-pytest-9.1.1.pyc →
tests/__pycache__/test_media_docs.cpython-312-pytest-8.4.0.pyc →
tests/__pycache__/test_retired_publishing_tools.cpython-311-pytest-9.1.1.pyc →
tests/__pycache__/test_trade_scripts.cpython-311-pytest-9.1.1.pyc →
tests/__pycache__/test_trade_scripts.cpython-312-pytest-8.4.0.pyc →
tests/test_directory_submission_readiness.py →
scripts/trade_sql.py
− removed · + added
--- before +++ after @@ -0,0 +1,645 @@ +#!/usr/bin/env python3 +"""Generate ready-to-run SQL for the national customs trade schemas. + +Covers the six reporter datasets that share one series-ID grammar — +`{dataset}_{M|X}_{N}d_{hscode}_{partnercode}[_qty]`: + + source schema HS levels value unit quantity series + census census 6, 10 US$ _qty (10-digit only) + china china_customs 6, 8 US$ _qty (unit varies) + india india_trade 6, 8 US$ Million none + korea korea_trade 6, 10 US$ Thousand _qty (kg) + japan japan_trade 9 ¥ Thousand _qty and _qty2 (units vary) + taiwan taiwan_trade 6, 11 US$ none + +It encodes the traps for you: partner codes are per-source (numeric for +census/china/india/japan, ISO2 for korea/taiwan — resolved from a bundled +map), exactly one HS level per query (levels double-count each other), +value and quantity series never mix, and units differ per source (never sum +India's US$ Million with Korea's US$ Thousand without rescaling). + +Run the output with the run_sql tool using the schema in the header comment. +Mirror caveat: each source is that country's own customs view; reporter +views of the same flow differ on valuation, timing, and re-exports. + +Examples: + python3 "{plugin_root}/scripts/trade_sql.py" total --source census --partner China --flow imports \ + --start 2025-01 --end 2025-12 --monthly + python3 "{plugin_root}/scripts/trade_sql.py" products --source india --partner "united states" \ + --flow exports --start 2025-01 --end 2025-12 --group-by 2 --top 20 + python3 "{plugin_root}/scripts/trade_sql.py" trend --source korea --partner cn --flow exports \ + --hs 854232 --start 2020-01 --end 2025-12 + +Here {plugin_root} is the absolute directory containing the plugin manifests. +Label the HS codes a products query returns with its bundled hs_codes.py. +""" + +from __future__ import annotations + +import argparse +import json +import os +import re +import sys + +DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data") + +SOURCES = { + "census": { + "schema": "census", + "prefix": "us_census_hs", + "reporter": "United States", + "levels": (6, 10), + "value_unit": "US$", + "qty_suffixes": ("qty",), + "qty_levels": (10,), + "world_partner": "-", + "dataset_filter": "us_census_hs", + }, + "china": { + "schema": "china_customs", + "prefix": "china_customs", + "reporter": "China", + "levels": (6, 8), + "value_unit": "US$", + "qty_suffixes": ("qty",), + "qty_levels": (6, 8), + "world_partner": None, + "dataset_filter": "china_customs", + }, + "india": { + "schema": "india_trade", + "prefix": "india_trade", + "reporter": "India", + "levels": (6, 8), + "value_unit": "US$ Million", + "qty_suffixes": (), + "qty_levels": (), + "world_partner": None, + "dataset_filter": None, + }, + "korea": { + "schema": "korea_trade", + "prefix": "korea_trade", + "reporter": "South Korea", + "levels": (6, 10), + "value_unit": "US$ Thousand", + "qty_suffixes": ("qty",), + "qty_levels": (6, 10), + "world_partner": None, + "dataset_filter": None, + }, + "japan": { + "schema": "japan_trade", + "prefix": "japan_trade", + "reporter": "Japan", + "levels": (9,), + "value_unit": "¥ Thousand", + "qty_suffixes": ("qty", "qty2"), + "qty_levels": (9,), + "world_partner": None, + "dataset_filter": None, + }, + "taiwan": { + "schema": "taiwan_trade", + "prefix": "taiwan_trade", + "reporter": "Taiwan", + "levels": (6, 11), + "value_unit": "US$", + "qty_suffixes": (), + "qty_levels": (), + "world_partner": None, + "dataset_filter": None, + }, +} + +PARTNER_MAP_KEY = { # source -> key in trade_partners.json + "census": "us_census_hs", + "china": "china_customs", + "india": "india_trade", + "korea": "korea_trade", + "japan": "japan_trade", + "taiwan": "taiwan_trade", +} + + +def fail(message: str, code: int = 1) -> None: + print(json.dumps({"error": message}), file=sys.stderr) + sys.exit(code) + + +def parse_month(text: str, name: str) -> tuple[int, int]: + match = re.fullmatch(r"([0-9]{4})-(0[1-9]|1[0-2])", text) + if match is None: + fail(f"--{name} must be YYYY-MM, got '{text}'") + year, month = map(int, match.groups()) + if year == 0: + fail(f"--{name} year must be between 0001 and 9999, got '{text}'") + return year, month + + +def date_bounds(start: str, end: str) -> tuple[str, str]: + sy, sm = parse_month(start, "start") + ey, em = parse_month(end, "end") + if (sy, sm) > (ey, em): + fail(f"--start {start} is after --end {end}") + if (ey, em) == (9999, 12): + fail("--end 9999-12 cannot be represented as an exclusive upper date bound") + ny, nm = (ey + 1, 1) if em == 12 else (ey, em + 1) + return f"{sy:04d}-{sm:02d}-01", f"{ny:04d}-{nm:02d}-01" + + +def load_partners(source: str) -> tuple[dict[str, str], dict[str, str]]: + """Return (code -> name, alias -> code) for this source.""" + path = os.path.join(DATA_DIR, "trade_partners.json") + try: + with open(path, encoding="utf-8") as f: + data = json.load(f) + key = PARTNER_MAP_KEY[source] + partners = data["partners"][key] + aliases = data["aliases"][key] + if not isinstance(partners, dict) or not isinstance(aliases, dict): + fail(f"bundled partner map at {path} has an invalid shape") + if any( + not isinstance(code, str) or not isinstance(name, str) + for mapping in (partners, aliases) + for code, name in mapping.items() + ): + fail(f"bundled partner map at {path} has an invalid shape") + missing_alias_codes = sorted(set(aliases.values()) - set(partners)) + if missing_alias_codes: + fail( + f"bundled partner map at {path} has aliases for unknown code(s) " + f"{missing_alias_codes}" + ) + return partners, aliases + except (OSError, UnicodeError, json.JSONDecodeError, KeyError, TypeError) as exc: + fail(f"cannot read bundled partner map at {path}: {exc}") + raise AssertionError # unreachable + + +def normalize_partner_name(text: str) -> str: + """Fold punctuation and accidental spacing for partner-name matching.""" + return "".join(char for char in text.casefold() if char.isalnum()) + + +EU_AGGREGATE_QUERIES = { + "eu", + "eu27", + "euro", + "europeanunion", + "europeanunion27", +} + + +def same_name_codes(partners: dict[str, str], name: str) -> list[str]: + """Return every code whose display name denotes the same partner.""" + normalized_name = normalize_partner_name(name) + return [ + code + for code, candidate in partners.items() + if normalize_partner_name(candidate) == normalized_name + ] + + +def grouped_name_hits( + hits: list[tuple[str, str]], +) -> list[list[tuple[str, str]]]: + """Group code hits that are historical versions of the same partner.""" + grouped: dict[str, list[tuple[str, str]]] = {} + for code, name in hits: + grouped.setdefault(normalize_partner_name(name), []).append((code, name)) + return list(grouped.values()) + + +def resolve_partner(source: str, text: str) -> tuple[list[str], str]: + """Resolve a partner code or name to (codes, display name). + + A few China partner codes changed in January 2023. The bundled map keeps + both codes under the same name, so name-based queries must include both to + work across the boundary. Passing an exact code still selects only that + code. + """ + cfg = SOURCES[source] + query = text.strip() + if not query: + fail("--partner cannot be empty") + if query.lower() in ("world", "all"): + if cfg["world_partner"] is None: + hint = ( + " (for China's headline totals use the separate china_customs_prelim " + "series, e.g. china_customs_prelim_total_export_cny — note they are " + "CNY, not US$)" + if source == "china" + else "" + ) + fail( + f"source '{source}' stores no all-partner total rows — query a " + f"specific partner, or sum per-partner results yourself{hint}" + ) + query = cfg["world_partner"] + partners, aliases = load_partners(source) + # 1. exact code (case-insensitive). Keep this ahead of aliases so an + # explicit historical code always selects only that code. + for code, name in partners.items(): + if code.lower() == query.lower(): + return [code], name + normalized_query = normalize_partner_name(query) + if not normalized_query: + fail("--partner must contain at least one letter or number") + # Do not let an EU/EU-27 request fall through to fuzzy matching. Some + # national customs maps contain names such as "Other European Territories" + # but do not publish a European Union aggregate, so a fragment like + # "euro" could otherwise produce valid-looking SQL for the wrong geography. + if normalized_query in EU_AGGREGATE_QUERIES: + eu_codes = same_name_codes(partners, "European Union") + if not eu_codes: + fail( + f"source '{source}' has no European Union aggregate partner — " + "query EU member countries separately, or use comext_sql.py " + "for EU-reported trade" + ) + return eu_codes, partners[eu_codes[0]] + # 2. curated alias ("united states", "south korea", "uae", ...). + # Normalize aliases too, so "U.S." and repeated spaces work as expected. + alias_matches = { + code + for alias, code in aliases.items() + if normalize_partner_name(alias) == normalized_query + } + if len(alias_matches) > 1: + fail(f"bundled aliases for '{query}' resolve to multiple partner codes") + if alias_matches: + alias_code = next(iter(alias_matches)) + alias_name = partners[alias_code] + return same_name_codes(partners, alias_name), alias_name + # 3. exact normalized name. Multiple codes with the same name are + # historical versions of one partner and must all be queried. + exact = [ + (code, name) + for code, name in partners.items() + if normalize_partner_name(name) == normalized_query + ] + if exact: + return [code for code, _ in exact], exact[0][1] + # 4. unique normalized-name substring. Count names rather than codes: + # two historical codes for Georgia are one partner match, not ambiguity. + hits = [ + (code, name) + for code, name in partners.items() + if normalized_query in normalize_partner_name(name) + ] + if not hits: + fail(f"no partner in '{source}' matches '{text}' — try a shorter name fragment") + grouped_hits = grouped_name_hits(hits) + if len(grouped_hits) == 1: + return [code for code, _ in grouped_hits[0]], grouped_hits[0][0][1] + listing = "; ".join( + f"{','.join(code for code, _ in group)}={group[0][1]}" + for group in grouped_hits[:10] + ) + fail( + f"'{text}' is ambiguous in '{source}' ({len(grouped_hits)} matches): {listing}", + code=2, + ) + raise AssertionError # unreachable + + +def resolve_level(source: str, level: int | None) -> int: + cfg = SOURCES[source] + if level is None: + return cfg["levels"][0] + if level not in cfg["levels"]: + fail(f"source '{source}' stores HS levels {cfg['levels']}, not {level}") + return level + + +def flow_code(flow: str) -> str: + return {"imports": "M", "exports": "X"}[flow] + + +def limited_positive_int(text: str) -> int: + try: + value = int(text) + except ValueError: + raise argparse.ArgumentTypeError("must be an integer from 1 to 50") from None + if not 1 <= value <= 50: + raise argparse.ArgumentTypeError("must be from 1 to 50") + return value + + +def value_filter(source: str) -> str: + """WHERE fragment that keeps value series only (drops _qty/_qty2).""" + return f"s.measurement_units = '{SOURCES[source]['value_unit']}'" + + +def sql_string(text: str) -> str: + return "'" + text.replace("'", "''") + "'" + + +def add_partner_code_note(note: str, partner_codes: list[str]) -> str: + if len(partner_codes) == 1: + return note + codes = ", ".join(partner_codes) + return f"{note}; combined historical partner codes {codes}" + + +def dim_join(alias: str, dim_type: str, codes: str | list[str]) -> str: + code_list = [codes] if isinstance(codes, str) else codes + if len(code_list) == 1: + code_condition = f"{alias}.dimension_code = {sql_string(code_list[0])}" + else: + code_condition = ( + f"{alias}.dimension_code IN (" + + ", ".join(sql_string(code) for code in code_list) + + ")" + ) + return ( + f"JOIN dimensions {alias} ON {alias}.series_id = s.series_id\n" + f" AND {alias}.dimension_type = {sql_string(dim_type)} AND {code_condition}" + ) + + +def base_joins( + source: str, flow: str, level: int, partner_codes: list[str] +) -> tuple[str, list[str]]: + cfg = SOURCES[source] + parts = [ + "FROM series s", + dim_join("f", "flow", flow_code(flow)), + dim_join("l", "hs_level", str(level)), + dim_join("pa", "partner", partner_codes), + "JOIN data_points dp ON dp.series_id = s.series_id", + ] + where = [value_filter(source)] + if cfg["dataset_filter"]: + where.append(f"s.dataset_code = '{cfg['dataset_filter']}'") + return "\n".join(parts), where + + +def header( + source: str, + args: argparse.Namespace, + partner_name: str, + level: int, + extra: str = "", +) -> str: + cfg = SOURCES[source] + lines = [ + f"-- generated by trade_sql.py {args.command}: {cfg['reporter']} {args.flow} " + f"vs {partner_name}, {args.start}..{args.end}, HS-{level} level", + f'-- run with the run_sql tool, schema="{cfg["schema"]}"', + ] + if getattr(args, "metric", "value") == "quantity": + lines.append( + "-- quantities use product-specific units; measurement_units is returned " + "with each series" + ) + else: + lines.append( + f"-- values in {cfg['value_unit']} ({cfg['reporter']} customs' own view)" + ) + if extra: + lines.append(f"-- {extra}") + return "\n".join(lines) + + +def sql_total(args: argparse.Namespace) -> str: + source = args.source + partner_codes, partner_name = resolve_partner(source, args.partner) + level = resolve_level(source, args.level) + lo, hi = date_bounds(args.start, args.end) + + joins, where = base_joins(source, args.flow, level, partner_codes) + where.append(f"dp.time >= DATE '{lo}' AND dp.time < DATE '{hi}'") + if args.monthly: + select, group = ( + "dp.time::date AS month, SUM(dp.value) AS value", + "\nGROUP BY 1\nORDER BY 1", + ) + else: + select, group = "SUM(dp.value) AS value", "" + conditions = "\n AND ".join(where) + body = f"SELECT {select}\n{joins}\nWHERE {conditions}{group};" + note = add_partner_code_note( + f"all-goods total = sum over every HS-{level} line for this partner", + partner_codes, + ) + return header(source, args, partner_name, level, note) + "\n" + body + + +def sql_products(args: argparse.Namespace) -> str: + source = args.source + partner_codes, partner_name = resolve_partner(source, args.partner) + level = resolve_level(source, args.level) + group_digits = int(args.group_by) + if group_digits > level: + fail( + f"--group-by {group_digits} is finer than the HS-{level} lines being queried" + ) + lo, hi = date_bounds(args.start, args.end) + + joins, where = base_joins(source, args.flow, level, partner_codes) + joins += "\n" + ( + "JOIN dimensions c ON c.series_id = s.series_id\n" + " AND c.dimension_type = 'commodity'" + ) + where.append(f"dp.time >= DATE '{lo}' AND dp.time < DATE '{hi}'") + conditions = "\n AND ".join(where) + body = ( + f"SELECT LEFT(c.dimension_code, {group_digits}) AS code, SUM(dp.value) AS value\n" + f"{joins}\n" + f"WHERE {conditions}\n" + f"GROUP BY 1\nORDER BY 2 DESC\nLIMIT {args.top};" + ) + label_hint = ( + "name the codes locally with the bundled hs_codes.py helper" + if group_digits in (2, 4, 6) + else "national-line names live in dimensions.dimension_name (dimension_type='commodity')" + ) + note = add_partner_code_note( + f"top products by first {group_digits} HS digits; {label_hint}", + partner_codes, + ) + return header(source, args, partner_name, level, note) + "\n" + body + + +def sql_trend(args: argparse.Namespace) -> str: + source = args.source + cfg = SOURCES[source] + partner_codes, partner_name = resolve_partner(source, args.partner) + code = args.hs.strip() + if re.fullmatch(r"[0-9]+", code, flags=re.ASCII) is None: + fail(f"--hs must be an HS code, got '{args.hs}'") + lo, hi = date_bounds(args.start, args.end) + + if ( + len(code) in cfg["levels"] + and args.metric == "value" + and args.level in (None, len(code)) + ): + # Full-length code at a stored level: the series ID is constructible. + level = len(code) + series_ids = [ + f"{cfg['prefix']}_{flow_code(args.flow)}_{level}d_{code}_{partner_code}" + for partner_code in partner_codes + ] + if len(series_ids) == 1: + body = ( + f"SELECT time::date AS month, value\n" + f"FROM data_points\n" + f"WHERE series_id = {sql_string(series_ids[0])}\n" + f" AND time >= DATE '{lo}' AND time < DATE '{hi}'\n" + f"ORDER BY time;" + ) + note = f"exact series: {series_ids[0]}" + else: + id_list = ",\n ".join(sql_string(series_id) for series_id in series_ids) + body = ( + f"SELECT time::date AS month, SUM(value) AS value\n" + f"FROM data_points\n" + f"WHERE series_id IN (\n {id_list})\n" + f" AND time >= DATE '{lo}' AND time < DATE '{hi}'\n" + f"GROUP BY 1\n" + f"ORDER BY 1;" + ) + note = ( + f"{len(series_ids)} historical partner-code series combined: " + + ", ".join(series_ids) + ) + return header(source, args, partner_name, level, note) + "\n" + body + + if args.metric != "value": + if not cfg["qty_suffixes"]: + fail(f"source '{source}' stores value series only — no quantity/weight") + level = len(code) + if level not in cfg["qty_levels"]: + fail( + f"source '{source}' stores quantity only at HS level(s) " + f"{cfg['qty_levels']} — pass a full-length code at one of those levels" + ) + if args.level not in (None, level): + fail( + "quantity queries require one exact stored HS code; --level must " + "match the code length or be omitted" + ) + ids = [ + f"{cfg['prefix']}_{flow_code(args.flow)}_{level}d_{code}_{partner_code}_{sfx}" + for partner_code in partner_codes + for sfx in cfg["qty_suffixes"] + ] + id_list = ",\n ".join(sql_string(series_id) for series_id in ids) + body = ( + f"SELECT s.series_id, s.measurement_units, dp.time::date AS month, dp.value\n" + f"FROM series s JOIN data_points dp ON dp.series_id = s.series_id\n" + f"WHERE s.series_id IN (\n {id_list})\n" + f" AND dp.time >= DATE '{lo}' AND dp.time < DATE '{hi}'\n" + f"ORDER BY s.series_id, dp.time;" + ) + note = add_partner_code_note( + "quantity units are product-specific — read measurement_units off " + "each row and NEVER sum quantities across products", + partner_codes, + ) + return header(source, args, partner_name, level, note) + "\n" + body + + # Short (group) code over stored lines: aggregate via the commodity dimension. + level = resolve_level(source, args.level) + if len(code) not in (2, 4, 6): + fail( + f"--hs '{code}' is not a stored level for '{source}' and is not a " + "2/4/6-digit HS group" + ) + if len(code) >= level: + fail( + f"--hs '{code}' is not a stored level for '{source}' (levels {cfg['levels']}) " + "and not shorter than the aggregation level — pass a full-length code, " + f"or a 2/4/6-digit group with --level {level}" + ) + joins, where = base_joins(source, args.flow, level, partner_codes) + joins += "\n" + ( + "JOIN dimensions c ON c.series_id = s.series_id\n" + f" AND c.dimension_type = 'commodity' AND c.dimension_code LIKE '{code}%'" + ) + where.append(f"dp.time >= DATE '{lo}' AND dp.time < DATE '{hi}'") + conditions = "\n AND ".join(where) + body = ( + f"SELECT dp.time::date AS month, SUM(dp.value) AS value\n" + f"{joins}\n" + f"WHERE {conditions}\n" + f"GROUP BY 1\nORDER BY 1;" + ) + note = add_partner_code_note( + f"HS group {code}* summed over HS-{level} lines", partner_codes + ) + return header(source, args, partner_name, level, note) + "\n" + body + + +def main() -> None: + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + sub = parser.add_subparsers(dest="command", required=True) + + def add_common(p: argparse.ArgumentParser) -> None: + p.add_argument("--source", required=True, choices=sorted(SOURCES)) + p.add_argument( + "--partner", + required=True, + help="partner code or name fragment (resolved against the bundled per-source map); " + "'world' = the all-partner total row (census only)", + ) + p.add_argument("--flow", required=True, choices=["imports", "exports"]) + p.add_argument( + "--start", required=True, help="first month, YYYY-MM (inclusive)" + ) + p.add_argument("--end", required=True, help="last month, YYYY-MM (inclusive)") + p.add_argument( + "--level", + type=int, + help="HS digit level (default: the source's international level)", + ) + + p_total = sub.add_parser("total", help="all-goods total for one partner") + add_common(p_total) + p_total.add_argument("--monthly", action="store_true", help="one row per month") + + p_products = sub.add_parser("products", help="top products for one partner") + add_common(p_products) + p_products.add_argument( + "--group-by", + default="2", + choices=["2", "4", "6"], + help="HS digits to group by (default 2)", + ) + p_products.add_argument( + "--top", + type=limited_positive_int, + default=25, + help="rows to return, 1-50 (default 25)", + ) + + p_trend = sub.add_parser("trend", help="monthly trend for one HS code or group") + add_common(p_trend) + p_trend.add_argument( + "--hs", + required=True, + help="HS code: full-length = exact series, 2/4/6-digit = summed group", + ) + p_trend.add_argument( + "--metric", + default="value", + choices=["value", "quantity"], + help="default: value", + ) + + args = parser.parse_args() + print( + {"total": sql_total, "products": sql_products, "trend": sql_trend}[ + args.command + ](args) + ) + + +if __name__ == "__main__": + main()
Full technical diff · 104 changed fields
removed /files/.app.json
{
"sha256": "34235df105b1fcd3e30dacd9793ed81848078adc18bed0df6fd01837e0473b42",
"size": 127
}Field is absent
added /files/.claude-plugin~1marketplace.json
Field was absent
{
"sha256": "49fb6b53e79d5715aa9a9a093a0bf8d7f3dbd8b9a9328bb9ae21b336aa88cf49",
"size": 610
}added /files/.claude-plugin~1plugin.json
Field was absent
{
"sha256": "dec61fe1e1790fd335e220e1c54c16120e2e7632e16e044fe32f010d58d9c36e",
"size": 927
}changed /files/.codex-plugin~1plugin.json/sha256
"40992ee953af3848c3a0f65115d97dea99dcb6e0cd84aad7ae5539b6173ef4b3"
"add8506ef8caab254eb8e3518555c6a398af5aea31b7e1089d38ff02d4ea2cf9"
changed /files/.codex-plugin~1plugin.json/size
1496
2536
added /files/.gitignore
Field was absent
{
"sha256": "566702bcfdb6180828438f56a6f35b82c75d7221aa69a8c6aa7621adf8df5f00",
"size": 126
}added /files/.mcp.json
Field was absent
{
"sha256": "bd6807e5f73d473c49f99a29cd0eb178ba1e25349cd3db388d4f980963acaec9",
"size": 112
}added /files/LICENSE
Field was absent
{
"sha256": "ffe02ec2d2f9b23b61b38602bfd44d0fa777600a1cb1e8765da0626d09bd7114",
"size": 1068
}added /files/README.md
Field was absent
{
"sha256": "ff859c70ed0a7e6e53f2f077afd79125a1f6ac0d5e93e6764a17f49096f704ab",
"size": 16746
}added /files/SETUP.md
Field was absent
{
"sha256": "4a6e0b5db6c5948e362c9442ee2d9c35dd9980bafd6c01a056a7d123be5a286e",
"size": 2958
}added /files/assets~1factiq-logo.png
Field was absent
{
"sha256": "3b7bc0447b0612514780bc363f5a205710ef66de15daed4524ac4624998161e3",
"size": 17317
}added /files/evals~1README.md
Field was absent
{
"sha256": "976b22bcc20d210ac3187e45154be00bfbeb68ffc17412de2d8eea9417f6a163",
"size": 8941
}added /files/evals~1bilateral-trade-sql~1graders~1one-hs-level-only.md
Field was absent
{
"sha256": "1858daf1ab5d4774154d77458e7aa079da270af35e3476e904752180e6b82726",
"size": 471
}added /files/evals~1bilateral-trade-sql~1graders~1partner-code-is-numeric.md
Field was absent
{
"sha256": "ebfb683108dca135318753256062de5ababbd417c3fa3eaa3a1b9c712cd92f17",
"size": 523
}added /files/evals~1bilateral-trade-sql~1graders~1used-the-bundled-generator.md
Field was absent
{
"sha256": "8d5dfaa90973849c823636a1cf001b537fe4346f3f31e4467179557b45d90536",
"size": 121
}added /files/evals~1bilateral-trade-sql~1graders~1value-series-only.md
Field was absent
{
"sha256": "83258957a67431b6ddaaa98e01cd4694533f814ba4ecf97b14b0ae981eef9bec",
"size": 466
}added /files/evals~1bilateral-trade-sql~1prompt.md
Field was absent
{
"sha256": "6e0aeeaef20feb8ad194bfac0fb77fd63816c42fc8b1fc24914a1072e88e6b29",
"size": 842
}added /files/evals~1filings-duplicate-line~1graders~1figure-is-not-doubled.md
Field was absent
{
"sha256": "7f7444985429c85502638acdd809f0bc96b3b7a676d6f9b6ac246bfd88505ddf",
"size": 123
}added /files/evals~1filings-duplicate-line~1graders~1figure-is-the-first-line.md
Field was absent
{
"sha256": "325edda2814c36316d071e690539068175a5d9334eaf9bd555e84c5a38d2667d",
"size": 808
}added /files/evals~1filings-duplicate-line~1graders~1no-invented-filing-links.md
Field was absent
{
"sha256": "46043047d26759ce2ed60643464fd5a377f2d75a46937b1f17ee5f53f420f15b",
"size": 550
}added /files/evals~1filings-duplicate-line~1graders~1source-link-is-the-filing.md
Field was absent
{
"sha256": "30cf2586d074446b24b07333cf4860bc267b42d3efd36ed9f319f9aafcb11c41",
"size": 163
}added /files/evals~1filings-duplicate-line~1prompt.md
Field was absent
{
"sha256": "4cd0b9906584614ca73ddec45d3681a3573bbc68ce076274ae89826e228ac055",
"size": 813
}added /files/evals~1latest-value-direct-answer~1graders~1answers-in-prose.md
Field was absent
{
"sha256": "04588e346003462f88adf6a2fe6b85b5dd62f8c17ded2212b2bc9d068e5929a7",
"size": 669
}added /files/evals~1latest-value-direct-answer~1graders~1no-chart-file-written.md
Field was absent
{
"sha256": "a06cd9171ce44db1511d189c1467b55dd76e0ddd3025bf9c63ffd6df1eaada46",
"size": 60
}added /files/evals~1latest-value-direct-answer~1prompt.md
Field was absent
{
"sha256": "3a957c231947743012ecb886cd3c5fffa6e528444826b487df1b180f59d2d40e",
"size": 577
}added /files/evals~1mocks~1factiq~1_tools.json
Field was absent
{
"sha256": "b867d3bc2218c923d117350a8d19391578e31aaba251d806b766f711c4083373",
"size": 58563
}added /files/evals~1mocks~1factiq~1describe_dataset.md
Field was absent
{
"sha256": "aef6ae3bad4de381194fd3533f5ac2bf291f5c94cbe2a4c840eb09ad6fa91558",
"size": 2132
}added /files/evals~1mocks~1factiq~1fixtures~1LNS14000000.json
Field was absent
{
"sha256": "3432a266cfbd4d7c32b11cec8d8f7305db7e97b4f7a91930c166b13719071b93",
"size": 8750
}added /files/evals~1mocks~1factiq~1fixtures~1PKG.json
Field was absent
{
"sha256": "236b9ba9dd79f5e160faaa32e6c5991a909c4162011ec539f11fba0ee682215f",
"size": 15247
}added /files/evals~1mocks~1factiq~1get_data_catalog.md
Field was absent
{
"sha256": "840dc24cf2f2eb91611464c95d3414152c404df96600fae160fd0d1c07a777bb",
"size": 6858
}added /files/evals~1mocks~1factiq~1get_series.md
Field was absent
{
"sha256": "8be660b04874d51a9f4476049e8623e07eca076fb71dce5dcf7fccb9817c9d5b",
"size": 41
}added /files/evals~1mocks~1factiq~1get_style_guides.md
Field was absent
{
"sha256": "6363e4370e733e924f18a2c71a611509a1926a781e68ead99646b76659256f5a",
"size": 880
}added /files/evals~1mocks~1factiq~1run_sql.md
Field was absent
{
"sha256": "77b6cee5f1133990bc93147fe8e2956f9b8b0b4a5fc14783dbcc9971d91130d5",
"size": 2181
}added /files/evals~1mocks~1factiq~1search_company_filings.md
Field was absent
{
"sha256": "d7fa2f3b3a67aef362b459b0eba2362f2f3d12c242dded32a3f1402f95f3f268",
"size": 39
}added /files/evals~1mocks~1factiq~1search_datasets.md
Field was absent
{
"sha256": "98f364b4a4189012c607031b595c3e1bd7cb8e3ba95e10f59dd7aaf78883418f",
"size": 1034
}added /files/evals~1mocks~1factiq~1search_earnings_transcripts.md
Field was absent
{
"sha256": "6f0187121c6c4e5f998be00612e9d5bff30c6d5b6ad36ffccd447e21ba1650d5",
"size": 6189
}added /files/evals~1mocks~1factiq~1search_series.md
Field was absent
{
"sha256": "4a78565f723fcf708bcdc08f7df142f3568ad1652db43b87796d091716e9c41b",
"size": 1302
}added /files/evals~1quick-chart-of-a-trend~1graders~1answer-states-gap-and-source.md
Field was absent
{
"sha256": "b2dd20ccd3a717585bdfe2b5bfe101042ca3933734ab6cb273d5ac4bff90561f",
"size": 492
}added /files/evals~1quick-chart-of-a-trend~1graders~1chart-file-written.md
Field was absent
{
"sha256": "53a654575c25d75251de7e79e8d40d1837b12f186d31060f3a2a7819dfcaefcc",
"size": 53
}added /files/evals~1quick-chart-of-a-trend~1graders~1missing-month-is-not-filled-in.md
Field was absent
{
"sha256": "4012378ca9d63de3ebee5f3fdb39b78ff5095bd861f97716323d8564a3c8d1b2",
"size": 528
}added /files/evals~1quick-chart-of-a-trend~1graders~1spec-is-a-valid-chartspec.md
Field was absent
{
"sha256": "72ea853a887ba0bd91a97f49ae52cdbd66cb295eb4888c1bcb47719892bad82c",
"size": 946
}added /files/evals~1quick-chart-of-a-trend~1graders~1title-makes-a-claim.md
Field was absent
{
"sha256": "2d9c5e1e0ff470e04d170bd88140d874324a7db4086feb53adf19216d371a4d0",
"size": 656
}added /files/evals~1quick-chart-of-a-trend~1prompt.md
Field was absent
{
"sha256": "956fc00fd943f70ae85de3bd22b6b60147846dd67a3297ecbec36d64eff723d2",
"size": 690
}added /files/evals~1quote-and-source-discipline~1graders~1analyst-framing-is-not-management.md
Field was absent
{
"sha256": "db4672fe197c1bbc858969604d0fbdfece844c4a95bb4cbffb2a94da904b0553",
"size": 608
}added /files/evals~1quote-and-source-discipline~1graders~1link-fy2025q2-is-the-supplied-one.md
Field was absent
{
"sha256": "e5723ee4f90d36c669c66dfa247d5674dd4e71f6bb8b5290f4d1c7d65a4b89e4",
"size": 216
}added /files/evals~1quote-and-source-discipline~1graders~1link-fy2026q4-is-the-supplied-one.md
Field was absent
{
"sha256": "f0615b5f82e65e997603fd0dce33d331e0dc5aa86738521ea7e0720d9ffa484c",
"size": 215
}added /files/evals~1quote-and-source-discipline~1graders~1link-fy2027q1-is-the-supplied-one.md
Field was absent
{
"sha256": "da50e2f5694fdaf824130515c6cad1edd6581cc0068054c6eead1f03546fed87",
"size": 215
}added /files/evals~1quote-and-source-discipline~1graders~1missing-link-is-declared.md
Field was absent
{
"sha256": "3286a7f25db8fc1c059b14977cc35cd72cbb6bba67720b7b58137a47ad201177",
"size": 486
}added /files/evals~1quote-and-source-discipline~1graders~1no-invented-source-links.md
Field was absent
{
"sha256": "3418802ca26fd0b78017ccdab87a0a243cce30966c5e3482a87d1708a6e98ee0",
"size": 167
}added /files/evals~1quote-and-source-discipline~1graders~1quotes-are-verbatim.md
Field was absent
{
"sha256": "af6f44f2a953d8de18d8592486114447a94e8f621f0ea0a2e52d6d284d74ed14",
"size": 2001
}added /files/evals~1quote-and-source-discipline~1prompt.md
Field was absent
{
"sha256": "1287da04c18787fa65b4cb016cef62fe7d208b360f0d7d7f6750ffb68db35f78",
"size": 781
}added /files/evals~1run_ablation.py
Field was absent
{
"sha256": "550702da90fbe53889c67ef30f6cb7254e31fa1009719ec869f313b3aed9f1d3",
"size": 9041
}added /files/evals~1unrelated-coding-request~1graders~1answers-the-python-question.md
Field was absent
{
"sha256": "4db03d4fcb5e4bb6a04162e0dad4b5db3fef97d145103d64bfb041b50946f12a",
"size": 407
}added /files/evals~1unrelated-coding-request~1graders~1no-catalog-lookup.md
Field was absent
{
"sha256": "60bfc77bae34c51bdb2a2b7a3b8c72719e5bd55d81a281a71e9026595d426260",
"size": 98
}added /files/evals~1unrelated-coding-request~1graders~1no-factiq-skill-invoked.md
Field was absent
{
"sha256": "22813294a356e15059d59459cbe5da9ec0a4a18c760d9521ddc35ae886dcd7c5",
"size": 80
}added /files/evals~1unrelated-coding-request~1graders~1no-series-fetch.md
Field was absent
{
"sha256": "ede84d92b6c6e73e1e42d8968ddd3c8c0c8f9d7560bd169131987ca1db3e23f9",
"size": 92
}added /files/evals~1unrelated-coding-request~1graders~1no-sql-call.md
Field was absent
{
"sha256": "3e5d7fdb2a6fb1566d4ba420eb12550281f72f0deec9cb9e613378ceb76cd7ae",
"size": 89
}added /files/evals~1unrelated-coding-request~1prompt.md
Field was absent
{
"sha256": "40eb7a0228cca78e53786e361c687eb96238814f69911fc9d998f501b6575250",
"size": 492
}added /files/evals~1yoy-across-a-missing-month~1graders~1missing-month-is-stated.md
Field was absent
{
"sha256": "560524f7356fb5ceedf5314bfb511ae0b70c63c6b92bace819c52cc0cce26ee3",
"size": 376
}added /files/evals~1yoy-across-a-missing-month~1graders~1yoy-values-are-date-matched.md
Field was absent
{
"sha256": "3d6dfbc6957296d246e5e767d23ce83e134b92aa179d824cb6988100f3ba80cd",
"size": 860
}added /files/evals~1yoy-across-a-missing-month~1prompt.md
Field was absent
{
"sha256": "fcdbe2f5cc33e6a2d0e27d88143ea5d5fd57c59cd1ccbb889c58b9cbbe7aa380",
"size": 678
}added /files/evals~1yoy-without-a-server-hint~1graders~1missing-month-is-stated.md
Field was absent
{
"sha256": "560524f7356fb5ceedf5314bfb511ae0b70c63c6b92bace819c52cc0cce26ee3",
"size": 376
}added /files/evals~1yoy-without-a-server-hint~1graders~1yoy-values-are-date-matched.md
Field was absent
{
"sha256": "3d6dfbc6957296d246e5e767d23ce83e134b92aa179d824cb6988100f3ba80cd",
"size": 860
}added /files/evals~1yoy-without-a-server-hint~1mocks~1factiq~1fixtures~1LNS14000000.json
Field was absent
{
"sha256": "9827dc5a5e9f5390e7ebf352502d29ad95a7a0654355622ab0a53aad40c6bd6a",
"size": 7971
}added /files/evals~1yoy-without-a-server-hint~1mocks~1factiq~1get_series.md
Field was absent
{
"sha256": "8be660b04874d51a9f4476049e8623e07eca076fb71dce5dcf7fccb9817c9d5b",
"size": 41
}added /files/evals~1yoy-without-a-server-hint~1mocks~1factiq~1run_sql.md
Field was absent
{
"sha256": "8236cf759b4a8f1f91c7725c7f54d69679490766f110aa29bd846c6a7537e98a",
"size": 2146
}added /files/evals~1yoy-without-a-server-hint~1prompt.md
Field was absent
{
"sha256": "678326246a74ba8f44c43dad47b172248ff9e030df00146f766acd52ec88467b",
"size": 786
}added /files/references~1data~1satellite.md
Field was absent
{
"sha256": "2d310c84485c86f91b8a864dc69147988c07f5d9a06a96e0c42961014406b882",
"size": 13687
}added /files/references~1data~1schemas.md
Field was absent
{
"sha256": "51fd1bd6e71b5a48dd8b15cc923e16d608c2d2638edfda5c0fff1a1d56ca47b8",
"size": 22132
}added /files/references~1data~1sql-guide.md
Field was absent
{
"sha256": "4924bd8ae696ef3ee8aaa5c5dbb4ba53356cefa82653d65b3040df407e800027",
"size": 21312
}added /files/references~1output~1chart-spec.md
Field was absent
{
"sha256": "2fb1b622fa6b037e8860c3bfba20bfd97b744192f34d36df16fec82b6f4c30dc",
"size": 8704
}added /files/references~1output~1report-spec.md
Field was absent
{
"sha256": "5e16ae46b0fc2083a35dc262e4483d87e88cc9c6fb8f1412eebd7b2b0570250c",
"size": 14050
}added /files/references~1report-patterns~1README.md
Field was absent
{
"sha256": "674c9df1c81c8cb5d4beb07243ba837217da86912e5e2a59c63641a9531166b9",
"size": 11027
}added /files/references~1report-patterns~1bilateral-economic-policy.md
Field was absent
{
"sha256": "48c89a71f875aa92d7a7ddd11e3c134b108788585f48a8f13af65b2e323e4305",
"size": 9123
}added /files/references~1report-patterns~1bilateral-trade.md
Field was absent
{
"sha256": "98cc223764dd709ffb64ddcb13d3e549669e28331736140e769bae7319d76dac",
"size": 19502
}added /files/references~1report-patterns~1business-formation-statistics.md
Field was absent
{
"sha256": "324ea681d9b3ad7eceb9cc5371608ac01fd86743b3c3581236398053184cbcda",
"size": 5440
}added /files/references~1report-patterns~1earnings-intelligence.md
Field was absent
{
"sha256": "9e491f60843c1fa4d9b0e4f5ddd831974ce2f3eddbc202ad77f64549f33c0634",
"size": 17082
}added /files/references~1report-patterns~1fiscal-policy-revenue.md
Field was absent
{
"sha256": "7525d09c34a0b990e0eb5cf73bcf1e7077bd373e0be8be238706cde1b0cbc670",
"size": 7628
}added /files/references~1report-patterns~1interview-step.md
Field was absent
{
"sha256": "b5edb929dfcc6257c1b25fc407ae29878383c0dca9cf974041e437f0b70e0682",
"size": 3806
}added /files/references~1report-patterns~1media-intelligence.md
Field was absent
{
"sha256": "a9f31dc9760757af5c6462333ca176bfa724980814f3fc55e77ba107b50f0f22",
"size": 17242
}added /files/references~1report-patterns~1monetary-policy.md
Field was absent
{
"sha256": "6439f63e7c77ab5d5d424a09bc112edea12f37630615c96315e80490939ffa38",
"size": 11190
}added /files/scripts~1__pycache__~1term_chart.cpython-312.pyc
Field was absent
{
"sha256": "9b87da15116997e594cba9e058b9ff8e015cd91be7322c1c84d1d0bf6599d14b",
"size": 32120
}added /files/scripts~1comext_sql.py
Field was absent
{
"sha256": "8a8bcc07156d5f1527540dae466ca6ee6ae0c6a743dadeb3d1c8cf94fb87d187",
"size": 19633
}added /files/scripts~1data~1hs_names.json.gz
Field was absent
{
"sha256": "3f5def41a331d3ad3a4ebb70c49e442e6e19e898673c577c04fa8be1ea9e017b",
"size": 155694
}added /files/scripts~1data~1trade_partners.json
Field was absent
{
"sha256": "7445d1193623a87480dbe68107a007bcd23c73aa330cec3c30e04ba3b662bc67",
"size": 38397
}added /files/scripts~1hs_codes.py
Field was absent
{
"sha256": "38230174536c64a18adfb130b486d81a9dc7e6c69ca866f08a1fd6ecca071f98",
"size": 7191
}added /files/scripts~1series_math.py
Field was absent
{
"sha256": "5ee047d8b9d00c934b3e1bd1f25c1a25e6a545c09371f8f5a93ad46adce6cdf1",
"size": 22168
}added /files/scripts~1trade_sql.py
Field was absent
{
"sha256": "246f4a7bdf972f3d30374398d50d7701ae3aa8f00e86403175e82df6f062b6a7",
"size": 23894
}changed /files/skills~1factiq~1SKILL.md/sha256
"46d0e8dcc2169a508f3ba93b5a00cc9d44d8b8fdbf5d7109f2a6d3938c13e9ab"
"b1583be415b4c87002379f6737819536a9556cc0b55ca47b5ee1af33dee8b4ad"
changed /files/skills~1factiq~1SKILL.md/size
47741
52129
added /files/tests~1__pycache__~1test_directory_submission_readiness.cpython-311-pytest-9.1.1.pyc
Field was absent
{
"sha256": "7cd7a02f7438f3ccb26d9887b3434e9de712e1a1ba8b31e02188fe7ed259e5b4",
"size": 9731
}added /files/tests~1__pycache__~1test_earnings_docs.cpython-311-pytest-9.1.1.pyc
Field was absent
{
"sha256": "cce9b51a6d22b7085758a56649b264874da358e8d661ab19901e96dd9c749b23",
"size": 8276
}added /files/tests~1__pycache__~1test_earnings_docs.cpython-312-pytest-8.4.0.pyc
Field was absent
{
"sha256": "6ea5eab90eab2f70dde65e6870c0b4c0604a5126b884d20d3cb9541167d81df7",
"size": 6506
}added /files/tests~1__pycache__~1test_media_docs.cpython-311-pytest-9.1.1.pyc
Field was absent
{
"sha256": "a9c11af354f7918893faf1dc53bd478e8b622f44f8435072dab99d7394a28e29",
"size": 9927
}added /files/tests~1__pycache__~1test_media_docs.cpython-312-pytest-8.4.0.pyc
Field was absent
{
"sha256": "77c4092fa0c7e91219fca81739eec2094b70779623b518b2a464ef97dc1f466b",
"size": 8624
}added /files/tests~1__pycache__~1test_retired_publishing_tools.cpython-311-pytest-9.1.1.pyc
Field was absent
{
"sha256": "092c2a078d0d34ec21dd9cf5e0ca61665cba3080d44c80f2a338c72c40fd7720",
"size": 2790
}added /files/tests~1__pycache__~1test_trade_scripts.cpython-311-pytest-9.1.1.pyc
Field was absent
{
"sha256": "d341dcc6f3409f2eb1a6fef285d8ee450cdc9af181aa4b1bf44753dce27be131",
"size": 39627
}added /files/tests~1__pycache__~1test_trade_scripts.cpython-312-pytest-8.4.0.pyc
Field was absent
{
"sha256": "a7915418895584c253832c1d221e17fe97606e39b0e2e8f041cbf1c64f425a55",
"size": 37264
}added /files/tests~1test_directory_submission_readiness.py
Field was absent
{
"sha256": "996daa950b56bd3368d7e45221c75b8fa9ce7a1a7a23d91734f8ddc286f81f3a",
"size": 6918
}added /files/tests~1test_earnings_docs.py
Field was absent
{
"sha256": "6e596f81295baaefb70ae514dee2f9e6175c34d146afba1ac27a01412040304a",
"size": 4884
}added /files/tests~1test_media_docs.py
Field was absent
{
"sha256": "214149d3ddb196a85639600ce7ae75a25add42196a5923d8b95123c36dd54974",
"size": 6290
}added /files/tests~1test_retired_publishing_tools.py
Field was absent
{
"sha256": "395261b5067573c050ecda46f594530d91d67fc2ec07484540c9adeaa0a2306a",
"size": 1442
}added /files/tests~1test_sql_docs.py
Field was absent
{
"sha256": "18b2581835f82ce007d78e538e5359d2ad30fa13f37652bea06aba5da21c6872",
"size": 12090
}added /files/tests~1test_trade_scripts.py
Field was absent
{
"sha256": "d024d95711d2da25f2407626d81422357ded2ec8b3791dd9934dab1140123d04",
"size": 27782
}Full snapshot data
{
"files": {
".claude-plugin/marketplace.json": {
"sha256": "49fb6b53e79d5715aa9a9a093a0bf8d7f3dbd8b9a9328bb9ae21b336aa88cf49",
"size": 610
},
".claude-plugin/plugin.json": {
"sha256": "dec61fe1e1790fd335e220e1c54c16120e2e7632e16e044fe32f010d58d9c36e",
"size": 927
},
".codex-plugin/plugin.json": {
"sha256": "add8506ef8caab254eb8e3518555c6a398af5aea31b7e1089d38ff02d4ea2cf9",
"size": 2536
},
".gitignore": {
"sha256": "566702bcfdb6180828438f56a6f35b82c75d7221aa69a8c6aa7621adf8df5f00",
"size": 126
},
".mcp.json": {
"sha256": "bd6807e5f73d473c49f99a29cd0eb178ba1e25349cd3db388d4f980963acaec9",
"size": 112
},
"LICENSE": {
"sha256": "ffe02ec2d2f9b23b61b38602bfd44d0fa777600a1cb1e8765da0626d09bd7114",
"size": 1068
},
"README.md": {
"sha256": "ff859c70ed0a7e6e53f2f077afd79125a1f6ac0d5e93e6764a17f49096f704ab",
"size": 16746
},
"SETUP.md": {
"sha256": "4a6e0b5db6c5948e362c9442ee2d9c35dd9980bafd6c01a056a7d123be5a286e",
"size": 2958
},
"assets/factiq-logo.png": {
"sha256": "3b7bc0447b0612514780bc363f5a205710ef66de15daed4524ac4624998161e3",
"size": 17317
},
"evals/README.md": {
"sha256": "976b22bcc20d210ac3187e45154be00bfbeb68ffc17412de2d8eea9417f6a163",
"size": 8941
},
"evals/bilateral-trade-sql/graders/one-hs-level-only.md": {
"sha256": "1858daf1ab5d4774154d77458e7aa079da270af35e3476e904752180e6b82726",
"size": 471
},
"evals/bilateral-trade-sql/graders/partner-code-is-numeric.md": {
"sha256": "ebfb683108dca135318753256062de5ababbd417c3fa3eaa3a1b9c712cd92f17",
"size": 523
},
"evals/bilateral-trade-sql/graders/used-the-bundled-generator.md": {
"sha256": "8d5dfaa90973849c823636a1cf001b537fe4346f3f31e4467179557b45d90536",
"size": 121
},
"evals/bilateral-trade-sql/graders/value-series-only.md": {
"sha256": "83258957a67431b6ddaaa98e01cd4694533f814ba4ecf97b14b0ae981eef9bec",
"size": 466
},
"evals/bilateral-trade-sql/prompt.md": {
"sha256": "6e0aeeaef20feb8ad194bfac0fb77fd63816c42fc8b1fc24914a1072e88e6b29",
"size": 842
},
"evals/filings-duplicate-line/graders/figure-is-not-doubled.md": {
"sha256": "7f7444985429c85502638acdd809f0bc96b3b7a676d6f9b6ac246bfd88505ddf",
"size": 123
},
"evals/filings-duplicate-line/graders/figure-is-the-first-line.md": {
"sha256": "325edda2814c36316d071e690539068175a5d9334eaf9bd555e84c5a38d2667d",
"size": 808
},
"evals/filings-duplicate-line/graders/no-invented-filing-links.md": {
"sha256": "46043047d26759ce2ed60643464fd5a377f2d75a46937b1f17ee5f53f420f15b",
"size": 550
},
"evals/filings-duplicate-line/graders/source-link-is-the-filing.md": {
"sha256": "30cf2586d074446b24b07333cf4860bc267b42d3efd36ed9f319f9aafcb11c41",
"size": 163
},
"evals/filings-duplicate-line/prompt.md": {
"sha256": "4cd0b9906584614ca73ddec45d3681a3573bbc68ce076274ae89826e228ac055",
"size": 813
},
"evals/latest-value-direct-answer/graders/answers-in-prose.md": {
"sha256": "04588e346003462f88adf6a2fe6b85b5dd62f8c17ded2212b2bc9d068e5929a7",
"size": 669
},
"evals/latest-value-direct-answer/graders/no-chart-file-written.md": {
"sha256": "a06cd9171ce44db1511d189c1467b55dd76e0ddd3025bf9c63ffd6df1eaada46",
"size": 60
},
"evals/latest-value-direct-answer/prompt.md": {
"sha256": "3a957c231947743012ecb886cd3c5fffa6e528444826b487df1b180f59d2d40e",
"size": 577
},
"evals/mocks/factiq/_tools.json": {
"sha256": "b867d3bc2218c923d117350a8d19391578e31aaba251d806b766f711c4083373",
"size": 58563
},
"evals/mocks/factiq/describe_dataset.md": {
"sha256": "aef6ae3bad4de381194fd3533f5ac2bf291f5c94cbe2a4c840eb09ad6fa91558",
"size": 2132
},
"evals/mocks/factiq/fixtures/LNS14000000.json": {
"sha256": "3432a266cfbd4d7c32b11cec8d8f7305db7e97b4f7a91930c166b13719071b93",
"size": 8750
},
"evals/mocks/factiq/fixtures/PKG.json": {
"sha256": "236b9ba9dd79f5e160faaa32e6c5991a909c4162011ec539f11fba0ee682215f",
"size": 15247
},
"evals/mocks/factiq/get_data_catalog.md": {
"sha256": "840dc24cf2f2eb91611464c95d3414152c404df96600fae160fd0d1c07a777bb",
"size": 6858
},
"evals/mocks/factiq/get_series.md": {
"sha256": "8be660b04874d51a9f4476049e8623e07eca076fb71dce5dcf7fccb9817c9d5b",
"size": 41
},
"evals/mocks/factiq/get_style_guides.md": {
"sha256": "6363e4370e733e924f18a2c71a611509a1926a781e68ead99646b76659256f5a",
"size": 880
},
"evals/mocks/factiq/run_sql.md": {
"sha256": "77b6cee5f1133990bc93147fe8e2956f9b8b0b4a5fc14783dbcc9971d91130d5",
"size": 2181
},
"evals/mocks/factiq/search_company_filings.md": {
"sha256": "d7fa2f3b3a67aef362b459b0eba2362f2f3d12c242dded32a3f1402f95f3f268",
"size": 39
},
"evals/mocks/factiq/search_datasets.md": {
"sha256": "98f364b4a4189012c607031b595c3e1bd7cb8e3ba95e10f59dd7aaf78883418f",
"size": 1034
},
"evals/mocks/factiq/search_earnings_transcripts.md": {
"sha256": "6f0187121c6c4e5f998be00612e9d5bff30c6d5b6ad36ffccd447e21ba1650d5",
"size": 6189
},
"evals/mocks/factiq/search_series.md": {
"sha256": "4a78565f723fcf708bcdc08f7df142f3568ad1652db43b87796d091716e9c41b",
"size": 1302
},
"evals/quick-chart-of-a-trend/graders/answer-states-gap-and-source.md": {
"sha256": "b2dd20ccd3a717585bdfe2b5bfe101042ca3933734ab6cb273d5ac4bff90561f",
"size": 492
},
"evals/quick-chart-of-a-trend/graders/chart-file-written.md": {
"sha256": "53a654575c25d75251de7e79e8d40d1837b12f186d31060f3a2a7819dfcaefcc",
"size": 53
},
"evals/quick-chart-of-a-trend/graders/missing-month-is-not-filled-in.md": {
"sha256": "4012378ca9d63de3ebee5f3fdb39b78ff5095bd861f97716323d8564a3c8d1b2",
"size": 528
},
"evals/quick-chart-of-a-trend/graders/spec-is-a-valid-chartspec.md": {
"sha256": "72ea853a887ba0bd91a97f49ae52cdbd66cb295eb4888c1bcb47719892bad82c",
"size": 946
},
"evals/quick-chart-of-a-trend/graders/title-makes-a-claim.md": {
"sha256": "2d9c5e1e0ff470e04d170bd88140d874324a7db4086feb53adf19216d371a4d0",
"size": 656
},
"evals/quick-chart-of-a-trend/prompt.md": {
"sha256": "956fc00fd943f70ae85de3bd22b6b60147846dd67a3297ecbec36d64eff723d2",
"size": 690
},
"evals/quote-and-source-discipline/graders/analyst-framing-is-not-management.md": {
"sha256": "db4672fe197c1bbc858969604d0fbdfece844c4a95bb4cbffb2a94da904b0553",
"size": 608
},
"evals/quote-and-source-discipline/graders/link-fy2025q2-is-the-supplied-one.md": {
"sha256": "e5723ee4f90d36c669c66dfa247d5674dd4e71f6bb8b5290f4d1c7d65a4b89e4",
"size": 216
},
"evals/quote-and-source-discipline/graders/link-fy2026q4-is-the-supplied-one.md": {
"sha256": "f0615b5f82e65e997603fd0dce33d331e0dc5aa86738521ea7e0720d9ffa484c",
"size": 215
},
"evals/quote-and-source-discipline/graders/link-fy2027q1-is-the-supplied-one.md": {
"sha256": "da50e2f5694fdaf824130515c6cad1edd6581cc0068054c6eead1f03546fed87",
"size": 215
},
"evals/quote-and-source-discipline/graders/missing-link-is-declared.md": {
"sha256": "3286a7f25db8fc1c059b14977cc35cd72cbb6bba67720b7b58137a47ad201177",
"size": 486
},
"evals/quote-and-source-discipline/graders/no-invented-source-links.md": {
"sha256": "3418802ca26fd0b78017ccdab87a0a243cce30966c5e3482a87d1708a6e98ee0",
"size": 167
},
"evals/quote-and-source-discipline/graders/quotes-are-verbatim.md": {
"sha256": "af6f44f2a953d8de18d8592486114447a94e8f621f0ea0a2e52d6d284d74ed14",
"size": 2001
},
"evals/quote-and-source-discipline/prompt.md": {
"sha256": "1287da04c18787fa65b4cb016cef62fe7d208b360f0d7d7f6750ffb68db35f78",
"size": 781
},
"evals/run_ablation.py": {
"sha256": "550702da90fbe53889c67ef30f6cb7254e31fa1009719ec869f313b3aed9f1d3",
"size": 9041
},
"evals/unrelated-coding-request/graders/answers-the-python-question.md": {
"sha256": "4db03d4fcb5e4bb6a04162e0dad4b5db3fef97d145103d64bfb041b50946f12a",
"size": 407
},
"evals/unrelated-coding-request/graders/no-catalog-lookup.md": {
"sha256": "60bfc77bae34c51bdb2a2b7a3b8c72719e5bd55d81a281a71e9026595d426260",
"size": 98
},
"evals/unrelated-coding-request/graders/no-factiq-skill-invoked.md": {
"sha256": "22813294a356e15059d59459cbe5da9ec0a4a18c760d9521ddc35ae886dcd7c5",
"size": 80
},
"evals/unrelated-coding-request/graders/no-series-fetch.md": {
"sha256": "ede84d92b6c6e73e1e42d8968ddd3c8c0c8f9d7560bd169131987ca1db3e23f9",
"size": 92
},
"evals/unrelated-coding-request/graders/no-sql-call.md": {
"sha256": "3e5d7fdb2a6fb1566d4ba420eb12550281f72f0deec9cb9e613378ceb76cd7ae",
"size": 89
},
"evals/unrelated-coding-request/prompt.md": {
"sha256": "40eb7a0228cca78e53786e361c687eb96238814f69911fc9d998f501b6575250",
"size": 492
},
"evals/yoy-across-a-missing-month/graders/missing-month-is-stated.md": {
"sha256": "560524f7356fb5ceedf5314bfb511ae0b70c63c6b92bace819c52cc0cce26ee3",
"size": 376
},
"evals/yoy-across-a-missing-month/graders/yoy-values-are-date-matched.md": {
"sha256": "3d6dfbc6957296d246e5e767d23ce83e134b92aa179d824cb6988100f3ba80cd",
"size": 860
},
"evals/yoy-across-a-missing-month/prompt.md": {
"sha256": "fcdbe2f5cc33e6a2d0e27d88143ea5d5fd57c59cd1ccbb889c58b9cbbe7aa380",
"size": 678
},
"evals/yoy-without-a-server-hint/graders/missing-month-is-stated.md": {
"sha256": "560524f7356fb5ceedf5314bfb511ae0b70c63c6b92bace819c52cc0cce26ee3",
"size": 376
},
"evals/yoy-without-a-server-hint/graders/yoy-values-are-date-matched.md": {
"sha256": "3d6dfbc6957296d246e5e767d23ce83e134b92aa179d824cb6988100f3ba80cd",
"size": 860
},
"evals/yoy-without-a-server-hint/mocks/factiq/fixtures/LNS14000000.json": {
"sha256": "9827dc5a5e9f5390e7ebf352502d29ad95a7a0654355622ab0a53aad40c6bd6a",
"size": 7971
},
"evals/yoy-without-a-server-hint/mocks/factiq/get_series.md": {
"sha256": "8be660b04874d51a9f4476049e8623e07eca076fb71dce5dcf7fccb9817c9d5b",
"size": 41
},
"evals/yoy-without-a-server-hint/mocks/factiq/run_sql.md": {
"sha256": "8236cf759b4a8f1f91c7725c7f54d69679490766f110aa29bd846c6a7537e98a",
"size": 2146
},
"evals/yoy-without-a-server-hint/prompt.md": {
"sha256": "678326246a74ba8f44c43dad47b172248ff9e030df00146f766acd52ec88467b",
"size": 786
},
"references/data/satellite.md": {
"sha256": "2d310c84485c86f91b8a864dc69147988c07f5d9a06a96e0c42961014406b882",
"size": 13687
},
"references/data/schemas.md": {
"sha256": "51fd1bd6e71b5a48dd8b15cc923e16d608c2d2638edfda5c0fff1a1d56ca47b8",
"size": 22132
},
"references/data/sql-guide.md": {
"sha256": "4924bd8ae696ef3ee8aaa5c5dbb4ba53356cefa82653d65b3040df407e800027",
"size": 21312
},
"references/output/chart-spec.md": {
"sha256": "2fb1b622fa6b037e8860c3bfba20bfd97b744192f34d36df16fec82b6f4c30dc",
"size": 8704
},
"references/output/report-spec.md": {
"sha256": "5e16ae46b0fc2083a35dc262e4483d87e88cc9c6fb8f1412eebd7b2b0570250c",
"size": 14050
},
"references/report-patterns/README.md": {
"sha256": "674c9df1c81c8cb5d4beb07243ba837217da86912e5e2a59c63641a9531166b9",
"size": 11027
},
"references/report-patterns/bilateral-economic-policy.md": {
"sha256": "48c89a71f875aa92d7a7ddd11e3c134b108788585f48a8f13af65b2e323e4305",
"size": 9123
},
"references/report-patterns/bilateral-trade.md": {
"sha256": "98cc223764dd709ffb64ddcb13d3e549669e28331736140e769bae7319d76dac",
"size": 19502
},
"references/report-patterns/business-formation-statistics.md": {
"sha256": "324ea681d9b3ad7eceb9cc5371608ac01fd86743b3c3581236398053184cbcda",
"size": 5440
},
"references/report-patterns/earnings-intelligence.md": {
"sha256": "9e491f60843c1fa4d9b0e4f5ddd831974ce2f3eddbc202ad77f64549f33c0634",
"size": 17082
},
"references/report-patterns/fiscal-policy-revenue.md": {
"sha256": "7525d09c34a0b990e0eb5cf73bcf1e7077bd373e0be8be238706cde1b0cbc670",
"size": 7628
},
"references/report-patterns/interview-step.md": {
"sha256": "b5edb929dfcc6257c1b25fc407ae29878383c0dca9cf974041e437f0b70e0682",
"size": 3806
},
"references/report-patterns/media-intelligence.md": {
"sha256": "a9f31dc9760757af5c6462333ca176bfa724980814f3fc55e77ba107b50f0f22",
"size": 17242
},
"references/report-patterns/monetary-policy.md": {
"sha256": "6439f63e7c77ab5d5d424a09bc112edea12f37630615c96315e80490939ffa38",
"size": 11190
},
"scripts/__pycache__/term_chart.cpython-312.pyc": {
"sha256": "9b87da15116997e594cba9e058b9ff8e015cd91be7322c1c84d1d0bf6599d14b",
"size": 32120
},
"scripts/comext_sql.py": {
"sha256": "8a8bcc07156d5f1527540dae466ca6ee6ae0c6a743dadeb3d1c8cf94fb87d187",
"size": 19633
},
"scripts/data/hs_names.json.gz": {
"sha256": "3f5def41a331d3ad3a4ebb70c49e442e6e19e898673c577c04fa8be1ea9e017b",
"size": 155694
},
"scripts/data/trade_partners.json": {
"sha256": "7445d1193623a87480dbe68107a007bcd23c73aa330cec3c30e04ba3b662bc67",
"size": 38397
},
"scripts/hs_codes.py": {
"sha256": "38230174536c64a18adfb130b486d81a9dc7e6c69ca866f08a1fd6ecca071f98",
"size": 7191
},
"scripts/series_math.py": {
"sha256": "5ee047d8b9d00c934b3e1bd1f25c1a25e6a545c09371f8f5a93ad46adce6cdf1",
"size": 22168
},
"scripts/trade_sql.py": {
"sha256": "246f4a7bdf972f3d30374398d50d7701ae3aa8f00e86403175e82df6f062b6a7",
"size": 23894
},
"skills/factiq/SKILL.md": {
"sha256": "b1583be415b4c87002379f6737819536a9556cc0b55ca47b5ee1af33dee8b4ad",
"size": 52129
},
"tests/__pycache__/test_directory_submission_readiness.cpython-311-pytest-9.1.1.pyc": {
"sha256": "7cd7a02f7438f3ccb26d9887b3434e9de712e1a1ba8b31e02188fe7ed259e5b4",
"size": 9731
},
"tests/__pycache__/test_earnings_docs.cpython-311-pytest-9.1.1.pyc": {
"sha256": "cce9b51a6d22b7085758a56649b264874da358e8d661ab19901e96dd9c749b23",
"size": 8276
},
"tests/__pycache__/test_earnings_docs.cpython-312-pytest-8.4.0.pyc": {
"sha256": "6ea5eab90eab2f70dde65e6870c0b4c0604a5126b884d20d3cb9541167d81df7",
"size": 6506
},
"tests/__pycache__/test_media_docs.cpython-311-pytest-9.1.1.pyc": {
"sha256": "a9c11af354f7918893faf1dc53bd478e8b622f44f8435072dab99d7394a28e29",
"size": 9927
},
"tests/__pycache__/test_media_docs.cpython-312-pytest-8.4.0.pyc": {
"sha256": "77c4092fa0c7e91219fca81739eec2094b70779623b518b2a464ef97dc1f466b",
"size": 8624
},
"tests/__pycache__/test_retired_publishing_tools.cpython-311-pytest-9.1.1.pyc": {
"sha256": "092c2a078d0d34ec21dd9cf5e0ca61665cba3080d44c80f2a338c72c40fd7720",
"size": 2790
},
"tests/__pycache__/test_trade_scripts.cpython-311-pytest-9.1.1.pyc": {
"sha256": "d341dcc6f3409f2eb1a6fef285d8ee450cdc9af181aa4b1bf44753dce27be131",
"size": 39627
},
"tests/__pycache__/test_trade_scripts.cpython-312-pytest-8.4.0.pyc": {
"sha256": "a7915418895584c253832c1d221e17fe97606e39b0e2e8f041cbf1c64f425a55",
"size": 37264
},
"tests/test_directory_submission_readiness.py": {
"sha256": "996daa950b56bd3368d7e45221c75b8fa9ce7a1a7a23d91734f8ddc286f81f3a",
"size": 6918
},
"tests/test_earnings_docs.py": {
"sha256": "6e596f81295baaefb70ae514dee2f9e6175c34d146afba1ac27a01412040304a",
"size": 4884
},
"tests/test_media_docs.py": {
"sha256": "214149d3ddb196a85639600ce7ae75a25add42196a5923d8b95123c36dd54974",
"size": 6290
},
"tests/test_retired_publishing_tools.py": {
"sha256": "395261b5067573c050ecda46f594530d91d67fc2ec07484540c9adeaa0a2306a",
"size": 1442
},
"tests/test_sql_docs.py": {
"sha256": "18b2581835f82ce007d78e538e5359d2ad30fa13f37652bea06aba5da21c6872",
"size": 12090
},
"tests/test_trade_scripts.py": {
"sha256": "d024d95711d2da25f2407626d81422357ded2ec8b3791dd9934dab1140123d04",
"size": 27782
}
}
}SHA-256 of public snapshot: 2437a378d6bdbf34db5cb4c2c9fed0392b6d6acd0b48c7fc5d12ab4a5fd75c12