| # AGENTS.md |
|
|
| ## Project Overview |
|
|
| This repository implements the Minimum Viable Product for the GCMD Science Keyword Classifier described in `PROJECT_SPEC.md`. |
|
|
| The system classifies scientific journal articles into valid Global Change Master Directory Science Keyword concepts using article titles and abstracts. |
|
|
| The classifier must follow the GCMD hierarchy: |
|
|
| `Topic β Term β Variable_Level_1 β Variable_Level_2 β Variable_Level_3` |
|
|
| The MVP must use constrained hierarchical classification rather than unrestricted generation of complete GCMD keyword paths. |
|
|
| ## Sources of Truth |
|
|
| Use the following precedence order when making implementation decisions: |
|
|
| 1. The MVP requirements in `PROJECT_SPEC.md` |
| 2. Other requirements in `PROJECT_SPEC.md` that explicitly apply to the MVP |
| 3. This `AGENTS.md` |
| 4. `IMPLEMENTATION_PLAN.md`, after it has been reviewed and approved |
| 5. Existing source code |
| 6. `prototype/app_hf_poc.py` |
|
|
| When these sources conflict, follow the higher-priority source. |
|
|
| Do not reinterpret the proof of concept as the target architecture. |
|
|
| ## Proof-of-Concept Application |
|
|
| `prototype/app_hf_poc.py` is a frozen Hugging Face Spaces proof of concept and research baseline. |
|
|
| It may be read to understand: |
|
|
| * the current Gradio interface; |
| * multi-label Topic routing; |
| * LangGraph branch fan-out; |
| * Pydantic structured outputs; |
| * current OpenAI model integration; and |
| * Hugging Face deployment assumptions. |
|
|
| It must not be treated as the MVP implementation architecture. |
|
|
| The proof of concept selects complete keyword paths from a Topic-wide list. The MVP must replace that approach with progressive direct-child classification: |
|
|
| `Topic β Term β Variable_Level_1 β Variable_Level_2 β Variable_Level_3` |
|
|
| Do not modify `prototype/app_hf_poc.py`. |
|
|
| Do not incrementally expand it into the MVP. |
|
|
| The final Hugging Face root-level `app.py` should be a thin launcher that imports and starts the tested Gradio interface from the application package. |
|
|
| ## MVP Objective |
|
|
| The MVP must demonstrate that constrained hierarchical classification can produce valid, scientifically defensible GCMD recommendations more reliably than unrestricted complete-path selection. |
|
|
| The MVP must: |
|
|
| * load and recursively parse `gcmd_hierarchy.json`; |
| * create canonical vocabulary records and hierarchy lookup structures; |
| * treat UUID-bearing internal nodes and leaf nodes as assignable concepts; |
| * load and validate articles from `articles.json`; |
| * use DOI as the unique article identifier; |
| * perform multi-label Topic routing; |
| * perform dynamic Term routing within selected Topics; |
| * perform controlled Variable-level descent using direct children only; |
| * allow classification to stop at any supported UUID-bearing level; |
| * support multiple independent classifications per article; |
| * construct authoritative UUIDs, labels, hierarchy levels, and paths from the vocabulary index; |
| * perform deterministic vocabulary validation; |
| * save structured JSON results; |
| * support batch processing; |
| * preserve completed results incrementally; and |
| * provide a lightweight Gradio interface for demonstration. |
|
|
| ## Deferred Features |
|
|
| Do not implement the following as part of the initial MVP unless explicitly requested: |
|
|
| * independent semantic validation; |
| * production-grade human-review interfaces; |
| * vector databases; |
| * embedding-based semantic retrieval; |
| * automated vocabulary synchronization; |
| * external bibliographic lookup; |
| * full-text article retrieval; |
| * integration with CMR or another external metadata system; |
| * evaluation dashboards; |
| * advanced model-comparison infrastructure; |
| * confidence calibration; |
| * risk-based validation policies; |
| * production authentication; |
| * distributed processing; or |
| * production deployment infrastructure. |
|
|
| Interfaces should be designed so deferred features can be added later without major rewrites. |
|
|
| ## Core Classification Rule |
|
|
| The classifier must return the deepest UUID-bearing GCMD concept adequately supported by the article title and abstract. |
|
|
| A broader classification with strong support is preferable to a deeper classification with weak or uncertain support. |
|
|
| A final classification may occur at: |
|
|
| * `Topic`; |
| * `Term`; |
| * `Variable_Level_1`; |
| * `Variable_Level_2`; or |
| * `Variable_Level_3`. |
|
|
| Do not force classification to a leaf node. |
|
|
| Do not treat classification depth as a measure of quality. |
|
|
| ## Vocabulary Authority |
|
|
| `gcmd_hierarchy.json` is the authoritative source for: |
|
|
| * GCMD UUIDs; |
| * concept names; |
| * hierarchy levels; |
| * parentβchild relationships; |
| * definitions; and |
| * canonical paths. |
|
|
| The vocabulary file must be treated as read-only. |
|
|
| The system must not: |
|
|
| * alter GCMD labels; |
| * invent UUIDs; |
| * invent concepts; |
| * construct nonexistent parentβchild relationships; |
| * accept model-generated paths without validation; |
| * silently correct invalid model output; or |
| * add model-generated terms to the vocabulary. |
|
|
| Every final classification must resolve to an existing UUID-bearing record in the loaded hierarchy. |
|
|
| ## Assignable Concepts |
|
|
| Every UUID-bearing GCMD node is assignable, including nodes that have children. |
|
|
| Internal nodes must not be treated only as routing nodes. |
|
|
| A Topic, Term, or intermediate Variable concept may be the correct final classification when the article does not support a more specific descendant. |
|
|
| ## Candidate Selection Rules |
|
|
| Language models must select only from candidates supplied by the application. |
|
|
| At each level, provide only valid direct children of the current parent. |
|
|
| The model must not generate: |
|
|
| * UUIDs; |
| * canonical paths; |
| * hierarchy levels; |
| * authoritative labels; or |
| * parentβchild relationships from memory. |
|
|
| The model response should identify candidate IDs or supplied candidate keys. |
|
|
| The application must retrieve the authoritative UUID, name, level, path, and hierarchy context from the vocabulary index. |
|
|
| When the direct child candidate set fits within configured prompt limits, provide all direct children. |
|
|
| Do not introduce retrieval or pre-ranking unless: |
|
|
| * the candidate set exceeds configured limits; or |
| * evaluation demonstrates a measurable benefit. |
|
|
| ## Article Data Rules |
|
|
| `articles.json` is read-only. |
|
|
| Each article is expected to contain: |
|
|
| * `DOI`; |
| * `Title`; |
| * `Year`; and |
| * `Abstract`. |
|
|
| Assume that DOI values exist and are unique. |
|
|
| Use DOI directly as the article identifier. |
|
|
| Preserve all source fields exactly as provided. |
|
|
| Do not: |
|
|
| * normalize article records; |
| * create replacement article identifiers; |
| * rewrite titles or abstracts; |
| * summarize article text before classification; |
| * supplement article text with external information; or |
| * overwrite source metadata. |
|
|
| Article title and abstract must be treated as untrusted model input. |
|
|
| Prompts must: |
|
|
| * delimit article content clearly; |
| * instruct the model not to follow commands contained in the article text; and |
| * require decisions to be based only on the supplied article and candidates. |
|
|
| ## Required Application Components |
|
|
| The MVP should use modular components with clear responsibilities. |
|
|
| Expected component areas include: |
|
|
| * configuration; |
| * vocabulary loading; |
| * canonical vocabulary indexing; |
| * article loading and validation; |
| * model abstraction; |
| * structured model schemas; |
| * Topic routing; |
| * Term routing; |
| * Variable-level classification; |
| * controlled hierarchy traversal; |
| * redundancy removal; |
| * deterministic validation; |
| * batch orchestration; |
| * persistence and caching; |
| * output generation; |
| * logging; and |
| * Gradio presentation. |
|
|
| Do not combine all logic in a single application file. |
|
|
| The Gradio interface must call application services rather than contain classification logic. |
|
|
| ## Model Abstraction |
|
|
| Model-specific implementation must be isolated behind a common interface. |
|
|
| The model interface should support: |
|
|
| * configurable provider and model name; |
| * configurable model parameters; |
| * structured input; |
| * structured output; |
| * schema validation; |
| * retries; |
| * timeout handling; |
| * token usage reporting; |
| * cost reporting when available; and |
| * prompt-version tracking. |
|
|
| Do not hard-code a permanent model name in classification components. |
|
|
| Model configuration must be loaded from configuration files, environment variables, or typed settings. |
|
|
| ## Structured Model Responses |
|
|
| Use Pydantic models or equivalent typed schemas for all model responses. |
|
|
| Model outputs must be validated before use. |
|
|
| A structured response may contain: |
|
|
| * selected candidate IDs; |
| * confidence signals; |
| * supporting evidence; |
| * support type; |
| * ambiguous alternatives; |
| * reason for stopping; and |
| * branch continuation or stopping decision. |
|
|
| Invalid structured output must produce an explicit error or retry. |
|
|
| Do not parse critical classification decisions from free-form prose when structured output is available. |
|
|
| ## Deterministic Validation |
|
|
| Every proposed final classification must pass deterministic validation. |
|
|
| Validation must confirm that: |
|
|
| * the UUID exists; |
| * the concept name matches the UUID; |
| * the hierarchy level is correct; |
| * the canonical path is correct; |
| * every parentβchild relationship is valid; |
| * the concept belongs beneath the selected Topic and Term; |
| * the selected node is assignable; and |
| * no path component was invented or altered. |
|
|
| Deterministic validation verifies vocabulary integrity only. |
|
|
| It does not prove that the article scientifically supports the concept. |
|
|
| A candidate that fails deterministic validation must not appear as an accepted result. |
|
|
| ## Redundancy Rules |
|
|
| Do not return duplicate UUIDs or duplicate canonical paths. |
|
|
| When both an ancestor and a supported descendant are selected in the same branch, retain only the deepest final classification unless the ancestor represents an independent classification decision. |
|
|
| Ancestors should remain visible through `path_components`, not as redundant final assignments. |
|
|
| ## No-Classification Behavior |
|
|
| Returning no classification is a valid outcome. |
|
|
| Do not force a prediction when the title and abstract do not support a defensible GCMD concept. |
|
|
| A no-classification result must: |
|
|
| * use completed processing status when the workflow succeeded; |
| * contain an empty classifications list; and |
| * include a concise reason. |
|
|
| Do not treat no classification as a system failure. |
|
|
| ## Output Rules |
|
|
| The primary output format is JSON. |
|
|
| Output must preserve: |
|
|
| * `DOI`; |
| * `Title`; |
| * `Year`; |
| * `Abstract`; and |
| * original source values. |
|
|
| Each final classification should include: |
|
|
| * authoritative UUID; |
| * authoritative name; |
| * hierarchy level; |
| * canonical path; |
| * path components; |
| * Topic; |
| * Term when applicable; |
| * confidence signals; |
| * evidence; |
| * support type; |
| * reason for stopping; |
| * deterministic validation result; |
| * final status; and |
| * review flag when applicable. |
|
|
| Use the formal output schema defined by the project when available. |
|
|
| Examples in documentation are illustrative. The formal JSON Schema is authoritative for field names and enumerations. |
|
|
| ## Status Scope |
|
|
| Keep status fields separate by scope. |
|
|
| ### Article processing status |
|
|
| Use for workflow execution state: |
|
|
| * `completed`; |
| * `partial`; |
| * `failed`; or |
| * `skipped`. |
|
|
| ### Article classification outcome |
|
|
| Use for semantic article-level outcome: |
|
|
| * `classified`; |
| * `pending_review`; or |
| * `not_classified`. |
|
|
| ### Classification final status |
|
|
| Use for an individual candidate: |
|
|
| * `accepted`; |
| * `reduced_to_ancestor`; |
| * `review_required`; or |
| * `rejected`. |
|
|
| ### Review status |
|
|
| Use for human-review state: |
|
|
| * `not_required`; |
| * `pending`; or |
| * `completed`. |
|
|
| Do not use one status field to represent multiple scopes. |
|
|
| ## Naming Conventions |
|
|
| Preserve source article field names exactly: |
|
|
| * `DOI`; |
| * `Title`; |
| * `Year`; |
| * `Abstract`. |
|
|
| Use `UUID` for the authoritative UUID stored on a serialized GCMD concept record. |
|
|
| Use snake_case for generated fields, including: |
| |
| * `parent_uuid`; |
| * `child_uuids`; |
| * `deepest_supported_uuid`; |
| * `final_uuid`; |
| * `canonical_path`; |
| * `path_components`; |
| * `processing_status`; |
| * `classification_outcome`; |
| * `review_status`; and |
| * `processing_metadata`. |
|
|
| Do not introduce multiple names for the same concept. |
|
|
| ## Persistence and Caching |
|
|
| Save article-level results incrementally. |
|
|
| Completed work must survive: |
|
|
| * process interruption; |
| * later article failures; |
| * model errors; and |
| * validation errors. |
|
|
| Caching must account for all inputs that can affect classification, including: |
|
|
| * article content or article fingerprint; |
| * vocabulary version or file hash; |
| * model name and parameters; |
| * prompt versions; |
| * thresholds; |
| * application version; and |
| * relevant configuration. |
|
|
| A reused cached result remains a completed result with `cache_used: true`. |
|
|
| Do not classify a cached article as skipped solely because the cache was used. |
|
|
| ## Logging |
|
|
| Logs must support debugging and reproducibility. |
|
|
| Record, when available: |
|
|
| * DOI; |
| * processing stage; |
| * selected candidates; |
| * model calls; |
| * retries; |
| * structured-output errors; |
| * deterministic validation failures; |
| * processing time; |
| * token usage; |
| * estimated cost; |
| * cache usage; and |
| * final outcome. |
|
|
| Do not expose: |
|
|
| * API keys; |
| * authentication tokens; |
| * protected environment values; or |
| * sensitive request headers. |
|
|
| Distinguish clearly among: |
|
|
| * model recommendations; |
| * deterministic validation results; |
| * automated decisions; and |
| * human-reviewed outcomes. |
|
|
| ## Error Handling |
|
|
| Do not silently convert failures into successful classifications. |
|
|
| Record explicit errors for: |
|
|
| * malformed hierarchy nodes; |
| * malformed article records; |
| * missing required fields; |
| * duplicate UUIDs; |
| * duplicate DOIs; |
| * model failures; |
| * timeouts; |
| * rate limits; |
| * structured-output failures; |
| * invalid candidate IDs; |
| * invalid hierarchy relationships; |
| * output-schema failures; and |
| * persistence failures. |
|
|
| Temporary failures may be retried according to configurable retry rules. |
|
|
| Retries must not create duplicate accepted results. |
|
|
| Failure of one article must not prevent remaining valid articles from being processed. |
|
|
| ## Testing Requirements |
|
|
| Core deterministic functions must be covered by automated tests. |
|
|
| At minimum, test: |
|
|
| * recursive traversal of variable-depth hierarchy branches; |
| * Topic, Term, and Variable-level nodes; |
| * assignable internal nodes; |
| * leaf nodes; |
| * UUID preservation; |
| * duplicate UUID detection; |
| * canonical path construction; |
| * parent lookup; |
| * direct-child lookup; |
| * Topic-to-Term lookup; |
| * Term-to-Variable lookup; |
| * optional definitions; |
| * malformed hierarchy records; |
| * article-schema validation; |
| * DOI uniqueness; |
| * structured response validation; |
| * deterministic vocabulary validation; |
| * redundancy removal; |
| * no-classification behavior; |
| * status handling; |
| * caching behavior; |
| * incremental persistence; |
| * output-schema validation; and |
| * source-file immutability. |
|
|
| Tests must not require live model API calls unless explicitly marked as integration tests. |
|
|
| Use model fakes or stubs for deterministic unit tests. |
|
|
| ## MVP Evaluation Baseline |
|
|
| Preserve `prototype/app_hf_poc.py` as the original baseline. |
|
|
| The MVP should later be compared with the proof of concept on: |
|
|
| * vocabulary-valid output rate; |
| * accepted-classification precision; |
| * Topic recall; |
| * exact-path accuracy; |
| * ancestor-aware correctness; |
| * unsupported descent rate; |
| * average classification depth; |
| * processing time; and |
| * model cost. |
|
|
| Do not modify the baseline in ways that invalidate comparison. |
|
|
| ## Repository Structure |
|
|
| Prefer a modular package structure similar to: |
|
|
| ```text |
| . |
| βββ AGENTS.md |
| βββ PROJECT_SPEC.md |
| βββ IMPLEMENTATION_PLAN.md |
| βββ MVP_PROGRESS.md |
| βββ README.md |
| βββ pyproject.toml |
| βββ .env.example |
| βββ app.py |
| βββ data/ |
| β βββ gcmd_hierarchy.json |
| β βββ articles.json |
| βββ prototype/ |
| β βββ app_hf_poc.py |
| βββ src/ |
| β βββ gcmd_classifier/ |
| β βββ config.py |
| β βββ models.py |
| β βββ vocabulary/ |
| β βββ articles/ |
| β βββ llm/ |
| β βββ classification/ |
| β βββ pipeline/ |
| β βββ persistence/ |
| β βββ ui/ |
| βββ schemas/ |
| βββ tests/ |
| ``` |
|
|
| The exact structure may be refined in `IMPLEMENTATION_PLAN.md`, but the implementation must remain modular. |
|
|
| ## Planning Before Implementation |
|
|
| For substantial tasks: |
|
|
| 1. read `PROJECT_SPEC.md`; |
| 2. read this `AGENTS.md`; |
| 3. inspect the relevant repository files; |
| 4. inspect the applicable section of `IMPLEMENTATION_PLAN.md`; |
| 5. identify assumptions or conflicts; |
| 6. implement only the requested milestone; and |
| 7. run the required tests. |
|
|
| Do not implement the entire MVP in one broad task. |
|
|
| Do not expand scope without explicit approval. |
|
|
| When asked to plan, do not modify implementation code unless explicitly instructed. |
|
|
| ## Milestone Discipline |
|
|
| Implement one approved milestone at a time. |
|
|
| For each milestone: |
|
|
| * identify applicable specification requirements; |
| * define acceptance criteria; |
| * implement only the milestone scope; |
| * add or update tests; |
| * run tests and static checks; |
| * update `MVP_PROGRESS.md`; |
| * report deviations from the plan; and |
| * stop before beginning the next milestone. |
|
|
| Do not automatically continue into later milestones. |
|
|
| ## Required Completion Report |
|
|
| At the end of every implementation task, report: |
|
|
| 1. files created, modified, or deleted; |
| 2. requirements implemented; |
| 3. important design decisions; |
| 4. test commands executed; |
| 5. test results; |
| 6. formatting or static-analysis results; |
| 7. whether source JSON files remained unchanged; |
| 8. deviations from `IMPLEMENTATION_PLAN.md`; |
| 9. known limitations; |
| 10. deferred work; and |
| 11. whether all requested acceptance criteria were satisfied. |
|
|
| Do not claim that a milestone is complete when required tests are failing. |
|
|
| ## Code Quality |
|
|
| Use: |
|
|
| * Python type hints; |
| * clear module boundaries; |
| * descriptive names; |
| * Pydantic or typed schemas; |
| * dependency injection where useful; |
| * configurable settings; |
| * explicit error types; |
| * concise docstrings; |
| * deterministic helper functions; and |
| * tests for nontrivial logic. |
|
|
| Avoid: |
|
|
| * monolithic application files; |
| * hard-coded vocabulary content; |
| * global mutable state; |
| * hidden exception handling; |
| * broad catch-all exceptions without logging; |
| * duplicated classification logic; |
| * unnecessary abstractions; |
| * premature optimization; and |
| * dependencies that are not justified by MVP requirements. |
|
|
| ## Hugging Face Compatibility |
|
|
| The final MVP must remain deployable as a Hugging Face Space. |
|
|
| The root-level `app.py` should contain only deployment and interface-launch code. |
|
|
| Business logic must remain under `src/gcmd_classifier/`. |
|
|
| Do not introduce local filesystem assumptions that are incompatible with Hugging Face Spaces. |
|
|
| Configuration and credentials must use environment variables or supported configuration files. |
|
|
| The Gradio interface must remain separate from the core classification pipeline. |
|
|
| ## Final Implementation Principle |
|
|
| Build the smallest tested system that proves the core research and engineering claim: |
|
|
| > Constrained direct-child classification through the GCMD hierarchy can produce valid recommendations at the deepest level supported by article evidence without forcing unsupported specificity. |
|
|
| Do not add complexity unless it supports this claim or is required by the approved MVP scope. |
|
|
|
|