Chorus
view release on metacpan or search on metacpan
agent/skills/chorus-import-project.md view on Meta::CPAN
if word_mode == "hybrid" and all_figure_descs:
annotated_descs, xref_index_block, xref_map = _xref_pass_word(
all_figure_descs, block_texts, find_text_occurrences_word)
else:
annotated_descs = all_figure_descs
xref_index_block = ""
xref_map = {}
# xref_map passed to Phase 3 as first-class matching candidates (same as PDF pipeline)
```
##### Step 3 â Assemble final output
XML order is the reading order â no Y-sort required. Append XREF INDEX at end.
```python
output_parts = [content for (_, content) in elements]
if xref_index_block:
output_parts.append(xref_index_block)
extracted_text = "\n\n".join(output_parts)
```
##### nohup gate (hybrid mode â Word)
If the document contains **⥠15 embedded images** â exit(2) + nohup command.
`CHORUS_WORD_FORCE=1` to bypass, identical to `chorus-pdf` nohup gate.
##### Figure-heavy domains warning (text mode)
When `word_mode == "text"` **and** ⥠5 images detected, emit the same prominent
warning as the PDF pipeline â Phase 3 will be blind to image content.
##### Dependencies
| Package | Install | Notes |
|---------|---------|-------|
| `python-docx` | `pip install python-docx` | DOCX extraction |
| `Pillow` | `pip install Pillow` | Image conversion (hybrid mode) |
> â **If extraction tools are absent** â warn and offer Case A (inline paste).
> Never block the workflow over a missing optional tool.
---
#### Other formats â LibreOffice universal fallback
For formats not natively handled (`.doc`, `.odt`, `.pptx`, `.ods`, `.rtf`):
```bash
libreoffice --headless --convert-to pdf "<fichier>" --outdir /tmp/
# â produces /tmp/<basename>.pdf â feed to PDF hybrid pipeline above
```
If LibreOffice is absent â ask the engineer to provide copy-pasted content (Case A).
Never block the workflow over a missing tool â offer the inline alternative.
---
## Phase 1 â Read the KB (canonical terminology)
### 1.0 Sandbox inventory (first tool call â token keepalive)
**Before reading any file**, read the directory tree $SANDBOX/ immediately.
This serves two purposes:
1. Acquires the full sandbox structure early (agents list, rules dirs, existing JSON/report files)
2. Ensures at least one tool call happens before any long reading+thinking cycle,
keeping the IDE token active from the very start.
Use this inventory to:
- Confirm the list of `<slug>.org` files to read in 1.2
- Know which `rules/<slug>/` directories exist (for the keepalive calls in 1.2)
- Detect `$SANDBOX/agent/thesaurus.org` if present (for 1.2b â highest priority source)
- Detect any existing `import-report-*.org` files (for 1.3 â secondary memory)
### 1.1 Pipeline Index
Read `$SANDBOX/agent/chorus/index.org`:
- Namespace + agent list (slug, pos)
- Global slot dictionary (if present in the index)
### 1.2 Per-agent terminology
For each agent, apply this two-step sequence:
1. **Read** `$SANDBOX/agent/chorus/<slug>.org` and extract:
| KB Section | What we extract |
|---|---|
| `Ontologie` | Domain concepts, synonyms, relationships (e.g. "entrait" = horizontal truss beam) |
| `Catalogue des Frames` | Exact types (`type_element`), mandatory slots per type |
| `Dictionnaire des slots` | Canonical names, value types, units, allowed domains |
2. **Immediately after** (no thinking between the two calls): read the directory tree $SANDBOX/rules/<slug>/
to list the rule files for this agent.
> **Why the immediate tool call:** Opus extended thinking after reading a dense KB file
> can be long enough to expire the IDE token. Reading the directory tree right after
> each read resets the token TTL and produces a useful rules inventory at no extra cost.
Build an internal **terminology reference**:
```
concept_kb â type_element / slot_kb unit_kb domain
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
montant porteur â montant_porteur â â
lisse â lisse_basse / lisse_haute â to clarify
classe résistance â classe_bois â C14/C16/C18/C24/C30
épaisseur isolant â epaisseur_mm mm positive integer
conductivité λ â classe_conductivite â "031"/"035"/"040"
hauteur libre â hauteur_libre_m m decimal
section â section_bois â "BxH" ex. "45x145"
```
### 1.2b Sandbox thesaurus (highest priority source)
If `$SANDBOX/agent/thesaurus.org` exists, **read it immediately after Phase 1.2**,
before any import-report.
The thesaurus is the **canonical project-terminology memory** for this sandbox. It is
separated from the normative KB (`<slug>.org`) and from import reports: it stores
project-specific synonyms validated by the engineer across all previous imports.
**Priority rule:**
```
thesaurus.org (1.2b) > import-report-*.org (1.3) > KB aliases (1.2)
```
A mapping present in the thesaurus is applied **at â
confidence without asking the
engineer again**, regardless of what the KB or previous import-reports say.
#### Thesaurus format
agent/skills/chorus-import-project.md view on Meta::CPAN
* Pending â to confirm on next import
Terms provisionally mapped (â ï¸) in a previous import, not yet confirmed by the engineer.
Re-raised on next import if the same term appears â engineer decision upgrades to â
or rejects.
| Project term | Proposed KB mapping | Flag | Source import |
|---|---|---|---|
| isolant soufflé | type_element: isolant_vrac ? | â ï¸ _a_confirmer | import-report-003 |
* Out-of-scope terms (â¬)
Terms explicitly identified as outside this sandbox's KB scope.
Silently excluded on future imports â not re-raised to the engineer.
| Project term | Reason | Recommended sandbox | Last seen |
|---|---|---|---|
| bardage zinc | hors périmètre sandbox-structurel | sandbox-bardage | import-report-001 |
```
#### How the thesaurus is used in Phase 3
When building the alignment table (Phase 3), **check the thesaurus first** for every
term in the raw inventory:
```
For each project term T:
1. Look up T in thesaurus â Aliases type_element : hit â apply â
, skip KB lookup
2. Look up T in thesaurus â Aliases slot values : hit â apply â
, skip KB lookup
3. Look up T in thesaurus â Out-of-scope : hit â mark â¬, skip KB lookup
4. Look up T in thesaurus â Pending : hit â re-raise â ï¸ to engineer
5. Not in thesaurus â proceed with KB lookup (Phase 3 standard flow)
```
> **Rule:** a thesaurus hit at step 1â3 is **final** â do not re-ask the engineer,
> do not consult the KB, do not propose alternatives. The engineer already decided.
>
> A thesaurus hit at step 4 (Pending) re-raises the question exactly once. If the
> engineer confirms â move the entry to Aliases and record â
. If rejected â move to
> Out-of-scope and record â¬.
#### Thesaurus initialisation
If `thesaurus.org` does not yet exist, it is created automatically at the end of the
first import that produces at least one â
or â ï¸ alignment (Phase 6 â see below).
No manual creation is required.
---
### 1.3 Previous alignment decisions
If `$SANDBOX/agent/import-report-*.org` exists, read the **latest report** as a
secondary memory source â complementary to the thesaurus, not a substitute.
- Retrieve mappings not yet promoted to the thesaurus â reapply without asking
- Retrieve pending questions not yet in thesaurus â re-raise if the same terms reappear
- **Skip any entry already covered by thesaurus.org** (1.2b takes priority)
---
## Phase 2 â Raw Inventory of Project Elements
### Keepalive checkpoint (token refresh before long thinking phases)
**Before starting the inventory**, if the source is a filesystem file, call:
```bash
wc -l "<fichier-source-extrait>"
```
or, if working from inline/already-extracted text, read the directoy tree $SANDBOX/agent/
to confirm the report directory.
> **Why:** Phases 2, 3 and 4 are pure thinking phases with no tool calls.
> On a complex project (many element types, many ambiguous terms), the combined
> thinking time across these three phases can expire the IDE token before Phase 5
> triggers the next tool call (JSON write). This checkpoint resets the TTL just
> before entering the silent zone.
Scan the source data and produce a **raw inventory**:
an uninterpreted list of what the engineer has provided.
```
Source line / cell Term identified Associated values
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
"Poteau porteur 45Ã145 C24" "poteau porteur" dim=45Ã145, classe=C24
"h libre 2,5m, entraxe 40cm" "h libre" 2.5m / "entraxe"=40cm
"Laine de verre λ035, e=20cm" "laine de verre" λ=0.035, e=200mm
"panneau OSB 12mm, CE" "panneau OSB" ep=12mm, CE=oui
```
> **Rule:** do not map at this stage â inventory first, align later.
> Preserve the original source text in the inventory for traceability.
---
## Phase 3 â Terminology Alignment
### KB Coverage Gauge (pre-alignment check)
**Before starting the term-by-term alignment**, compute a coverage indicator from the
raw inventory (Phase 2) against the KB reference (Phase 1.2):
```
ð KB Coverage Gauge
Distinct types detected in inventory : N (e.g. 8)
Types recognised in KB : n / N (e.g. 5 / 8 = 62%)
Critical slots covered : n / total (e.g. 11 / 17 = 65%)
KB Aliases section present : yes / no
```
| Coverage | Level | Action |
|---|---|---|
| ⥠80% types + ⥠80% critical slots | ð¢ Good | Proceed directly |
| 60â79% on either axis | ð¡ Moderate | Proceed with a warning â flag `_couverture_kb: moderate` in the JSON `_import` block |
| < 60% on either axis | ð´ Low | Emit the warning below and ask whether to continue |
**ð´ Low-coverage warning (display before alignment):**
```
â ï¸ KB Coverage Gauge â LOW COVERAGE DETECTED
Types recognised : n/N (XX%)
Critical slots : n/N (XX%)
The KB may lack aliases for the project's terminology.
( run in 1.220 second using v1.01-cache-2.11-cpan-14f38c9f855 )