citesense 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. citesense-1.0.0/PKG-INFO +279 -0
  2. citesense-1.0.0/README.md +270 -0
  3. citesense-1.0.0/pyproject.toml +37 -0
  4. citesense-1.0.0/setup.cfg +4 -0
  5. citesense-1.0.0/skills/audit-orchestrator/scripts/__init__.py +1 -0
  6. citesense-1.0.0/skills/audit-orchestrator/scripts/compare_reports.py +238 -0
  7. citesense-1.0.0/skills/audit-orchestrator/scripts/compose_report.py +395 -0
  8. citesense-1.0.0/skills/audit-orchestrator/scripts/fix_snippets.py +479 -0
  9. citesense-1.0.0/skills/audit-orchestrator/scripts/proactive_recommendations.py +241 -0
  10. citesense-1.0.0/skills/audit-orchestrator/scripts/report_io.py +65 -0
  11. citesense-1.0.0/skills/audit-orchestrator/scripts/run_audit.py +296 -0
  12. citesense-1.0.0/skills/audit-orchestrator/scripts/scored.py +164 -0
  13. citesense-1.0.0/skills/citation-simulator/scripts/__init__.py +1 -0
  14. citesense-1.0.0/skills/citation-simulator/scripts/generate_queries.py +371 -0
  15. citesense-1.0.0/skills/crawl-render-audit/scripts/__init__.py +1 -0
  16. citesense-1.0.0/skills/crawl-render-audit/scripts/audit_common.py +322 -0
  17. citesense-1.0.0/skills/crawl-render-audit/scripts/crawlability_check.py +230 -0
  18. citesense-1.0.0/skills/crawl-render-audit/scripts/models.py +190 -0
  19. citesense-1.0.0/skills/crawl-render-audit/scripts/render_and_data_scan.py +421 -0
  20. citesense-1.0.0/skills/crawl-render-audit/scripts/site_inventory.py +911 -0
  21. citesense-1.0.0/skills/engagement-audit/scripts/__init__.py +1 -0
  22. citesense-1.0.0/skills/engagement-audit/scripts/engagement_scan.py +402 -0
  23. citesense-1.0.0/skills/freshness-corroboration/scripts/__init__.py +1 -0
  24. citesense-1.0.0/skills/freshness-corroboration/scripts/freshness_and_consistency_scan.py +214 -0
  25. citesense-1.0.0/skills/trust-corroboration-graph/scripts/__init__.py +1 -0
  26. citesense-1.0.0/skills/trust-corroboration-graph/scripts/corroboration_scorer.py +283 -0
  27. citesense-1.0.0/src/citesense/__init__.py +6 -0
  28. citesense-1.0.0/src/citesense/__main__.py +5 -0
  29. citesense-1.0.0/src/citesense/_marketplace/__init__.py +1 -0
  30. citesense-1.0.0/src/citesense/api.py +64 -0
  31. citesense-1.0.0/src/citesense/cli.py +11 -0
  32. citesense-1.0.0/src/citesense.egg-info/PKG-INFO +279 -0
  33. citesense-1.0.0/src/citesense.egg-info/SOURCES.txt +47 -0
  34. citesense-1.0.0/src/citesense.egg-info/dependency_links.txt +1 -0
  35. citesense-1.0.0/src/citesense.egg-info/entry_points.txt +2 -0
  36. citesense-1.0.0/src/citesense.egg-info/top_level.txt +1 -0
  37. citesense-1.0.0/tests/test_adversarial_false_positives.py +132 -0
  38. citesense-1.0.0/tests/test_citability_score.py +176 -0
  39. citesense-1.0.0/tests/test_compare_reports.py +256 -0
  40. citesense-1.0.0/tests/test_fix_snippets.py +373 -0
  41. citesense-1.0.0/tests/test_marketplace.py +54 -0
  42. citesense-1.0.0/tests/test_new_checks.py +192 -0
  43. citesense-1.0.0/tests/test_origin_and_shell.py +93 -0
  44. citesense-1.0.0/tests/test_package.py +34 -0
  45. citesense-1.0.0/tests/test_proactive_and_crawler_class.py +168 -0
  46. citesense-1.0.0/tests/test_quality_fixtures.py +218 -0
  47. citesense-1.0.0/tests/test_regressions.py +389 -0
  48. citesense-1.0.0/tests/test_report_io.py +144 -0
  49. citesense-1.0.0/tests/test_site_inventory.py +105 -0
@@ -0,0 +1,279 @@
1
+ Metadata-Version: 2.4
2
+ Name: citesense
3
+ Version: 1.0.0
4
+ Summary: Evidence-backed AI discoverability and on-site engagement audits.
5
+ Author: CiteSense
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+
10
+ # CiteSense
11
+
12
+ An Agent Skill Marketplace that audits a website for AI-discoverability and on-site-engagement
13
+ problems and produces a structured report of evidence-backed findings with prioritized fixes.
14
+ Built for Adobe University Hackathon 2026, Round 3.
15
+
16
+ Marketplace name `citesense`, entrypoint `audit-orchestrator`, six skills. The manifest name,
17
+ this README and the repository directory all use the same identity, so the zip root, the manifest
18
+ and the docs agree.
19
+
20
+ ## Installable package
21
+
22
+ Install CiteSense from the repository root in a clean Python environment:
23
+
24
+ ```bash
25
+ python -m pip install .
26
+ ```
27
+
28
+ Run the same single-entrypoint audit through the installed console command:
29
+
30
+ ```bash
31
+ citesense https://example.com --output report.json
32
+ ```
33
+
34
+ The package exposes the existing orchestrator without duplicating its engine:
35
+
36
+ ```python
37
+ from citesense import run_full_audit
38
+
39
+ report = run_full_audit("https://example.com", max_pages=5, timeout=8)
40
+ print(report["summary"])
41
+ ```
42
+
43
+ The package remains read-only, enforces `robots.txt`, uses bounded crawling, and never
44
+ bypasses CAPTCHA, WAF, login, or anti-bot protections.
45
+
46
+ ## Quickstart (30 seconds to a structured report)
47
+
48
+ No dependencies to install — the entire marketplace runs on the Python standard library.
49
+
50
+ ```bash
51
+ # Audit any site (writes report.json)
52
+ python skills/audit-orchestrator/scripts/run_audit.py https://www.python.org --output report.json
53
+ ```
54
+
55
+ That's the whole loop: point it at a URL and get a structured report. A typical audit finishes
56
+ in 5-20 seconds, well under the 5-minute budget.
57
+
58
+ Prefer to see output without running anything? Pre-generated reports for ten real sites live in
59
+ [`validation-runs/`](validation-runs/), with severity counts and runtimes in
60
+ [`validation-runs/RUNS.md`](validation-runs/RUNS.md).
61
+
62
+ ## Documentation
63
+
64
+ - [Case study: the site that passes its checks and is still invisible](docs/CASE-STUDY.md)
65
+
66
+ ---
67
+
68
+ ## Entrypoint
69
+ `skills/audit-orchestrator` is the single entrypoint that orchestrates the audit.
70
+ See `marketplace.json` for the full marketplace manifest.
71
+
72
+ ## Project structure
73
+
74
+ ```text
75
+ src/citesense/ # Public Python API and console adapter
76
+ skills/ # Marketplace skills and the single audit entrypoint
77
+ marketplace.json # Marketplace manifest (one entrypoint)
78
+ tests/ # Unit, regression, package, and marketplace tests
79
+ pyproject.toml # Install/build metadata
80
+ ```
81
+
82
+ ## Architecture & Skills
83
+
84
+ ```mermaid
85
+ graph TD
86
+ User([Audit Request: URL]) --> Orchestrator[skills/audit-orchestrator]
87
+ Orchestrator --> SiteInventory[Shared SiteInventory Crawler]
88
+ SiteInventory -->|Single Bounded Crawl| Snapshots[(Cached Page Snapshots & Ground Truth)]
89
+
90
+ Snapshots --> Skill1[crawl-render-audit]
91
+ Snapshots --> Skill2[freshness-corroboration]
92
+ Snapshots --> Skill3[engagement-audit]
93
+ Snapshots --> Orchestrator2[Orchestrator derives ground truth]
94
+ Orchestrator2 --> Skill4[trust-corroboration-graph]
95
+ Orchestrator2 --> Skill5[citation-simulator]
96
+
97
+ Skill1 -->|CandidateFindings + Evidence| Dedup[Root-Cause Deduplication & Impact Prioritization]
98
+ Skill2 -->|CandidateFindings + Evidence| Dedup
99
+ Skill3 -->|CandidateFindings + Evidence| Dedup
100
+ Skill4 -->|CandidateFindings + Evidence| Dedup
101
+ Skill5 -->|CandidateFindings + Evidence| Dedup
102
+
103
+ Dedup --> Validator[Schema Validator & ID Assigner]
104
+ Validator --> FinalReport[report.json]
105
+ ```
106
+
107
+ | Skill | Concern | What it adds |
108
+ |---|---|---|
109
+ | **crawl-render-audit** | Off-site discoverability, steps A-C | Is the crawler let in? Scored **by crawler class** -- blocking training crawlers (GPTBot, ClaudeBot) costs no citations and is a legitimate licensing stance; blocking search-index (OAI-SearchBot, Claude-SearchBot, PerplexityBot) or user-triggered (ChatGPT-User, Claude-User) agents is what makes a brand uncitable. Can it read the page without executing JS? Is structured data present and valid? Are facts locked inside images or canvas? |
110
+ | **freshness-corroboration** | Temporal + internal consistency (Appendix D, half 1) | Claim-based freshness: detects actual stale/conflicting facts (e.g. conflicting founding years, expired promotions) instead of treating missing `dateModified` as a defect. |
111
+ | **engagement-audit** | On-site engagement | Evaluates orientation, buttons/forms/CTAs, navigation, redirect-aware broken links, and mobile viewport. |
112
+ | **citation-simulator** | Proof-of-failure | Generates realistic questions about the brand, then tests **answerability**: given only the pages a retrieval bot actually fetched, could an assistant quote an answer? Also classifies supplied live-search results (omission / misattribution / staleness / contradiction) when an agent provides them. |
113
+ | **trust-corroboration-graph** | External identity (Appendix D, half 2) | Observable on-site: does any machine-readable path exist from the brand to an independent authority (`sameAs` URIs, outbound links to Wikidata/Wikipedia/Crunchbase/LinkedIn/registries)? Agent-supplied: scores real third-party corroboration and same-name collision risk. |
114
+ | **audit-orchestrator** (entrypoint) | Composition & Orchestration | Crawls pages once via `SiteInventory`, executes specialist skills to collect `CandidateFindings`, merges and deduplicates by root cause, prioritizes by severity and impact, adds proactive recommendations, and validates the report. |
115
+
116
+ ---
117
+
118
+ ## Key Features & Improvements
119
+
120
+ 1. **Shared SiteInventory:** Pages are crawled once in a bounded sequential pass (default 5 pages: root, money page, content page, docs/about page), gated by robots.txt. `crawl-render-audit`, `freshness-corroboration` and `engagement-audit` read the exact same cached snapshots, eliminating redundant network calls. `citation-simulator` and `trust-corroboration-graph` derive their inputs from those same snapshots via the orchestrator.
121
+ 2. **Structured CandidateFindings Contract:** Every specialist skill generates standardized `CandidateFinding` objects directly with concrete evidence and suggested fixes. The orchestrator never invents or hardcodes findings, and no check claims an observation it did not make -- checks that would require live third-party search are exposed through the standalone skill CLIs for agent-driven runs, not simulated in the deterministic pipeline.
122
+ 3. **Evidence-Verification Layer:** Every finding includes URL, observation, method, timestamp, and confidence rating (`Observed at <url> via <method> [<timestamp>]: <observation> (Confidence: <confidence>)`).
123
+ 4. **Finding Metadata:** Includes `status` (`confirmed` / `likely-risk` / `proactive`), `confidence` (`high` / `medium` / `low`), and `impact` (`critical` / `high` / `medium` / `low`).
124
+ 5. **False-Positive Elimination:**
125
+ - Follows HTTP redirects up to 5 hops; links redirecting to 200 are recognized as working.
126
+ - 4xx/5xx responses are distinguished from transient network timeouts.
127
+ - Missing `dateModified` or `datePublished` on static pages is **not** penalized.
128
+ - Breadcrumbs are only evaluated on deep paths (`depth >= 2`), not on root/shallow pages.
129
+ - JavaScript usage alone is **not** a defect if raw HTML contains the core facts.
130
+ - Entity collisions are only flagged if plausible in the same/adjacent industry without `sameAs` disambiguation.
131
+ 6. **Fact-Extractability Detection:** Analyzes the **raw, non-JS-executed HTML** for crucial facts (identity, offering, pricing, contact) -- exactly what a non-rendering retrieval bot sees -- and flags pages whose facts are absent from it or locked inside `<canvas>`. No headless browser is used: the audit is deliberately static, which is the harsher and more realistic case for AI crawlers.
132
+ 7. **Advanced Engagement Detection:** Recognizes `<button>`, `<input type="submit">`, `<form>`, `role="button"`, and prominent CTA links.
133
+ 8. **Root-Cause Deduplication:** Consolidates findings sharing the same fingerprint across pages and skills, merging evidence and assigning highest severity.
134
+ 9. **Evidence-Based Proactive Recommendations:** Up to 6 beyond-defect suggestions derived from what the crawl observed and ordered strongest-evidence-first -- FAQPage markup for existing Q&A content, third-party entity anchoring, answer-first content structure, Article/WebSite/BreadcrumbList schema, explicit AI usage terms in robots.txt, an agent-facing NLWeb/MCP endpoint, and llms.txt reported with its real (weak) evidence base. Each fires only on an observed condition, so a well-optimised site correctly receives fewer. Basis: `skills/audit-orchestrator/references/ai-visibility-standards-2026.md`.
135
+ 10. **Strict Guardrails:** Recommend-only, 100% read-only, and robots.txt is **enforced on our own fetches** (`SiteInventory.may_fetch()` gates both page crawling and link probing against the `*` group; declined URLs are recorded in `skipped_by_robots`). Strictly budgeted under 5 minutes -- a typical audit runs in 2-20 seconds.
136
+ 11. **Access Classification:** Distinguishes readable pages, robots-disallowed paths, HTTP blocks, anti-bot challenges, network failures, empty responses, and undecodable content. Evidence-dependent findings and scores are withheld when no page was readable; protections are never bypassed.
137
+ 12. **Report Schema Compliance:** Fully conforms to `skills/audit-orchestrator/references/report-schema.json`.
138
+ 13. **Auto-Generated Fix Snippets:** Structured-data findings carry a ready-to-paste JSON-LD block pre-populated from observed ground truth. Unknown values are explicit `REPLACE_WITH_...` markers, and a snippet that would be mostly placeholders is **suppressed** rather than shipped as a fix.
139
+ 14. **Report Comparison:** Diffs two reports by stable `fingerprint` into `resolved` / `new` / `unchanged` buckets with a weighted `score_delta`, so "did the fix work?" is answerable.
140
+ 15. **AI-Citability Score:** A deterministic, monotonic 0-100 score in `summary.citability_score`, with its formula and rationale documented in `references/citability-score.md` rather than hidden in code.
141
+
142
+ ---
143
+
144
+ ## Running the Audit
145
+
146
+ ### 1. End-to-End Orchestrator CLI
147
+ To run a complete audit against any website:
148
+ ```bash
149
+ python skills/audit-orchestrator/scripts/run_audit.py https://example.com --output report.json
150
+ ```
151
+
152
+ ### 2. Standalone Skill CLI
153
+ Each specialist script can also be executed independently:
154
+ ```bash
155
+ # 1. Crawlability & Robots Audit
156
+ python skills/crawl-render-audit/scripts/crawlability_check.py https://example.com
157
+
158
+ # 2. Render & Schema Scan
159
+ python skills/crawl-render-audit/scripts/render_and_data_scan.py https://example.com
160
+
161
+ # 3. Freshness & Consistency Scan
162
+ python skills/freshness-corroboration/scripts/freshness_and_consistency_scan.py https://example.com
163
+
164
+ # 4. Engagement Audit
165
+ python skills/engagement-audit/scripts/engagement_scan.py https://example.com
166
+
167
+ # 5. Citation answerability (needs a saved inventory)
168
+ python skills/audit-orchestrator/scripts/run_audit.py https://example.com --save-inventory inv.json -o report.json
169
+ python skills/citation-simulator/scripts/generate_queries.py inv.json
170
+
171
+ # 6. Trust / corroboration scoring (agent supplies real third-party search results)
172
+ python skills/trust-corroboration-graph/scripts/corroboration_scorer.py '{"brand_name":"Acme","site_url":"https://example.com","facts":[],"name_collisions_found":[],"disambiguating_markers_present":{}}' --findings-only
173
+
174
+ # 7. Report Merge & Validation
175
+ python skills/audit-orchestrator/scripts/compose_report.py validate --input report.json
176
+
177
+ # 7. Report Comparison / Diff (before vs. after a fix, or two points in time)
178
+ # Matches findings by fingerprint (falling back to normalized title + category) and
179
+ # buckets them into resolved / new / unchanged, with a weighted score_delta.
180
+ python skills/audit-orchestrator/scripts/compare_reports.py before.json after.json --output diff.json
181
+
182
+ # 8. AI-Citability Score (recompute + show the arithmetic for any existing report)
183
+ python skills/audit-orchestrator/scripts/scored.py report.json --explain
184
+
185
+ # 9. Fix-Snippet Inspector
186
+ # Shows, per structured-data finding, whether a JSON-LD snippet could be generated and
187
+ # WHY NOT when it could not. Needs --inventory: report.json alone carries no ground
188
+ # truth, and this tool will not fabricate one.
189
+ python skills/audit-orchestrator/scripts/fix_snippets.py report.json \
190
+ --inventory inventory.json --output annotated-report.json
191
+ ```
192
+
193
+ All three report-consuming CLIs fail readably rather than with a traceback — a missing file,
194
+ malformed JSON, or a non-object JSON document produces a one-line `error:` on stderr and
195
+ exit code 1 — and `--output` creates its parent directory if it does not exist.
196
+
197
+ ### What shows up inside the report
198
+ Two additive fields are produced automatically during composition. Both are **optional** in
199
+ `references/report-schema.json` — existing consumers are unaffected.
200
+
201
+ **`summary.citability_score`** — a 0-100 AI-Citability Score written on every composed
202
+ report (`run_audit.py` and `compose_report.py merge`). Starts at 100 and subtracts a
203
+ per-finding severity penalty (critical 25 / high 12 / medium 5 / low 2), with a small,
204
+ data-gated corroboration credit. The exact formula, worked example, and rationale live in
205
+ [`skills/audit-orchestrator/references/citability-score.md`](skills/audit-orchestrator/references/citability-score.md).
206
+
207
+ ```json
208
+ "summary": { "total_findings": 7, "critical": 0, "high": 1, "citability_score": 64 }
209
+ ```
210
+
211
+ **`suggested_action.fix_snippet`** — a ready-to-paste JSON-LD block on structured-data
212
+ findings, pre-populated from data the crawl actually observed (brand name, `sameAs`,
213
+ founding year, page H1, real URL path). It appears only when the audit holds enough real
214
+ data to fill the entity's identifying fields; genuinely unknown values are emitted as
215
+ explicit `REPLACE_WITH_...` markers, and a snippet that would be mostly placeholders is
216
+ suppressed rather than presented as a fix.
217
+
218
+ ```json
219
+ "suggested_action": {
220
+ "summary": "Add Organization JSON-LD markup to the homepage.",
221
+ "priority": "medium",
222
+ "how_to_fix": "Add a JSON-LD script declaring @type 'Organization'...",
223
+ "fix_snippet": "<script type=\"application/ld+json\">\n{\n \"@type\": \"Organization\",\n \"name\": \"Mozilla\",\n \"foundingDate\": \"1998\",\n \"logo\": \"REPLACE_WITH_YOUR_LOGO_URL\"\n}\n</script>"
224
+ }
225
+ ```
226
+
227
+ **Evidence and assessment metadata** — findings carry stable `evidence_refs` pointing to
228
+ structured observations in the top-level `evidence_ledger`. Reports also include `assessments`
229
+ for checks that passed or were `inconclusive`/`not-assessed` because access or evidence was
230
+ unavailable. These statuses are deliberately separate from findings, so a blocked or
231
+ anti-bot-protected page is not reported as if its content were missing.
232
+
233
+ Snippets need the crawl's ground truth. `run_audit.py` supplies it automatically; when
234
+ merging findings by hand, pass a saved inventory (or a bare `ground_truth` JSON):
235
+
236
+ ```bash
237
+ python skills/audit-orchestrator/scripts/run_audit.py https://example.com \
238
+ --save-inventory inventory.json --output report.json
239
+
240
+ python skills/audit-orchestrator/scripts/compose_report.py merge \
241
+ --site https://example.com --input crawl_findings.json engagement_findings.json \
242
+ --inventory inventory.json --output report.json
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Running Tests
248
+
249
+ Run the complete unit, adversarial and regression suite:
250
+ ```bash
251
+ python -m unittest discover -s tests -v
252
+ ```
253
+ All tests run with the Python standard library and zero external dependencies.
254
+
255
+ `tests/test_regressions.py` locks in every false positive and guardrail bug that has been fixed
256
+ (gzip transport, copyright ranges, founding-claim prose, page-purpose classification, robots.txt
257
+ enforcement, evidence honesty, brand-name extraction). If one fails, a regression was
258
+ reintroduced -- see `Progress.md` for the original reproduction.
259
+
260
+ ## Validation runs
261
+
262
+ `validation-runs/` holds reports regenerated from the current pipeline across six sites of
263
+ different shapes, plus `RUNS.md` with runtimes and severity counts. All six validate against
264
+ `report-schema.json`.
265
+
266
+ ## Evidence basis
267
+
268
+ Detection severities and recommendation priorities trace to documented field research, not
269
+ intuition. `skills/audit-orchestrator/references/ai-visibility-standards-2026.md` records what
270
+ drives AI visibility as of September 2026 -- the three-way AI crawler taxonomy, why FAQPage is the
271
+ highest-leverage schema, the ~11% citation-source overlap between platforms that makes off-site
272
+ presence decisive, content-chunking effects on extractability, and an honest read on llms.txt
273
+ (major crawlers almost never request it; Google states it has no effect) -- with sources and a
274
+ table mapping each finding to its basis.
275
+
276
+ ## Project status
277
+
278
+ `Progress.md` is the working log: what has been fixed, how each fix was verified, and what is
279
+ still open. Read it before changing detection logic.
@@ -0,0 +1,270 @@
1
+ # CiteSense
2
+
3
+ An Agent Skill Marketplace that audits a website for AI-discoverability and on-site-engagement
4
+ problems and produces a structured report of evidence-backed findings with prioritized fixes.
5
+ Built for Adobe University Hackathon 2026, Round 3.
6
+
7
+ Marketplace name `citesense`, entrypoint `audit-orchestrator`, six skills. The manifest name,
8
+ this README and the repository directory all use the same identity, so the zip root, the manifest
9
+ and the docs agree.
10
+
11
+ ## Installable package
12
+
13
+ Install CiteSense from the repository root in a clean Python environment:
14
+
15
+ ```bash
16
+ python -m pip install .
17
+ ```
18
+
19
+ Run the same single-entrypoint audit through the installed console command:
20
+
21
+ ```bash
22
+ citesense https://example.com --output report.json
23
+ ```
24
+
25
+ The package exposes the existing orchestrator without duplicating its engine:
26
+
27
+ ```python
28
+ from citesense import run_full_audit
29
+
30
+ report = run_full_audit("https://example.com", max_pages=5, timeout=8)
31
+ print(report["summary"])
32
+ ```
33
+
34
+ The package remains read-only, enforces `robots.txt`, uses bounded crawling, and never
35
+ bypasses CAPTCHA, WAF, login, or anti-bot protections.
36
+
37
+ ## Quickstart (30 seconds to a structured report)
38
+
39
+ No dependencies to install — the entire marketplace runs on the Python standard library.
40
+
41
+ ```bash
42
+ # Audit any site (writes report.json)
43
+ python skills/audit-orchestrator/scripts/run_audit.py https://www.python.org --output report.json
44
+ ```
45
+
46
+ That's the whole loop: point it at a URL and get a structured report. A typical audit finishes
47
+ in 5-20 seconds, well under the 5-minute budget.
48
+
49
+ Prefer to see output without running anything? Pre-generated reports for ten real sites live in
50
+ [`validation-runs/`](validation-runs/), with severity counts and runtimes in
51
+ [`validation-runs/RUNS.md`](validation-runs/RUNS.md).
52
+
53
+ ## Documentation
54
+
55
+ - [Case study: the site that passes its checks and is still invisible](docs/CASE-STUDY.md)
56
+
57
+ ---
58
+
59
+ ## Entrypoint
60
+ `skills/audit-orchestrator` is the single entrypoint that orchestrates the audit.
61
+ See `marketplace.json` for the full marketplace manifest.
62
+
63
+ ## Project structure
64
+
65
+ ```text
66
+ src/citesense/ # Public Python API and console adapter
67
+ skills/ # Marketplace skills and the single audit entrypoint
68
+ marketplace.json # Marketplace manifest (one entrypoint)
69
+ tests/ # Unit, regression, package, and marketplace tests
70
+ pyproject.toml # Install/build metadata
71
+ ```
72
+
73
+ ## Architecture & Skills
74
+
75
+ ```mermaid
76
+ graph TD
77
+ User([Audit Request: URL]) --> Orchestrator[skills/audit-orchestrator]
78
+ Orchestrator --> SiteInventory[Shared SiteInventory Crawler]
79
+ SiteInventory -->|Single Bounded Crawl| Snapshots[(Cached Page Snapshots & Ground Truth)]
80
+
81
+ Snapshots --> Skill1[crawl-render-audit]
82
+ Snapshots --> Skill2[freshness-corroboration]
83
+ Snapshots --> Skill3[engagement-audit]
84
+ Snapshots --> Orchestrator2[Orchestrator derives ground truth]
85
+ Orchestrator2 --> Skill4[trust-corroboration-graph]
86
+ Orchestrator2 --> Skill5[citation-simulator]
87
+
88
+ Skill1 -->|CandidateFindings + Evidence| Dedup[Root-Cause Deduplication & Impact Prioritization]
89
+ Skill2 -->|CandidateFindings + Evidence| Dedup
90
+ Skill3 -->|CandidateFindings + Evidence| Dedup
91
+ Skill4 -->|CandidateFindings + Evidence| Dedup
92
+ Skill5 -->|CandidateFindings + Evidence| Dedup
93
+
94
+ Dedup --> Validator[Schema Validator & ID Assigner]
95
+ Validator --> FinalReport[report.json]
96
+ ```
97
+
98
+ | Skill | Concern | What it adds |
99
+ |---|---|---|
100
+ | **crawl-render-audit** | Off-site discoverability, steps A-C | Is the crawler let in? Scored **by crawler class** -- blocking training crawlers (GPTBot, ClaudeBot) costs no citations and is a legitimate licensing stance; blocking search-index (OAI-SearchBot, Claude-SearchBot, PerplexityBot) or user-triggered (ChatGPT-User, Claude-User) agents is what makes a brand uncitable. Can it read the page without executing JS? Is structured data present and valid? Are facts locked inside images or canvas? |
101
+ | **freshness-corroboration** | Temporal + internal consistency (Appendix D, half 1) | Claim-based freshness: detects actual stale/conflicting facts (e.g. conflicting founding years, expired promotions) instead of treating missing `dateModified` as a defect. |
102
+ | **engagement-audit** | On-site engagement | Evaluates orientation, buttons/forms/CTAs, navigation, redirect-aware broken links, and mobile viewport. |
103
+ | **citation-simulator** | Proof-of-failure | Generates realistic questions about the brand, then tests **answerability**: given only the pages a retrieval bot actually fetched, could an assistant quote an answer? Also classifies supplied live-search results (omission / misattribution / staleness / contradiction) when an agent provides them. |
104
+ | **trust-corroboration-graph** | External identity (Appendix D, half 2) | Observable on-site: does any machine-readable path exist from the brand to an independent authority (`sameAs` URIs, outbound links to Wikidata/Wikipedia/Crunchbase/LinkedIn/registries)? Agent-supplied: scores real third-party corroboration and same-name collision risk. |
105
+ | **audit-orchestrator** (entrypoint) | Composition & Orchestration | Crawls pages once via `SiteInventory`, executes specialist skills to collect `CandidateFindings`, merges and deduplicates by root cause, prioritizes by severity and impact, adds proactive recommendations, and validates the report. |
106
+
107
+ ---
108
+
109
+ ## Key Features & Improvements
110
+
111
+ 1. **Shared SiteInventory:** Pages are crawled once in a bounded sequential pass (default 5 pages: root, money page, content page, docs/about page), gated by robots.txt. `crawl-render-audit`, `freshness-corroboration` and `engagement-audit` read the exact same cached snapshots, eliminating redundant network calls. `citation-simulator` and `trust-corroboration-graph` derive their inputs from those same snapshots via the orchestrator.
112
+ 2. **Structured CandidateFindings Contract:** Every specialist skill generates standardized `CandidateFinding` objects directly with concrete evidence and suggested fixes. The orchestrator never invents or hardcodes findings, and no check claims an observation it did not make -- checks that would require live third-party search are exposed through the standalone skill CLIs for agent-driven runs, not simulated in the deterministic pipeline.
113
+ 3. **Evidence-Verification Layer:** Every finding includes URL, observation, method, timestamp, and confidence rating (`Observed at <url> via <method> [<timestamp>]: <observation> (Confidence: <confidence>)`).
114
+ 4. **Finding Metadata:** Includes `status` (`confirmed` / `likely-risk` / `proactive`), `confidence` (`high` / `medium` / `low`), and `impact` (`critical` / `high` / `medium` / `low`).
115
+ 5. **False-Positive Elimination:**
116
+ - Follows HTTP redirects up to 5 hops; links redirecting to 200 are recognized as working.
117
+ - 4xx/5xx responses are distinguished from transient network timeouts.
118
+ - Missing `dateModified` or `datePublished` on static pages is **not** penalized.
119
+ - Breadcrumbs are only evaluated on deep paths (`depth >= 2`), not on root/shallow pages.
120
+ - JavaScript usage alone is **not** a defect if raw HTML contains the core facts.
121
+ - Entity collisions are only flagged if plausible in the same/adjacent industry without `sameAs` disambiguation.
122
+ 6. **Fact-Extractability Detection:** Analyzes the **raw, non-JS-executed HTML** for crucial facts (identity, offering, pricing, contact) -- exactly what a non-rendering retrieval bot sees -- and flags pages whose facts are absent from it or locked inside `<canvas>`. No headless browser is used: the audit is deliberately static, which is the harsher and more realistic case for AI crawlers.
123
+ 7. **Advanced Engagement Detection:** Recognizes `<button>`, `<input type="submit">`, `<form>`, `role="button"`, and prominent CTA links.
124
+ 8. **Root-Cause Deduplication:** Consolidates findings sharing the same fingerprint across pages and skills, merging evidence and assigning highest severity.
125
+ 9. **Evidence-Based Proactive Recommendations:** Up to 6 beyond-defect suggestions derived from what the crawl observed and ordered strongest-evidence-first -- FAQPage markup for existing Q&A content, third-party entity anchoring, answer-first content structure, Article/WebSite/BreadcrumbList schema, explicit AI usage terms in robots.txt, an agent-facing NLWeb/MCP endpoint, and llms.txt reported with its real (weak) evidence base. Each fires only on an observed condition, so a well-optimised site correctly receives fewer. Basis: `skills/audit-orchestrator/references/ai-visibility-standards-2026.md`.
126
+ 10. **Strict Guardrails:** Recommend-only, 100% read-only, and robots.txt is **enforced on our own fetches** (`SiteInventory.may_fetch()` gates both page crawling and link probing against the `*` group; declined URLs are recorded in `skipped_by_robots`). Strictly budgeted under 5 minutes -- a typical audit runs in 2-20 seconds.
127
+ 11. **Access Classification:** Distinguishes readable pages, robots-disallowed paths, HTTP blocks, anti-bot challenges, network failures, empty responses, and undecodable content. Evidence-dependent findings and scores are withheld when no page was readable; protections are never bypassed.
128
+ 12. **Report Schema Compliance:** Fully conforms to `skills/audit-orchestrator/references/report-schema.json`.
129
+ 13. **Auto-Generated Fix Snippets:** Structured-data findings carry a ready-to-paste JSON-LD block pre-populated from observed ground truth. Unknown values are explicit `REPLACE_WITH_...` markers, and a snippet that would be mostly placeholders is **suppressed** rather than shipped as a fix.
130
+ 14. **Report Comparison:** Diffs two reports by stable `fingerprint` into `resolved` / `new` / `unchanged` buckets with a weighted `score_delta`, so "did the fix work?" is answerable.
131
+ 15. **AI-Citability Score:** A deterministic, monotonic 0-100 score in `summary.citability_score`, with its formula and rationale documented in `references/citability-score.md` rather than hidden in code.
132
+
133
+ ---
134
+
135
+ ## Running the Audit
136
+
137
+ ### 1. End-to-End Orchestrator CLI
138
+ To run a complete audit against any website:
139
+ ```bash
140
+ python skills/audit-orchestrator/scripts/run_audit.py https://example.com --output report.json
141
+ ```
142
+
143
+ ### 2. Standalone Skill CLI
144
+ Each specialist script can also be executed independently:
145
+ ```bash
146
+ # 1. Crawlability & Robots Audit
147
+ python skills/crawl-render-audit/scripts/crawlability_check.py https://example.com
148
+
149
+ # 2. Render & Schema Scan
150
+ python skills/crawl-render-audit/scripts/render_and_data_scan.py https://example.com
151
+
152
+ # 3. Freshness & Consistency Scan
153
+ python skills/freshness-corroboration/scripts/freshness_and_consistency_scan.py https://example.com
154
+
155
+ # 4. Engagement Audit
156
+ python skills/engagement-audit/scripts/engagement_scan.py https://example.com
157
+
158
+ # 5. Citation answerability (needs a saved inventory)
159
+ python skills/audit-orchestrator/scripts/run_audit.py https://example.com --save-inventory inv.json -o report.json
160
+ python skills/citation-simulator/scripts/generate_queries.py inv.json
161
+
162
+ # 6. Trust / corroboration scoring (agent supplies real third-party search results)
163
+ python skills/trust-corroboration-graph/scripts/corroboration_scorer.py '{"brand_name":"Acme","site_url":"https://example.com","facts":[],"name_collisions_found":[],"disambiguating_markers_present":{}}' --findings-only
164
+
165
+ # 7. Report Merge & Validation
166
+ python skills/audit-orchestrator/scripts/compose_report.py validate --input report.json
167
+
168
+ # 7. Report Comparison / Diff (before vs. after a fix, or two points in time)
169
+ # Matches findings by fingerprint (falling back to normalized title + category) and
170
+ # buckets them into resolved / new / unchanged, with a weighted score_delta.
171
+ python skills/audit-orchestrator/scripts/compare_reports.py before.json after.json --output diff.json
172
+
173
+ # 8. AI-Citability Score (recompute + show the arithmetic for any existing report)
174
+ python skills/audit-orchestrator/scripts/scored.py report.json --explain
175
+
176
+ # 9. Fix-Snippet Inspector
177
+ # Shows, per structured-data finding, whether a JSON-LD snippet could be generated and
178
+ # WHY NOT when it could not. Needs --inventory: report.json alone carries no ground
179
+ # truth, and this tool will not fabricate one.
180
+ python skills/audit-orchestrator/scripts/fix_snippets.py report.json \
181
+ --inventory inventory.json --output annotated-report.json
182
+ ```
183
+
184
+ All three report-consuming CLIs fail readably rather than with a traceback — a missing file,
185
+ malformed JSON, or a non-object JSON document produces a one-line `error:` on stderr and
186
+ exit code 1 — and `--output` creates its parent directory if it does not exist.
187
+
188
+ ### What shows up inside the report
189
+ Two additive fields are produced automatically during composition. Both are **optional** in
190
+ `references/report-schema.json` — existing consumers are unaffected.
191
+
192
+ **`summary.citability_score`** — a 0-100 AI-Citability Score written on every composed
193
+ report (`run_audit.py` and `compose_report.py merge`). Starts at 100 and subtracts a
194
+ per-finding severity penalty (critical 25 / high 12 / medium 5 / low 2), with a small,
195
+ data-gated corroboration credit. The exact formula, worked example, and rationale live in
196
+ [`skills/audit-orchestrator/references/citability-score.md`](skills/audit-orchestrator/references/citability-score.md).
197
+
198
+ ```json
199
+ "summary": { "total_findings": 7, "critical": 0, "high": 1, "citability_score": 64 }
200
+ ```
201
+
202
+ **`suggested_action.fix_snippet`** — a ready-to-paste JSON-LD block on structured-data
203
+ findings, pre-populated from data the crawl actually observed (brand name, `sameAs`,
204
+ founding year, page H1, real URL path). It appears only when the audit holds enough real
205
+ data to fill the entity's identifying fields; genuinely unknown values are emitted as
206
+ explicit `REPLACE_WITH_...` markers, and a snippet that would be mostly placeholders is
207
+ suppressed rather than presented as a fix.
208
+
209
+ ```json
210
+ "suggested_action": {
211
+ "summary": "Add Organization JSON-LD markup to the homepage.",
212
+ "priority": "medium",
213
+ "how_to_fix": "Add a JSON-LD script declaring @type 'Organization'...",
214
+ "fix_snippet": "<script type=\"application/ld+json\">\n{\n \"@type\": \"Organization\",\n \"name\": \"Mozilla\",\n \"foundingDate\": \"1998\",\n \"logo\": \"REPLACE_WITH_YOUR_LOGO_URL\"\n}\n</script>"
215
+ }
216
+ ```
217
+
218
+ **Evidence and assessment metadata** — findings carry stable `evidence_refs` pointing to
219
+ structured observations in the top-level `evidence_ledger`. Reports also include `assessments`
220
+ for checks that passed or were `inconclusive`/`not-assessed` because access or evidence was
221
+ unavailable. These statuses are deliberately separate from findings, so a blocked or
222
+ anti-bot-protected page is not reported as if its content were missing.
223
+
224
+ Snippets need the crawl's ground truth. `run_audit.py` supplies it automatically; when
225
+ merging findings by hand, pass a saved inventory (or a bare `ground_truth` JSON):
226
+
227
+ ```bash
228
+ python skills/audit-orchestrator/scripts/run_audit.py https://example.com \
229
+ --save-inventory inventory.json --output report.json
230
+
231
+ python skills/audit-orchestrator/scripts/compose_report.py merge \
232
+ --site https://example.com --input crawl_findings.json engagement_findings.json \
233
+ --inventory inventory.json --output report.json
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Running Tests
239
+
240
+ Run the complete unit, adversarial and regression suite:
241
+ ```bash
242
+ python -m unittest discover -s tests -v
243
+ ```
244
+ All tests run with the Python standard library and zero external dependencies.
245
+
246
+ `tests/test_regressions.py` locks in every false positive and guardrail bug that has been fixed
247
+ (gzip transport, copyright ranges, founding-claim prose, page-purpose classification, robots.txt
248
+ enforcement, evidence honesty, brand-name extraction). If one fails, a regression was
249
+ reintroduced -- see `Progress.md` for the original reproduction.
250
+
251
+ ## Validation runs
252
+
253
+ `validation-runs/` holds reports regenerated from the current pipeline across six sites of
254
+ different shapes, plus `RUNS.md` with runtimes and severity counts. All six validate against
255
+ `report-schema.json`.
256
+
257
+ ## Evidence basis
258
+
259
+ Detection severities and recommendation priorities trace to documented field research, not
260
+ intuition. `skills/audit-orchestrator/references/ai-visibility-standards-2026.md` records what
261
+ drives AI visibility as of September 2026 -- the three-way AI crawler taxonomy, why FAQPage is the
262
+ highest-leverage schema, the ~11% citation-source overlap between platforms that makes off-site
263
+ presence decisive, content-chunking effects on extractability, and an honest read on llms.txt
264
+ (major crawlers almost never request it; Google states it has no effect) -- with sources and a
265
+ table mapping each finding to its basis.
266
+
267
+ ## Project status
268
+
269
+ `Progress.md` is the working log: what has been fixed, how each fix was verified, and what is
270
+ still open. Read it before changing detection logic.
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "citesense"
7
+ version = "1.0.0"
8
+ description = "Evidence-backed AI discoverability and on-site engagement audits."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [{name = "CiteSense"}]
13
+ dependencies = []
14
+
15
+ [project.scripts]
16
+ citesense = "citesense.cli:main"
17
+
18
+ [tool.setuptools]
19
+ packages = [
20
+ "citesense",
21
+ "citesense._marketplace",
22
+ "citesense._marketplace.audit_orchestrator",
23
+ "citesense._marketplace.crawl_render_audit",
24
+ "citesense._marketplace.freshness_corroboration",
25
+ "citesense._marketplace.engagement_audit",
26
+ "citesense._marketplace.citation_simulator",
27
+ "citesense._marketplace.trust_corroboration_graph",
28
+ ]
29
+
30
+ [tool.setuptools.package-dir]
31
+ "" = "src"
32
+ "citesense._marketplace.audit_orchestrator" = "skills/audit-orchestrator/scripts"
33
+ "citesense._marketplace.crawl_render_audit" = "skills/crawl-render-audit/scripts"
34
+ "citesense._marketplace.freshness_corroboration" = "skills/freshness-corroboration/scripts"
35
+ "citesense._marketplace.engagement_audit" = "skills/engagement-audit/scripts"
36
+ "citesense._marketplace.citation_simulator" = "skills/citation-simulator/scripts"
37
+ "citesense._marketplace.trust_corroboration_graph" = "skills/trust-corroboration-graph/scripts"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """Audit orchestrator skill modules."""