diff --git a/README.md b/README.md index 959a16d..8b706e3 100644 --- a/README.md +++ b/README.md @@ -2,147 +2,67 @@ # STAC Scout -**Find the data. Prove it exists. Know what you're getting.** - -`intent → task semantics → catalog federation → live item evidence → asset plan → manifest` - -[![CI](https://github.com/GeoGeekLab/stac-scout/actions/workflows/ci.yml/badge.svg)](https://github.com/GeoGeekLab/stac-scout/actions/workflows/ci.yml) -[![Python](https://img.shields.io/badge/Python-3.12%20%7C%203.13%20%7C%203.14-3776AB?style=flat-square&logo=python&logoColor=white)](.github/workflows/ci.yml) -[![License: MIT](https://img.shields.io/badge/license-MIT-2ea44f?style=flat-square)](LICENSE) -[![STAC](https://img.shields.io/badge/STAC-evidence--first-111111?style=flat-square)](https://stacspec.org/) - -A deterministic decision layer for the STAC ecosystem. - - - -## STAC is syntax. Dataset choice is semantics. - -A model can generate a valid STAC query. - -That does not mean it chose the right dataset. - -A Collection can advertise the right spatial and temporal extent. - -That does not mean an Item actually exists for your AOI and date. - -An asset can be called `B08`. +--- -That does not mean a caller should silently assume what it contains. +**Scout STAC catalogs before you commit the compute.** -STAC Scout lives in that gap. +A Python CLI for finding suitable datasets, checking real Items, choosing assets, +planning raster reads, and replaying the result later. -```text -"find imagery for this task" - │ - ▼ - what does the task need? - │ - ▼ - which datasets fit? - │ - ▼ - do matching items exist? - │ - ▼ - which assets are actually required? - │ - ▼ - how much data will this read? - │ - ▼ - can the decision be replayed? -``` +[![CI](https://img.shields.io/github/actions/workflow/status/GeoGeekLab/stac-scout/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/GeoGeekLab/stac-scout/actions/workflows/ci.yml) +[![release](https://img.shields.io/github/v/release/GeoGeekLab/stac-scout?style=flat-square&color=f97316)](https://github.com/GeoGeekLab/stac-scout/releases) +[![PyPI](https://img.shields.io/pypi/v/stac-scout?style=flat-square&color=2563eb)](https://pypi.org/project/stac-scout/) +[![license](https://img.shields.io/badge/license-MIT-16a34a?style=flat-square)](LICENSE) +[![python](https://img.shields.io/pypi/pyversions/stac-scout?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/stac-scout/) +[![typing](https://img.shields.io/badge/typing-strict-2563eb?style=flat-square)](pyproject.toml) -The operating rule is simple: +[Quickstart](#quickstart) · +[Workflow](#workflow) · +[Tasks](#task-intelligence) · +[Providers](#providers) · +[Planning](#asset-and-raster-planning) · +[Replay](#manifests-and-replay) · +[Examples](examples/) · +[Contributing](CONTRIBUTING.md) · +[Security](SECURITY.md) · +[Releases](https://github.com/GeoGeekLab/stac-scout/releases) -> **Never infer what can be inspected.** +
-## What Scout actually does +Scout, the STAC Scout mascot -```text -natural language / structured request - │ - ▼ - IntentDraft - │ - task_type + facts - ▼ - ┌───────────────────┐ - │ TaskAdvisor │◄──── versioned task rules - └────────┬─────────┘ - │ - ▼ - ScoutRequest - │ - ┌───────┴────────┐ - │ │ - ▼ ▼ - ScoutEngine FederatedScout - │ │ - │ provider isolation - │ dataset identity - │ duplicate evidence - │ explicit failures - │ │ - └───────┬────────┘ - ▼ - live Item probe - │ - AOI coverage - │ - asset semantics - │ - access planning - │ - ▼ - manifest + replay -``` +**Find it. Verify it. Plan it. Replay it.** -Scout does **not** replace `pystac-client`, `odc-stac`, or a STAC API. + -It decides what should be asked, checks what came back, and records why. +## What is STAC Scout? -## The invariants +STAC Scout is a small decision layer for STAC workflows. -These are not style preferences. They are the contract. +It helps answer the questions that usually show up between "I found a Collection" and +"my pipeline is ready to run": -- **Collection metadata is not availability evidence.** Item Search is. -- **`intersects` is not AOI coverage.** -- **Unknown is not false.** -- **Required and preferred measurements are different things.** -- **Task rules do not invent dates.** -- **Explicit user constraints beat defaults.** -- **Probable duplicates stay visible.** -- **Provider health is not scientific quality.** -- **A language model may classify intent; it does not own geospatial truth.** -- **Every useful decision should be reproducible.** +- Which collections match the task and the hard constraints? +- Do matching Items actually exist for this AOI and time window? +- Which assets should be loaded? +- What resolution, CRS, resampling, and approximate transfer size should the read use? +- Can the same choice be inspected again after the catalog changes? -Or shorter: +Scout works with normal STAC APIs. It does not replace +[pystac-client](https://github.com/stac-utils/pystac-client), +[odc-stac](https://github.com/opendatacube/odc-stac), or the provider itself. -```text -metadata ≠ evidence -similarity ≠ identity -availability ≠ suitability -confidence ≠ proof -``` +## Quickstart -## Install +Install from PyPI: ```bash python -m pip install stac-scout ``` -Python 3.12 or newer is required. Python 3.12, 3.13, and 3.14 are tested in CI. - -For Planetary Computer access recipes: - -```bash -python -m pip install "stac-scout[planetary-computer]" -``` - -## 60-second first success +Python 3.12, 3.13, and 3.14 are tested in CI. -This first check is deterministic and does not call a remote catalog: +Create a request: ```bash cat > request.json <<'JSON' @@ -155,302 +75,212 @@ cat > request.json <<'JSON' } } JSON - -stac-scout advise request.json --task wildfire_impact ``` -The important part of the output is the decision contract, not prose: - -```json -{ - "data_type": "optical", - "required_measurements": ["nir", "swir22"], - "follow_up_requirements": ["comparison_windows"] -} -``` - -Scout derives the optical/NIR/SWIR2 requirement but refuses to invent the missing comparison -window. For a live Item-to-manifest walkthrough, see -[`examples/wildfire-impact/`](examples/wildfire-impact/). - -## Geo Task Intelligence - -![Geo Task Intelligence workflow](docs/assets/geo-task-intelligence.svg) - -The user often knows the problem, not the bands. +Ask Scout what the task needs: -```text -"assess wildfire impact" - ↓ -optical - ↓ -NIR + SWIR2 required - ↓ -surface reflectance preferred - ↓ -before/after strategy - ↓ -comparison_windows still required from the user +```bash +stac-scout advise request.json --task wildfire_impact ``` -Scout keeps that knowledge in a versioned, inspectable registry instead of hiding it in prompts. +The task profile adds the dataset requirements it can derive and reports anything that still +needs to come from the caller. -List the built-in task archetypes: +Then move on to live catalogs: ```bash -stac-scout tasks -stac-scout task-profile wildfire_impact -``` - -Derive task-aware data requirements: +stac-scout federate request.json -```bash -stac-scout advise request.json --task wildfire_impact -``` +stac-scout verify request.json \ + --provider earth-search \ + --collection sentinel-2-l2a -The output includes: +stac-scout plan request.json \ + --provider earth-search \ + --collection sentinel-2-l2a \ + --manifest scout.manifest.json \ + --recipe load.py -```text -TaskProfile -├── rule_id -├── rationale -├── sources -├── required measurements -├── preferred measurements -├── temporal strategy -├── processing preferences -└── mask preferences - -TaskAdvice -├── enriched ScoutRequest -├── derivations[] -│ ├── rule_id -│ ├── field -│ ├── value -│ ├── required | preferred -│ └── rationale -├── follow_up_requirements[] -└── notes[] +stac-scout replay scout.manifest.json ``` -Task rules live in: - -```text -src/stac_scout/data/tasks.toml -``` +For a complete runnable walkthrough, see +[`examples/wildfire-impact/`](examples/wildfire-impact/). -The scientific basis and rule boundaries are documented in [`docs/TASK_RULES.md`](docs/TASK_RULES.md). +## Workflow -### Rules are allowed to say "I don't know" +Scout deliberately keeps the workflow boring and inspectable: -For example, a before/after wildfire task does **not** cause Scout to hallucinate a pre-fire window. +| Stage | CLI | What you get | +| --- | --- | --- | +| **Find** | `discover`, `federate` | candidate collections from one or more catalogs | +| **Verify** | `verify` | matching Items, timestamps, footprints, asset keys, cloud metadata when present | +| **Plan** | `plan` | selected assets, raster settings, estimated bytes, manifest, optional load recipe | +| **Replay** | `replay` | comparison against the saved manifest and current catalog state | -It returns: +Typical single-provider run: -```json -{ - "follow_up_requirements": ["comparison_windows"] -} +```bash +stac-scout discover request.json --provider earth-search +stac-scout verify request.json --provider earth-search --collection sentinel-2-l2a +stac-scout plan request.json --provider earth-search --collection sentinel-2-l2a ``` -Likewise, if the user explicitly asks for SAR while a task's default modality is optical, Scout preserves SAR and skips incompatible optical band defaults. - -No spectral fan fiction. +Typical multi-provider run: -## Intent boundary +```bash +stac-scout federate request.json --max-workers 4 --overall-timeout 30 +``` -STAC Scout deliberately does not ship an LLM SDK in the core package. +## Task intelligence -Any structured-output model can produce an `IntentDraft`. +Users usually know the job before they know the bands. -Get the contract: +Scout ships versioned task profiles for common geospatial workflows: ```bash -stac-scout intent-contract -stac-scout schema intent +stac-scout tasks +stac-scout task-profile wildfire_impact ``` -The model may identify a supported `task_type`. - -It is explicitly told **not** to invent: - -- coordinates; -- dates; -- dataset names; -- measurement names; -- hidden constraints. +A profile can define: -Those belong to deterministic code, explicit user input, or live metadata. +- optical or SAR modality; +- required and preferred measurements; +- temporal strategy; +- processing preferences; +- mask preferences; +- short scientific rationale and sources. -Resolve an intent directly: +Apply one to a request: ```bash -stac-scout resolve-intent intent.json +stac-scout advise request.json --task wildfire_impact ``` -Resolve it and apply task intelligence: +For example, the wildfire profile requires NIR and SWIR2 and uses a before/after strategy. +If the comparison windows are not in the request, Scout asks for them instead of making them up. -```bash -stac-scout advise-intent intent.json -``` +Task rules live in +[`src/stac_scout/data/tasks.toml`](src/stac_scout/data/tasks.toml), with notes in +[`docs/TASK_RULES.md`](docs/TASK_RULES.md). -If required information is still ambiguous, the draft stays unresolved. +## Providers -That is a feature. +The built-in provider registry currently enables: -## Providers are adapters, not assumptions +- **Element 84 Earth Search** +- **Microsoft Planetary Computer** -List the built-in provider registry: +List providers: ```bash stac-scout providers stac-scout providers --all ``` -Check operational health: +Check connectivity and adapter health: ```bash stac-scout health stac-scout health --provider earth-search ``` -The default enabled providers are: - -- Element 84 Earth Search -- Microsoft Planetary Computer - -Provider quirks stay behind adapters. - -Planetary Computer signing is recorded explicitly and generated recipes use the official `planetary_computer.sign_inplace` path instead of reimplementing SAS handling. - -Provider latency and uptime are reported as operational evidence only. - -Network behavior is bounded: adapters use explicit connect/read timeouts, a finite transient-retry -budget, capped backoff/Retry-After delays, and typed provider errors. A reachable provider with -invalid metadata is reported as degraded rather than falsely labeled unreachable. - -A slow endpoint does not make a scientifically suitable dataset worse. - -## Federation without pretending everything is the same - -Search a single provider: - -```bash -stac-scout discover request.json --provider earth-search -``` - -Or a raw STAC endpoint: +You can also point Scout at a raw STAC API: ```bash stac-scout discover request.json \ --catalog https://earth-search.aws.element84.com/v1 ``` -Search across enabled providers: - -```bash -stac-scout federate request.json -stac-scout federate request.json --max-workers 4 --overall-timeout 30 -``` - -Federation isolates expected provider failures such as timeouts, rate limits, authentication -errors, malformed metadata, and unsupported capabilities. Each failure reports its type, HTTP -status when known, and whether retry is reasonable. Unexpected internal exceptions are not -converted into provider failures. - -Dataset identity is conservative: +Provider-specific behavior stays behind adapters, including Planetary Computer signing. -```text -sci:doi - → exact +## Federation -collection id + platform / constellation / instrument evidence - → probable +`federate` searches enabled providers concurrently and keeps provider failures separate. -everything else - → local to that catalog +```bash +stac-scout federate request.json \ + --max-workers 4 \ + --overall-timeout 30 ``` -Only exact groups are considered safe to collapse. +Duplicate grouping is conservative: -Probable matches stay visible. +- DOI match → exact identity; +- matching collection/platform/constellation/instrument metadata → probable identity; +- otherwise → local to that catalog. -Because two catalogs agreeing on a name is not the same thing as two catalogs describing the same scientific product. +Probable matches remain visible instead of being silently collapsed. -## The catalog says maybe. Items say yes or no. +## Verification -Verification is item-level. +Collection metadata is useful for discovery. Item Search is what tells you whether the requested +scene is there. ```bash stac-scout verify request.json \ --provider earth-search \ - --collection sentinel-2-l2a + --collection sentinel-2-l2a \ + --max-items 20 ``` -Scout records: +Verification reports, when available: -- matching Item count; -- Item IDs; -- timestamps; +- Item IDs and datetimes; +- AOI coverage; - asset keys; -- cloud metadata when available; -- AOI coverage ratio; -- fraction of each Item intersected by the AOI; -- warnings when geometry or metadata cannot be evaluated. +- cloud metadata; +- provider warnings; +- whether the search hit its Item limit. -AOI coverage normalizes antimeridian-crossing geometry and measures overlap in an AOI-centered WGS84 equal-area projection rather than treating raw longitude/latitude as a flat Cartesian plane. +AOI coverage handles antimeridian-crossing and high-latitude geometry without treating raw +longitude/latitude as a flat Cartesian grid. -Because this is geospatial software. +## Asset and raster planning -## Asset planning - -A scientifically correct Collection can still produce a bad access plan. - -Scout resolves requested measurements against declared asset and band metadata rather than guessing asset names. +`plan` turns a verified collection into an explicit read plan. ```bash stac-scout plan request.json \ --provider earth-search \ --collection sentinel-2-l2a \ + --max-items 20 \ --manifest scout.manifest.json \ --recipe load.py ``` -Planning can produce: - -```text -measurement → asset + selection evidence -resampling strategy + evidence -windowed-read estimate -explicit target output resolution -provider signing requirements -warnings -odc-stac recipe -``` +The access plan can include: -`max_source_resolution_m` answers “is this source data fine enough?” while -`target_resolution_m` answers “what output grid should I request?”. It requires an explicit -`target_crs` whose units are meters (or odc-stac's explicit `"utm"` selector), because odc-stac -interprets resolution in output-CRS units. Scout never reuses the source threshold as an output -resampling instruction. The legacy input name -`max_spatial_resolution_m` is accepted as a source-resolution alias for compatibility. +- measurement → asset mapping; +- why an asset was selected; +- categorical vs continuous resampling choice; +- source GSD checks; +- target CRS and output resolution; +- provider signing requirements; +- estimated transfer bytes when `file:size` is available. -If multiple assets remain equally supported after semantic, role, coverage, media-type, and GSD -evidence, Scout reports the selection as ambiguous instead of choosing the alphabetically first -key. Unknown resampling semantics likewise remain unresolved rather than defaulting to bilinear. +Source and output resolution are separate settings: -When `file:size` exists, Scout estimates transfer volume from the AOI/item intersection fraction. +```text +max_source_resolution_m # "is the source detailed enough?" +target_resolution_m # "what output grid should I request?" +target_crs # projected CRS or "utm" +``` -It is an estimate, not a bandwidth prophecy. +If asset metadata is genuinely ambiguous, the plan stays unresolved instead of choosing a key +alphabetically. -## Manifests: because catalogs move +## Manifests and replay -A successful query today is not a frozen scientific record. +A plan can be saved as a versioned manifest: -Scout writes a versioned provenance manifest containing the canonical request/query, -provider/catalog identity, search limit and completeness, Collection fingerprint, full access -plan, selected-asset metadata, and the observed decision-matching Item set. Ephemeral asset URLs -are not copied into the provenance snapshot. +```bash +stac-scout plan request.json \ + --provider earth-search \ + --collection sentinel-2-l2a \ + --manifest scout.manifest.json +``` Replay it later: @@ -458,49 +288,41 @@ Replay it later: stac-scout replay scout.manifest.json ``` -By default replay reuses the manifest's recorded `max_items`. You can override it explicitly, -but Scout records that the limits differ. +The manifest records the request, provider/catalog identity, search limit/completeness, +collection fingerprint, selected Item IDs, asset metadata needed by the plan, output settings, +warnings, and assumptions. -Replay reports: +Replay reports retained, missing, new, and unresolved Item IDs plus collection metadata changes. -```text -comparison status: complete / partial / inconclusive -retained Item IDs -confirmed missing Item IDs -confirmed new Item IDs -unresolved missing Item IDs -unresolved new Item IDs -Collection metadata changed: true / false / unknown -``` +A capped search is not treated as a complete catalog snapshot. -A search that returns exactly `max_items` is marked `limit_reached`, not assumed complete or -definitely truncated. If either historical or current completeness cannot be proven, Scout will -not promote ordering/sample differences into confirmed drift. +## A few opinions -The manifest is evidence of the decision. +Scout is intentionally opinionated about a small number of things: -It is not a copy of the remote data. +- hard constraints are checked before ranking; +- missing metadata stays unknown; +- an Item limit is not proof that the search was complete; +- explicit user choices beat task defaults. -## CLI map +That is most of the philosophy. The rest is code and tests. + +## CLI ```text stac-scout ├── version ├── validate-request ├── schema -│ ├── intent-contract ├── resolve-intent ├── advise-intent -│ ├── tasks ├── task-profile ├── advise -│ ├── providers ├── health ├── inspect-catalog -│ ├── discover ├── federate ├── verify @@ -508,86 +330,57 @@ stac-scout └── replay ``` -## Repository map +Use `--help` on any command: -```text -stac-scout/ -├── src/stac_scout/ -│ ├── catalogs/ # STAC access boundary -│ ├── data/ -│ │ ├── providers.toml -│ │ └── tasks.toml -│ ├── discovery/ # candidate retrieval -│ ├── models/ # strict contracts -│ ├── normalize/ # provider metadata → stable models -│ ├── planning/ # assets, raster semantics, volume -│ ├── provenance/ # manifest + replay -│ ├── verify/ # live evidence + dateline-safe coverage -│ ├── federation.py -│ ├── health.py -│ ├── identity.py -│ ├── reasoning.py -│ ├── scout.py -│ ├── tasking.py -│ └── tasks.py -├── evals/ -│ ├── cases/ -│ ├── federation_cases/ -│ ├── task_cases/ -│ ├── regression_matrix.json -│ ├── runner.py -│ └── live.py -├── examples/ -│ └── wildfire-impact/ -├── docs/ -│ ├── ARCHITECTURE.md -│ └── TASK_RULES.md -├── skill/ -│ └── SKILL.md -└── tests/ +```bash +stac-scout --help +stac-scout plan --help ``` -## Evals over vibes +## Examples -The deterministic evaluation corpus checks contracts that affect dataset decisions: +### Wildfire impact -```bash -python evals/runner.py -``` +[`examples/wildfire-impact/`](examples/wildfire-impact/) follows a real Lahaina use case through: + +1. task requirements; +2. provider federation; +3. live Item verification; +4. asset selection; +5. volume estimation; +6. manifest generation; +7. replay. -It covers request invariants, modality mismatches, cloud PASS/FAIL/UNKNOWN, required versus -preferred measurements, DOI identity strength, multiple extents, antimeridian/polar AOIs, -empty and >100 Item behavior, provider timeout/429/partial failure, categorical resampling, -missing `file:size`, volume budgets, task/user conflicts, malformed provider metadata, -cross-provider identity, task derivation, temporal strategy, and follow-up requirements. +Remote catalog contents can change, so the example documents the workflow rather than pinning a +magic Item count. -`evals/regression_matrix.json` binds the hardening acceptance scenarios to concrete pytest node -IDs, so removing a required regression causes the eval runner to fail. +## Intent integration -Remote providers are intentionally kept out of ordinary CI. +The core package does not depend on an LLM SDK. -Live checks run separately: +If another system produces structured user intent, use the built-in contract: ```bash -python evals/live.py +stac-scout intent-contract +stac-scout schema intent +stac-scout resolve-intent intent.json +stac-scout advise-intent intent.json ``` -That separation is deliberate: - -```text -deterministic behavior - → CI gate - -remote catalog state - → live observation -``` +The rest of the pipeline is the same CLI and model layer used by hand-written requests. ## Development -Contributor installs are editable; normal users should use the PyPI command above. +Scout working at a geospatial developer terminal + +Scout is happiest when the tests are boring. ```bash +git clone https://github.com/GeoGeekLab/stac-scout.git +cd stac-scout + python -m pip install -e ".[dev]" + ruff check . ruff format --check . mypy @@ -596,41 +389,71 @@ python evals/runner.py python -m build ``` -CI runs on Python 3.12, 3.13, and 3.14. Python 3.15 prereleases are exercised as a non-blocking compatibility signal before the final 3.15 release. +CI runs the deterministic suite on Python 3.12, 3.13, and 3.14. Python 3.15 prereleases are used +as a non-blocking compatibility signal. + +Remote provider checks are separate: -Coverage must stay at or above 90%. +```bash +python evals/live.py +``` -The wheel is also checked to ensure the provider and task registries are actually packaged. +See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow. -## What Scout refuses to fake +
+ +## Repository map ```text -"the collection covers 2024, so data must exist" -"cloud_cover=8 means my AOI is clear" -"B08 probably means NIR" -"these two collections have similar names, merge them" -"the provider is fast, therefore the dataset is better" -"wildfire task means I'll invent a pre-fire date" -"the model sounded confident" +stac-scout/ +├── src/stac_scout/ +│ ├── catalogs/ # STAC adapters and network boundary +│ ├── data/ # provider + task registries +│ ├── discovery/ # candidate retrieval +│ ├── models/ # request/result contracts +│ ├── normalize/ # STAC metadata normalization +│ ├── planning/ # asset + raster planning +│ ├── provenance/ # manifest + replay +│ └── verify/ # Item checks and AOI coverage +├── evals/ # deterministic compatibility corpus +├── examples/ +│ └── wildfire-impact/ +├── docs/ +│ ├── ARCHITECTURE.md +│ ├── MASCOT.md +│ └── TASK_RULES.md +└── tests/ ``` -Those are shortcuts. +## Scout, the mascot -Scout's job is to turn them into inspectable claims. +The little field bug is **Scout**. -## Philosophy +Its layered shell loosely mirrors Collection → Item → Asset, and the scanner is there because +looking first is cheaper than debugging the wrong dataset later. -```text -STAC gives us a language. +Mascot files and usage notes live in [`docs/MASCOT.md`](docs/MASCOT.md). + +## Release -Scout adds skepticism. +The current package is published on PyPI and GitHub Releases: + +```bash +python -m pip install stac-scout +stac-scout version ``` -Or, in GeoGeek form: +Release artifacts are built once, published through PyPI Trusted Publishing, checksum-recorded, +and attached to the matching GitHub Release. + +See [`docs/RELEASE.md`](docs/RELEASE.md). + +## Security -> **The map can look right while the geography is wrong. -> The query can run while the dataset choice is wrong. -> Check the semantics. Check the evidence.** +For security reports, use [SECURITY.md](SECURITY.md). + +If STAC Scout is embedded in a hosted service, treat arbitrary catalog URLs as outbound network +input and apply the deployment's normal egress policy. ## License @@ -640,8 +463,8 @@ Or, in GeoGeek form:
-**Find it. Verify it. Plan it. Replay it.** +**STAC Scout** -`catalog metadata ≠ ground truth` +`find → verify → plan → replay`
diff --git a/docs/MASCOT.md b/docs/MASCOT.md new file mode 100644 index 0000000..3fc7340 --- /dev/null +++ b/docs/MASCOT.md @@ -0,0 +1,93 @@ +# Scout mascot system + +Scout is the visual mascot for **STAC Scout**. + +The character is a small field-scout beetle with a geospatial scanner, layered shell plates, and a +slightly skeptical expression. The goal is to give the project a recognizable open-source face +without turning the README into a product landing page. + +## Character + +Scout should read as: + +- curious; +- technical; +- calm; +- slightly skeptical; +- more field tool than chatbot. + +The character is not a debugging ladybug and should not be drawn as a generic AI robot. + +## Visual language + +Core features should stay stable across new artwork: + +- dark navy / charcoal body; +- cyan scanner eye and small cyan accents; +- two antennae; +- layered shell plates; +- compact geospatial scanner or terminal; +- simple explorer / field-kit details; +- one half-lidded eye or similarly understated expression. + +The layered shell is a loose visual nod to STAC's Collection → Item → Asset structure. It is not a +literal UI diagram. + +## Palette + +| Role | Color | +| --- | --- | +| Midnight | `#0B1B3B` | +| Slate | `#334155` | +| Cyan | `#00D1FF` | +| Blue | `#2563EB` | +| Verified | `#22C55E` | +| Unknown | `#F59E0B` | +| Failed | `#EF4444` | + +Green, amber, and red are status accents only. The normal mascot should remain mostly +midnight/slate/cyan. + +## README assets + +### Main pose + +`docs/assets/mascot/scout-hero.webp` + +Use for the repository header, release notes, or a compact project introduction. + +### Developer pose + +`docs/assets/mascot/scout-terminal.webp` + +Use around development, CLI, contributor, or geospatial coding material. + +## Usage rules + +- Prefer transparent-background art. +- Keep large mascot art to one or two pieces per document. +- Do not bake paragraphs, slogans, version numbers, or command output into the artwork. +- Keep technical labels in Markdown, where they stay searchable and editable. +- Do not use the mascot as a substitute for an architecture diagram. +- Do not imply that Scout is an AI assistant. +- Avoid excessive neon / cyberpunk styling; this is a geospatial developer tool. +- Keep alt text descriptive and short. + +## Suggested poses + +Future artwork can extend the same character into four small actions: + +- **Find** — scanning catalog cards or map layers; +- **Verify** — inspecting an Item footprint; +- **Plan** — organizing raster/assets into a stack; +- **Replay** — comparing two saved map states. + +Those actions should stay visually simple. The README owns the text labels. + +## Naming + +The project is **STAC Scout**. + +The mascot is simply **Scout**. + +Avoid introducing a second product name such as "ScoutBot" or "STAC Bug". diff --git a/docs/assets/geo-task-intelligence.svg b/docs/assets/geo-task-intelligence.svg deleted file mode 100644 index 4d7d25f..0000000 --- a/docs/assets/geo-task-intelligence.svg +++ /dev/null @@ -1,129 +0,0 @@ - - Geo Task Intelligence - A deterministic workflow from user goal to task rules, derived requirements, catalog discovery, live verification, and replayable decision output. - - - - Geo Task Intelligence - Turn a geospatial problem into explicit, testable data requirements. - - - - - - User Goal - wildfire impact - flood extent - snow cover - - - - - - - - Task Type - wildfire_impact - flood_extent - snow_cover - - - - - - - - Task Rules - - - required measurements - - preferred measurements - - temporal strategy - - processing preferences - - mask preferences - versioned • inspectable • deterministic - - - - - - - Derived Requirements - - data type - - bands / measurements - - before-after or single-window - - follow-up requirements - - - - - - - Scout - Request - - - - - - - - - Catalog - Discovery - which datasets fit? - - - - - Live - Verification - do matching items exist? - - - - - - - - Decision Output - asset plan - manifest - replayable evidence - - - ⓘ - Rules do not invent - dates or coordinates. - - - - ⓘ - Explicit user constraints - are preserved. - - - - - intent → task semantics → data requirements → discovery → verification - \ No newline at end of file diff --git a/docs/assets/mascot/scout-hero.webp b/docs/assets/mascot/scout-hero.webp new file mode 100644 index 0000000..96f008d Binary files /dev/null and b/docs/assets/mascot/scout-hero.webp differ diff --git a/docs/assets/mascot/scout-terminal.webp b/docs/assets/mascot/scout-terminal.webp new file mode 100644 index 0000000..208c446 Binary files /dev/null and b/docs/assets/mascot/scout-terminal.webp differ