pagegraph 0.6.1 → 0.7.0
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.
- package/README.md +164 -4
- package/dist/cli.js +1691 -623
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -309,6 +309,7 @@ pagegraph links verify <url> --assert-coverage # also assert seo.config.ts cove
|
|
|
309
309
|
pagegraph links verify <url> --emit-rendered <file> # save the rendered edge set
|
|
310
310
|
pagegraph links candidates # propose contextual links from the declared graph
|
|
311
311
|
pagegraph links decide <file> # answer typed link questions with Jev (TYPESAFE_API_KEY)
|
|
312
|
+
pagegraph decide <family> [<file>] # answer a decision batch with Jev (TYPESAFE_API_KEY)
|
|
312
313
|
pagegraph sitemap # print sitemap.xml
|
|
313
314
|
pagegraph robots # print robots.txt
|
|
314
315
|
```
|
|
@@ -408,13 +409,15 @@ pagegraph links candidates --decide
|
|
|
408
409
|
|
|
409
410
|
### Decide with Jev
|
|
410
411
|
|
|
411
|
-
`pagegraph links decide` answers
|
|
412
|
-
reason to link to the destination
|
|
413
|
-
|
|
412
|
+
`pagegraph links decide` answers four decisions per candidate — *does the source have a genuine
|
|
413
|
+
reason to link to the destination?*, *is descriptive anchor text already in the copy?*, *which
|
|
414
|
+
direction deserves the link?*, and *how relevant is it?* — and routes anything inside the confidence
|
|
415
|
+
band `(1−t, t)` to a `review` bucket instead of auto-applying. `--budget` (default 4) keeps only the
|
|
416
|
+
top-K candidates per source by relevance.
|
|
414
417
|
|
|
415
418
|
```bash
|
|
416
419
|
pagegraph links decide candidates.json --threshold 0.9
|
|
417
|
-
pagegraph links decide candidates.json --
|
|
420
|
+
pagegraph links decide candidates.json --budget 2 --json | jq
|
|
418
421
|
cat candidates.json | pagegraph links decide
|
|
419
422
|
```
|
|
420
423
|
|
|
@@ -424,6 +427,163 @@ is deliberately not a `seo.config.ts` field, so keys never live in the repo; `se
|
|
|
424
427
|
non-secret decision settings only. Without a key the command exits 1 with a clear message and an
|
|
425
428
|
empty stdout.
|
|
426
429
|
|
|
430
|
+
### The decision runner
|
|
431
|
+
|
|
432
|
+
`pagegraph decide <family>` generalizes Jev decisions over a batch. Each input answers every decision
|
|
433
|
+
for that input in one provider call; confident answers resolve and anything inside the confidence
|
|
434
|
+
band goes to a `review` bucket. Nothing is applied automatically — the report is the end product.
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
pagegraph decide <family> inputs.json --json | jq
|
|
438
|
+
cat inputs.json | pagegraph decide <family> --threshold 0.9
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
A batch is a JSON array, a `{ "inputs": [...] }` envelope, or JSONL (one input per line), from a file
|
|
442
|
+
argument or stdin. Flags are shared across families:
|
|
443
|
+
|
|
444
|
+
| Flag | Default | Meaning |
|
|
445
|
+
| ----------------- | ----------- | ------------------------------------------------------------- |
|
|
446
|
+
| `--json` | false | Emit the versioned report as JSON on stdout |
|
|
447
|
+
| `--model <id>` | `jev-latest` | TypeSafe System One model (`jev-latest`, `jev-preview`, …) |
|
|
448
|
+
| `--threshold <t>` | `0.7` | Confidence boundary; `(1−t, t)` is the review band |
|
|
449
|
+
| `--concurrency <n>` | `4` | In-flight decision calls |
|
|
450
|
+
| `--cache <dir>` | — | Reuse model answers by family + model + input hash |
|
|
451
|
+
| `--review-out <file>` | — | Write only the below-threshold records to JSON |
|
|
452
|
+
|
|
453
|
+
`pagegraph decide links` is the links family alias of `pagegraph links decide` (see
|
|
454
|
+
[Decide with Jev](#decide-with-jev)); it accepts the same candidate array.
|
|
455
|
+
|
|
456
|
+
#### `decide serp` — is our page the shape this SERP rewards?
|
|
457
|
+
|
|
458
|
+
Input: one saved results-page snapshot per input.
|
|
459
|
+
|
|
460
|
+
```json
|
|
461
|
+
{
|
|
462
|
+
"query": "best email api",
|
|
463
|
+
"ourPage": {
|
|
464
|
+
"url": "https://example.com/email-api",
|
|
465
|
+
"title": "Email API for developers",
|
|
466
|
+
"kind": "page",
|
|
467
|
+
"firstWords": "Send transactional email from your product."
|
|
468
|
+
},
|
|
469
|
+
"serpItems": [
|
|
470
|
+
{ "type": "organic", "rank": 1, "domain": "a.example", "title": "Best email APIs", "snippet": "Compare" }
|
|
471
|
+
]
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
| Verdict | Meaning |
|
|
476
|
+
| ---------- | ------------------------------------------------------------------ |
|
|
477
|
+
| `aligned` | Intent and format are both confidently positive. |
|
|
478
|
+
| `mismatch` | At least one of intent/format is confidently wrong. |
|
|
479
|
+
| `review` | Any answer (`ourFormatFit`, `intentMatch`, `titlePatternMatch`) is inside the band. |
|
|
480
|
+
|
|
481
|
+
#### `decide content` — does this page carry enough substance?
|
|
482
|
+
|
|
483
|
+
Input: one page per input, with the evidence the rubric reads.
|
|
484
|
+
|
|
485
|
+
```json
|
|
486
|
+
{
|
|
487
|
+
"url": "https://example.com/email-api",
|
|
488
|
+
"query": "best email api",
|
|
489
|
+
"title": "Transactional email API for product teams",
|
|
490
|
+
"h1": "Send transactional email",
|
|
491
|
+
"first150Words": "The API sends one message per call and reports delivery events.",
|
|
492
|
+
"headings": ["Quickstart", "Events", "Pricing"],
|
|
493
|
+
"wordCount": 1200,
|
|
494
|
+
"structuredData": ["Article", "FAQPage"],
|
|
495
|
+
"categoryLock": "email api",
|
|
496
|
+
"siblingIntents": ["email deliverability", "sms api"],
|
|
497
|
+
"competitorExcerpts": ["A competitor's overview."]
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
| Verdict | Meaning |
|
|
502
|
+
| -------- | --------------------------------------------------------------------------- |
|
|
503
|
+
| `pass` | The value rating is not `thin` and no rubric probability is confidently false. |
|
|
504
|
+
| `flag` | Value is `thin`, or a rubric probability (`originalValue`, `answersFirst`, …) is confidently false. |
|
|
505
|
+
| `review` | Any rubric or value probability is inside the band, or an evidence-dependent rubric (`distinctIntent`, `competitiveSubstance`) is confidently positive without `siblingIntents`/`competitorExcerpts`. |
|
|
506
|
+
|
|
507
|
+
`wordCount` must be a non-negative integer.
|
|
508
|
+
|
|
509
|
+
`value` rates `thin | adequate | strong`.
|
|
510
|
+
|
|
511
|
+
#### `decide fit` — which existing page should target this query?
|
|
512
|
+
|
|
513
|
+
Input: a query plus the site's candidate pages. Candidate ids become the provider labels, so the
|
|
514
|
+
family needs at least two candidates with unique ids of at most 255 characters.
|
|
515
|
+
|
|
516
|
+
```json
|
|
517
|
+
{
|
|
518
|
+
"query": "best email api",
|
|
519
|
+
"candidates": [
|
|
520
|
+
{ "id": "/email-api", "title": "Email API", "excerpt": "Send transactional email." },
|
|
521
|
+
{ "id": "/pricing", "title": "Pricing", "excerpt": "Volume pricing." }
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
| Verdict | Meaning |
|
|
527
|
+
| -------------- | -------------------------------------------------------- |
|
|
528
|
+
| `map` | A page is confidently best; update it. |
|
|
529
|
+
| `cannibalized` | Multiple pages already target the query. |
|
|
530
|
+
| `gap` | No page can serve the query; a new page is needed. |
|
|
531
|
+
| `review` | The conflict or the best page is inside the confidence band. |
|
|
532
|
+
|
|
533
|
+
#### `decide meta` — rank supplied title/description candidates
|
|
534
|
+
|
|
535
|
+
Input: a page plus the candidates to rank. Drafting is out of scope — only the provided candidates
|
|
536
|
+
are judged. Needs at least two candidates with unique ids of at most 255 characters.
|
|
537
|
+
|
|
538
|
+
```json
|
|
539
|
+
{
|
|
540
|
+
"url": "https://example.com/email-api",
|
|
541
|
+
"intent": "choose an email api",
|
|
542
|
+
"categoryLock": "email api",
|
|
543
|
+
"candidates": [
|
|
544
|
+
{ "id": "a", "title": "Email API", "description": "Send transactional email." },
|
|
545
|
+
{ "id": "b", "title": "Email pricing", "description": "Volume pricing." }
|
|
546
|
+
]
|
|
547
|
+
}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
| Verdict | Meaning |
|
|
551
|
+
| ------------- | ------------------------------------------------------------------------- |
|
|
552
|
+
| `choose:<id>` | A candidate is confidently best with clear intent, length, category, and clickbait checks. |
|
|
553
|
+
| `review` | A concern or an uncertain pick; a human decides. |
|
|
554
|
+
|
|
555
|
+
#### `decide authority` — is this a real link opportunity?
|
|
556
|
+
|
|
557
|
+
Input: one link target per input.
|
|
558
|
+
|
|
559
|
+
```json
|
|
560
|
+
{
|
|
561
|
+
"domain": "blog.example",
|
|
562
|
+
"url": "https://blog.example/email-guide",
|
|
563
|
+
"anchor": "transactional email API",
|
|
564
|
+
"context": "We cover how a transactional email API works end to end.",
|
|
565
|
+
"targetPath": "/email-api",
|
|
566
|
+
"rd": 120,
|
|
567
|
+
"signals": ["editorial", "no-outbound-links"]
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
| Verdict | Meaning |
|
|
572
|
+
| -------- | ------------------------------------------------------------------------ |
|
|
573
|
+
| `accept` | Legitimate, outreach-worthy, and a confident non-`none` fit. |
|
|
574
|
+
| `spam` | Spam is confidently high. |
|
|
575
|
+
| `review` | Any probability is inside the band, or the fit is `none`/uncertain. |
|
|
576
|
+
|
|
577
|
+
`fit` classifies `directory | partner | editorial | community | none`.
|
|
578
|
+
|
|
579
|
+
#### `decide links` — direction, relevance, and budget
|
|
580
|
+
|
|
581
|
+
`pagegraph decide links` shares the links decisions (see [Decide with Jev](#decide-with-jev)) and
|
|
582
|
+
adds `--budget <n>` (default 4): keep the top-K candidates per outbound page by `relevance`
|
|
583
|
+
(`irrelevant | useful | essential`). `direction` classifies `a_to_b | b_to_a | both`; a record also
|
|
584
|
+
carries the resulting `from`/`to` endpoints, so a `b_to_a` recommendation is reported — and
|
|
585
|
+
budgeted — against the page the model actually chose to link *from*.
|
|
586
|
+
|
|
427
587
|
### Contextual-link coverage
|
|
428
588
|
|
|
429
589
|
Declare a contextual-link coverage policy in `seo.config.ts` (a `coverage` array
|