aiwg 2026.9.7 → 2026.9.9

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 (122) hide show
  1. package/agentic/code/addons/aiwg-hooks/hooks/aiwg-session.cjs +22 -3
  2. package/agentic/code/addons/aiwg-utils/rules/auto-compact-continue.md +4 -0
  3. package/agentic/code/addons/aiwg-utils/rules/delivery-policy.md +6 -0
  4. package/agentic/code/addons/aiwg-utils/rules/escalation-discipline.md +4 -0
  5. package/agentic/code/addons/aiwg-utils/rules/human-authorization.md +7 -0
  6. package/agentic/code/addons/aiwg-utils/rules/instruction-comprehension.md +5 -0
  7. package/agentic/code/addons/aiwg-utils/rules/research-before-decision.md +5 -0
  8. package/agentic/code/addons/aiwg-utils/rules/respect-repo-access-manifest.md +27 -2
  9. package/agentic/code/addons/aiwg-utils/rules/skill-discovery.md +5 -0
  10. package/agentic/code/addons/aiwg-utils/rules/subagent-scoping.md +5 -0
  11. package/agentic/code/addons/aiwg-utils/rules/tool-quota.md +4 -0
  12. package/agentic/code/addons/aiwg-utils/skills/steward/SKILL.md +11 -2
  13. package/agentic/code/extensions/corpus-templates/templates/TEMPLATE-citations.md +58 -10
  14. package/agentic/code/extensions/corpus-templates/templates/TEMPLATES-README.md +2 -0
  15. package/agentic/code/frameworks/ops-complete/rules/ops-safety.md +6 -0
  16. package/agentic/code/frameworks/research-complete/docs/bibliographic-services.md +76 -0
  17. package/agentic/code/frameworks/research-complete/lint/uncertainty-registered.yaml +31 -0
  18. package/agentic/code/frameworks/research-complete/skills/induct-research/SKILL.md +238 -5
  19. package/agentic/code/frameworks/research-complete/templates/citation-sidecar.md +58 -10
  20. package/agentic/code/frameworks/research-complete/templates/reference-templates-guide.md +2 -0
  21. package/agentic/code/frameworks/sdlc-complete/rules/anti-laziness.md +6 -0
  22. package/agentic/code/frameworks/sdlc-complete/rules/no-attribution.md +4 -0
  23. package/agentic/code/frameworks/sdlc-complete/rules/token-security.md +6 -0
  24. package/agentic/code/frameworks/sdlc-complete/skills/address-issues/scripts/cycle-comment.mjs +3 -1
  25. package/agentic/code/frameworks/security-engineering/rules/ci-action-pinning.md +4 -0
  26. package/agentic/code/frameworks/security-engineering/rules/dependency-source-policy.md +4 -0
  27. package/agentic/code/plugins/agent-loop/.claude-plugin/plugin.json +1 -1
  28. package/agentic/code/plugins/agent-persistence/.claude-plugin/plugin.json +1 -1
  29. package/agentic/code/plugins/agentic-installer/.claude-plugin/plugin.json +1 -1
  30. package/agentic/code/plugins/aiwg-dev/.claude-plugin/plugin.json +1 -1
  31. package/agentic/code/plugins/aiwg-evals/.claude-plugin/plugin.json +1 -1
  32. package/agentic/code/plugins/auto-memory/.claude-plugin/plugin.json +1 -1
  33. package/agentic/code/plugins/browser-control/.claude-plugin/plugin.json +1 -1
  34. package/agentic/code/plugins/codex-sdlc/skills/address-issues/scripts/cycle-comment.mjs +3 -1
  35. package/agentic/code/plugins/color-palette/.claude-plugin/plugin.json +1 -1
  36. package/agentic/code/plugins/compound-memory/.claude-plugin/plugin.json +1 -1
  37. package/agentic/code/plugins/context-curator/.claude-plugin/plugin.json +1 -1
  38. package/agentic/code/plugins/daemon/.claude-plugin/plugin.json +1 -1
  39. package/agentic/code/plugins/doc-intelligence/.claude-plugin/plugin.json +1 -1
  40. package/agentic/code/plugins/droid-bridge/.claude-plugin/plugin.json +1 -1
  41. package/agentic/code/plugins/forensics/.claude-plugin/plugin.json +1 -1
  42. package/agentic/code/plugins/guided-implementation/.claude-plugin/plugin.json +1 -1
  43. package/agentic/code/plugins/hooks/.claude-plugin/plugin.json +1 -1
  44. package/agentic/code/plugins/hooks/hooks/aiwg-session.cjs +22 -3
  45. package/agentic/code/plugins/knowledge-base/.claude-plugin/plugin.json +1 -1
  46. package/agentic/code/plugins/line-memory/.claude-plugin/plugin.json +1 -1
  47. package/agentic/code/plugins/llm-wiki/.claude-plugin/plugin.json +1 -1
  48. package/agentic/code/plugins/marketing/.claude-plugin/plugin.json +1 -1
  49. package/agentic/code/plugins/media-curator/.claude-plugin/plugin.json +1 -1
  50. package/agentic/code/plugins/nlp-prod/.claude-plugin/plugin.json +1 -1
  51. package/agentic/code/plugins/ops/.claude-plugin/plugin.json +1 -1
  52. package/agentic/code/plugins/prose-integration/.claude-plugin/plugin.json +1 -1
  53. package/agentic/code/plugins/research/.claude-plugin/plugin.json +1 -1
  54. package/agentic/code/plugins/research/skills/induct-research/SKILL.md +237 -5
  55. package/agentic/code/plugins/rlm/.claude-plugin/plugin.json +1 -1
  56. package/agentic/code/plugins/sdlc/.claude-plugin/plugin.json +1 -1
  57. package/agentic/code/plugins/sdlc/skills/address-issues/scripts/cycle-comment.mjs +3 -1
  58. package/agentic/code/plugins/security-engineering/.claude-plugin/plugin.json +1 -1
  59. package/agentic/code/plugins/semantic-memory/.claude-plugin/plugin.json +1 -1
  60. package/agentic/code/plugins/skill-factory/.claude-plugin/plugin.json +1 -1
  61. package/agentic/code/plugins/star-prompt/.claude-plugin/plugin.json +1 -1
  62. package/agentic/code/plugins/testing-quality/.claude-plugin/plugin.json +1 -1
  63. package/agentic/code/plugins/twelve-factor/.claude-plugin/plugin.json +1 -1
  64. package/agentic/code/plugins/uat-mcp/.claude-plugin/plugin.json +1 -1
  65. package/agentic/code/plugins/utils/.claude-plugin/plugin.json +1 -1
  66. package/agentic/code/plugins/utils/skills/steward/SKILL.md +11 -2
  67. package/agentic/code/plugins/validation-complete/.claude-plugin/plugin.json +1 -1
  68. package/agentic/code/plugins/verbalized-sampling/.claude-plugin/plugin.json +1 -1
  69. package/agentic/code/plugins/voice/.claude-plugin/plugin.json +1 -1
  70. package/agentic/code/plugins/writing/.claude-plugin/plugin.json +1 -1
  71. package/dist/src/artifacts/index-builder.js +43 -1
  72. package/dist/src/artifacts/query-engine.js +7 -0
  73. package/dist/src/cli/handlers/installation.js +102 -2
  74. package/dist/src/cli/handlers/mc.js +87 -17
  75. package/dist/src/cli/handlers/refresh.js +67 -7
  76. package/dist/src/cli/handlers/repo-access.js +155 -4
  77. package/dist/src/cli/handlers/setup.js +5 -5
  78. package/dist/src/cli/handlers/steward.js +30 -1
  79. package/dist/src/cli/handlers/use.js +9 -4
  80. package/dist/src/cli/handlers/version.js +40 -14
  81. package/dist/src/cli/handlers/workspace-context.js +8 -0
  82. package/dist/src/cli/services/deployment-verification.js +39 -6
  83. package/dist/src/config/aiwg-config.js +95 -3
  84. package/dist/src/config/cli.js +16 -1
  85. package/dist/src/config/gitignore.js +5 -0
  86. package/dist/src/extensions/claude-hooks-installer.js +22 -6
  87. package/dist/src/lint/runner.js +138 -0
  88. package/dist/src/smiths/context-pipeline/workspace-context.js +51 -1
  89. package/dist/src/writing/writing-receipt.d.ts +16 -16
  90. package/docs/_manifest.json +14 -0
  91. package/docs/cli/reference.md +4 -0
  92. package/docs/configuration/aiwg-config.md +67 -0
  93. package/docs/development/cli-help-routing-audit.md +22 -15
  94. package/docs/development/rule-creation-guide.md +95 -0
  95. package/docs/integrations/codex-quickstart.md +6 -3
  96. package/docs/migration/workspace-context.md +32 -0
  97. package/docs/releases/v2026.9.9-announcement.md +144 -0
  98. package/docs/verification-contracts.md +2 -0
  99. package/package.json +2 -1
  100. package/prebuilt/fortemi-core/framework/aiwg-fortemi-index-v2.json +1 -1
  101. package/prebuilt/fortemi-core/framework/manifest.json +2 -2
  102. package/tools/agents/deploy-agents.mjs +4 -0
  103. package/tools/agents/providers/base.mjs +101 -4
  104. package/tools/cli/doctor.mjs +74 -4
  105. package/tools/ralph-external/index.mjs +20 -0
  106. package/tools/research/bibliography-resolver.mjs +435 -0
  107. package/vscode-extension/schemas/aiwg.config.v1.json +27 -2
  108. package/docs/addons/ralph/agent-persistence-integration.md +0 -1060
  109. package/docs/addons/ralph/best-practices.md +0 -313
  110. package/docs/addons/ralph/cross-loop-learning.md +0 -768
  111. package/docs/addons/ralph/examples/coverage.md +0 -113
  112. package/docs/addons/ralph/examples/migration.md +0 -102
  113. package/docs/addons/ralph/examples/test-fix-loop.md +0 -95
  114. package/docs/addons/ralph/executable-feedback-guide.md +0 -489
  115. package/docs/addons/ralph/quickstart.md +0 -233
  116. package/docs/addons/ralph/reflection-memory-guide.md +0 -673
  117. package/docs/addons/ralph/troubleshooting.md +0 -326
  118. package/docs/addons/ralph/when-to-use-ralph.md +0 -348
  119. /package/agentic/code/addons/agent-loop/docs/{when-to-use-ralph.md → when-to-use-agent-loop.md} +0 -0
  120. /package/agentic/code/plugins/agent-loop/docs/{when-to-use-ralph.md → when-to-use-agent-loop.md} +0 -0
  121. /package/docs/addons/agent-loop/{when-to-use-ralph.md → when-to-use-agent-loop.md} +0 -0
  122. /package/docs/{ralph-guide.md → agent-loop-guide.md} +0 -0
@@ -210,8 +210,28 @@ async function main() {
210
210
  break;
211
211
  }
212
212
 
213
+ case undefined:
214
+ case '':
215
+ // Invoked with no subcommand. This is the SessionStart hook path: anything
216
+ // printed here lands at the top of every session transcript, so stay silent
217
+ // and exit clean. Help is available explicitly via `help`/`--help`. (#2543)
218
+ break;
219
+
220
+ case 'help':
221
+ case '--help':
222
+ case '-h':
223
+ console.log(usage());
224
+ break;
225
+
213
226
  default:
214
- console.log(`
227
+ console.error(`Unknown command: ${command}`);
228
+ console.error(usage());
229
+ process.exitCode = 1;
230
+ }
231
+ }
232
+
233
+ function usage() {
234
+ return `
215
235
  AIWG Session Manager
216
236
 
217
237
  Usage:
@@ -226,8 +246,7 @@ Examples:
226
246
 
227
247
  aiwg-session.cjs record aiwg-security-review-2025-01-15 --workflow security-review
228
248
  aiwg-session.cjs list
229
- `);
230
- }
249
+ `;
231
250
  }
232
251
 
233
252
  main().catch(err => {
@@ -1,5 +1,9 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "should I keep working"
5
+ - "context is getting long"
6
+ - "should I stop here"
3
7
  ---
4
8
 
5
9
  # Auto-Compact and Continue
@@ -4,6 +4,12 @@ id: delivery-policy
4
4
  severity: HIGH
5
5
  applies_to: [all-agents]
6
6
  tags: [git, workflow, project-config, branching]
7
+ triggers:
8
+ - "should I open a pull request"
9
+ - "do I branch for this"
10
+ - "can I commit to main"
11
+ - "how does this project deliver changes"
12
+ - "force push policy"
7
13
  ---
8
14
 
9
15
  # Delivery Policy Rule
@@ -1,5 +1,9 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "should I use a stronger model"
5
+ - "is this worth escalating"
6
+ - "model tier"
3
7
  ---
4
8
 
5
9
  # Escalation Discipline
@@ -5,6 +5,13 @@ severity: HIGH
5
5
  safety-critical: true
6
6
  applies_to: [all-agents]
7
7
  tags: [authorization, scope, safety]
8
+ triggers:
9
+ - "am I allowed to do this"
10
+ - "do I need permission for this"
11
+ - "can I delete this"
12
+ - "should I close this issue"
13
+ - "acting on a finding"
14
+ - "is this in scope"
8
15
  ---
9
16
 
10
17
  # Human Authorization Rules
@@ -1,5 +1,10 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "what did the user actually ask for"
5
+ - "did I follow the instructions"
6
+ - "the user repeated themselves"
7
+ - "user says that is not what I asked"
3
8
  ---
4
9
 
5
10
  # Instruction Comprehension Rules
@@ -1,5 +1,10 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "which library should I use"
5
+ - "why does this keep failing"
6
+ - "I am guessing at this api"
7
+ - "before I decide"
3
8
  ---
4
9
 
5
10
  # Research Before Decision Rules
@@ -1,5 +1,12 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "register a repo in the workspace manifest"
5
+ - "add a repo to the access manifest"
6
+ - "register a repo"
7
+ - "repo access manifest"
8
+ - "am I allowed to write to this repo"
9
+ - "is this repo authorized"
3
10
  ---
4
11
 
5
12
  # Respect Repo Access Manifest
@@ -10,16 +17,33 @@ workspace manifest is `.aiwg/aiwg.config` `workspace` + `repos`. Legacy
10
17
  `.aiwg/ops/security/repo-access.manifest.yaml` and
11
18
  `.aiwg/security/repo-access.manifest.yaml` remain compatibility fallbacks.
12
19
 
20
+ To **register a repo in the workspace manifest**, add a repo to the access manifest,
21
+ or list repositories that are unlisted and therefore denied, use
22
+ `aiwg repo-access add | remove | audit`. Registration is an operator decision:
23
+ propose the command, do not run it on your own authority.
24
+
13
25
  ## Rule
14
26
 
15
27
  Before reading deeply, editing, committing, pushing, commenting on issues, or taking service actions against a repo path, run or mentally apply:
16
28
 
17
29
  ```bash
18
30
  aiwg repo-access check --path <repo-or-file> --action <read|write|commit|push|issue-comment|service-action|destructive>
31
+ # register a repo in the workspace manifest / add a repo to the access manifest:
32
+ aiwg repo-access add --path <p> --name <n> --allow read,write
19
33
  ```
20
34
 
21
35
  If the repo/path is unlisted, deny by default. Ask the operator to add or update
22
- the manifest before proceeding. For every listed member, load that member's own
36
+ the manifest before proceeding — the registration command is:
37
+
38
+ ```bash
39
+ aiwg repo-access add --path <repo-or-file> --name <name> \
40
+ --allow read,write,commit,push[,issue-comment,service-action] [--notes "..."]
41
+ aiwg repo-access remove --name <name>
42
+ aiwg repo-access audit # git repos under the workspace root with no manifest entry
43
+ ```
44
+
45
+ Registration is the operator's decision: propose the exact command, do not run it
46
+ on your own authority. For every listed member, load that member's own
23
47
  `.aiwg/aiwg.config`; never reuse the workspace root's delivery, remotes, tracker
24
48
  actor, or signing policy.
25
49
 
@@ -76,7 +100,8 @@ If asked to edit an adjacent repo that is not listed:
76
100
 
77
101
  1. Stop before editing.
78
102
  2. Explain that the manifest denies unlisted repo work.
79
- 3. Ask for a manifest update or explicit operator instruction to add the repo.
103
+ 3. Ask for a manifest update or explicit operator instruction to add the repo,
104
+ quoting the `aiwg repo-access add` command that would register it.
80
105
 
81
106
  If asked to comment on an issue in a handoff-only repo:
82
107
 
@@ -1,5 +1,10 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "does AIWG have a skill for this"
5
+ - "how do I find a capability"
6
+ - "is there a command for this"
7
+ - "AIWG does not seem to have"
3
8
  ---
4
9
 
5
10
  # Skill Discovery Rules
@@ -1,5 +1,10 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "how many subagents should I spawn"
5
+ - "should I delegate this"
6
+ - "how do I split this work"
7
+ - "parallel agents"
3
8
  ---
4
9
 
5
10
  # Subagent Scoping Rules
@@ -1,5 +1,9 @@
1
1
  ---
2
2
  enforcement: high
3
+ triggers:
4
+ - "how many times should I retry"
5
+ - "this command keeps failing"
6
+ - "am I in a loop"
3
7
  ---
4
8
 
5
9
  # Tool Quota and Loop Detection
@@ -124,15 +124,24 @@ Use this recovery ladder:
124
124
  aiwg regenerate
125
125
  ```
126
126
 
127
- 5. If discovery itself is stale after source edits or a failed deploy, rebuild
128
- the index and verify the route:
127
+ 5. If discovery itself is stale after source edits, a failed deploy, or an
128
+ install-root change (`npm link`), rebuild the index and verify the route.
129
+ **The framework graph indexes the AIWG corpus and can only be built at the
130
+ install root** — running the build step in a consumer project fails with
131
+ "No scan directories found". Only the sync step runs in the project:
129
132
 
130
133
  ```bash
134
+ cd "$(aiwg installation show --json | jq -r .actualRoot)" # or the known install root
131
135
  aiwg index build --graph framework --force
136
+
137
+ cd <your project>
132
138
  aiwg index sync --backend fortemi-core --graph framework
133
139
  aiwg discover "<original user need>"
134
140
  ```
135
141
 
142
+ `aiwg discover --backend local` works as an immediate workaround while the
143
+ framework graph is unavailable.
144
+
136
145
  6. Reload the provider session when `aiwg use`, `aiwg refresh`, or
137
146
  `aiwg regenerate` changes provider-facing files.
138
147
 
@@ -12,31 +12,73 @@ funders: # extracted from paper acknowledgements (om
12
12
  - id: PROF-F-funder-slug
13
13
  grant-id: "AGENCY-GRANT-NUMBER" # if stated; null if not
14
14
  status: induction-complete # optional: placeholder | pending-acquisition | acquisition-deficit
15
+ acquisition-obstacle: # required when status is pending-acquisition/acquisition-deficit
16
+ state: not-attempted # not-attempted | credential-required | structurally-unobtainable | artifact-absent
17
+ detail: "" # the specific obstacle, e.g. "needs HF_TOKEN"; never a bare boolean
18
+ paths-tried: [] # ["resolve/main/README.md 200", "raw/main/README.md 401"]
19
+ bibliography: # how the edges below were established
20
+ source: bbl # bbl | inline-thebibliography | pdf-reference-list
21
+ count: 0 # entries in the compiled bibliography
22
+ count-method: 'counted \bibitem in .bbl' # single-quoted: YAML "\b" is a backspace escape
23
+ unique-count: # when printed ≠ unique (duplicate entries), else omit
15
24
  ---
16
25
 
17
26
  # REF-XXX Citation Network
18
27
 
19
28
  ## Outgoing: Papers This Work Cites
20
29
 
21
- | # | Title | Authors | Year | DOI/URL | Inducted REF |
22
- |---|-------|---------|------|---------|--------------|
23
- | 1 | {cited title} | {Lastname et al.} | YYYY | arXiv:NNNN.NNNNN | REF-YYY |
24
- | 2 | {cited title} | {authors} | YYYY | DOI / URL | — |
25
- | ... | ... | ... | ... | ... | ... |
30
+ | # | Title | Authors | Year | DOI/URL | Inducted REF | Confirmed by |
31
+ |---|-------|---------|------|---------|--------------|--------------|
32
+ | 1 | {cited title} | {Lastname et al.} | YYYY | arXiv:NNNN.NNNNN | REF-YYY | arxiv-id |
33
+ | 2 | {cited title} | {authors} | YYYY | DOI / URL | — | printed-entry |
34
+ | ... | ... | ... | ... | ... | ... | ... |
26
35
 
27
36
  <!--
28
37
  Outgoing rules:
38
+ - Membership comes from the COMPILED bibliography, in this order of preference:
39
+ 1. `.bbl` (`\bibitem` for natbib/plain, `\entry{}` for biblatex)
40
+ 2. `\begin{thebibliography}` inline in the `.tex`
41
+ 3. the reference list in the extracted PDF text
42
+ 4. the shipped `.bib` — ONLY to enrich metadata for entries already confirmed by 1-3
43
+ The shipped `.bib` is the author's library, not the reference list. An entry present in
44
+ `.bib` and absent from the compiled bibliography is NOT a citation; asserting it
45
+ fabricates an edge. A 15-entry gap between the two is ordinary.
29
46
  - One row per distinct cited work in the paper's reference list (cap at ~30 most relevant
30
47
  if the paper has 100+ refs; note which references were cut and why in Notes).
31
48
  - "Inducted REF" column links to corpus REFs when the cited work is in the corpus.
32
49
  Mark as "—" (em dash) when the cited work is not (yet) in the corpus.
50
+ - "Confirmed by" records HOW the edge was established: `arxiv-id`, `exact-title`, or
51
+ `printed-entry` (read the entry directly). Title similarity against a corpus index is
52
+ not confirmation — author-year collisions defeat it (e.g. "Zou et al. 2023" may be GCG
53
+ or Representation Engineering: same first author, same year, different work). Normalise
54
+ brace-escaped titles (`{AI}`, `{Prompt}-{Driven}`) before comparing.
33
55
  - Authors column: "Lastname et al." for ≥4 authors; full list for ≤3.
34
56
  - DOI/URL: prefer arXiv ID format `arXiv:NNNN.NNNNN` for arXiv preprints; DOI for
35
57
  peer-reviewed; URL for blog posts / technical reports.
58
+ - Direction is a check, not an assumption: a work cannot cite something published after
59
+ it. Verify both publication dates before writing the edge.
36
60
  - When an outgoing row points to an inducted REF, that target REF's Incoming table
37
61
  MUST contain a corresponding row pointing back here. See bidirectionality below.
38
62
  -->
39
63
 
64
+ ## Rejected Candidates
65
+
66
+ | # | Title | Authors | Year | Why rejected |
67
+ |---|-------|---------|------|--------------|
68
+ | 1 | {candidate title} | {authors} | YYYY | `.bib`-only — absent from compiled `.bbl` |
69
+
70
+ <!--
71
+ Rejected-candidate rules:
72
+ - Record every candidate edge dropped after investigation, so a later extraction pass
73
+ does not silently reintroduce it.
74
+ - Most common reason: present in the shipped `.bib`, absent from the compiled
75
+ bibliography. Others: wrong node after author-year disambiguation; direction
76
+ impossible by publication date.
77
+ - REF ids here are deliberately NOT edges. Corpus tooling stops treating a section as
78
+ an edge source at this heading, so a rejection cannot assert the edge it records.
79
+ - Omit this section only when no candidate was rejected.
80
+ -->
81
+
40
82
  ## Incoming: Papers That Cite This Work
41
83
 
42
84
  | # | Title | Authors | Year | DOI/URL | Inducted REF |
@@ -66,12 +108,18 @@ Incoming rules:
66
108
  - **Author overlap**: shared authors with REF-AAA, REF-BBB (same lab / research line).
67
109
  - **Methodological lineage**: this paper extends / contradicts / parallels REF-XXX's approach.
68
110
  - **External replication state**: known independent replications or rebuttals not yet inducted.
69
- - **Reference list size**: total cited works in PDF vs included here (e.g., "PDF has 87 refs;
70
- this sidecar includes the 30 most relevant per Outgoing rules").
111
+ - **Reference list size**: entries in the COMPILED bibliography vs included here, stating
112
+ the counting method (e.g., "66 `\bibitem` in .bbl; this sidecar includes the 30 most
113
+ relevant per Outgoing rules"). Never `.bib` size, and never a sum of artifacts — summing
114
+ `.bib` and `.bbl` without dedup has produced counts inflated 2-3x. Note printed-vs-unique
115
+ where they differ.
71
116
 
72
- If acquisition is incomplete, document it here:
73
- - "PDF not acquired (paywall); Outgoing references deferred."
74
- - "Reference list extraction pending."
117
+ If acquisition is incomplete, document the named obstacle and the paths tried, not just
118
+ the fact:
119
+ - "PDF not acquired — structurally-unobtainable: closed access; Unpaywall zero OA locations,
120
+ Semantic Scholar reports abstract elided, no arXiv preprint. Outgoing deferred."
121
+ - "PDF not acquired — credential-required: dataset repo returns 401 to anonymous client on
122
+ `raw/main`; `resolve/main` also 401. Needs HF_TOKEN."
75
123
  }
76
124
 
77
125
  <!--
@@ -107,6 +107,8 @@ When backfilling, do **not** restructure heading content silently. Preserve the
107
107
  | `pdf_hash` | yes when PDF exists | string | SHA-256 of `pdfs/full/REF-XXX-*.pdf` |
108
108
  | `affiliation-primary` | optional | string or PROF-O ID | Primary author's institution |
109
109
  | `status` | optional | enum | `placeholder`, `pending-acquisition`, `acquisition-deficit` for partial inductions |
110
+ | `acquisition-obstacle` | required when status is `pending-acquisition`/`acquisition-deficit` | object | `state` (`not-attempted`, `credential-required`, `structurally-unobtainable`, `artifact-absent`), `detail` (the specific obstacle), `paths-tried` (each path and what it returned). A bare boolean cannot be triaged |
111
+ | `bibliography` | recommended on citation sidecars | object | `source` (`bbl`, `inline-thebibliography`, `pdf-reference-list`), `count`, `count-method`, optional `unique-count`. Counts come from the compiled bibliography, never `.bib` size or a sum of artifacts |
110
112
 
111
113
  The `pdf_hash` field is the load-bearing integrity check — verify with `sha256sum pdfs/full/REF-XXX-*.pdf` when refreshing.
112
114
 
@@ -1,5 +1,11 @@
1
1
  ---
2
2
  enforcement: critical
3
+ triggers:
4
+ - "is this command destructive"
5
+ - "can I run this safely"
6
+ - "blast radius"
7
+ - "this needs sudo"
8
+ - "interactive command"
3
9
  ---
4
10
 
5
11
  # Ops Safety Rules
@@ -0,0 +1,76 @@
1
+ # Bibliographic services: what each is good for, and where each will mislead you
2
+
3
+ Operating characteristics of the services the census, retraction, and acquisition
4
+ steps depend on. Measured across a 12-paper batch, 2026-09-12. Re-measure and
5
+ update the date when these change — the failure modes below are behavioural, not
6
+ documented guarantees.
7
+
8
+ The point of this table is not the happy path. It is that **one of these services
9
+ returns plausible, well-formed, badly wrong data with no error**, and an agent
10
+ discovering the ecosystem from scratch has no way to know which.
11
+
12
+ ## Service table
13
+
14
+ | Service | Use for | Do **not** use for | Auth | Observed failure |
15
+ |---|---|---|---|---|
16
+ | Semantic Scholar | citation counts, influential counts, venue corroboration | — | key strongly recommended | HTTP 429 even at 25 s spacing |
17
+ | OpenAlex | `is_retracted` | **citation counts** — splits preprint/published records; 18× undercount observed | none | none; returns wrong data silently |
18
+ | OpenReview | venue/acceptance confirmation | — | none | — |
19
+ | ACL Anthology / PMLR | published version, page ranges | — | none | PMLR asset lives at `raw.githubusercontent.com/mlresearch/...`; the intuitive proceedings path 404s |
20
+ | Crossref / Unpaywall / Europe PMC | OA routing, bibliographic metadata | — | none (Unpaywall wants `mailto`) | — |
21
+ | PubPeer | post-publication concerns | — | — | HTTP 403 to non-browser clients |
22
+ | DBLP | venue fallback | — | — | anti-bot challenge; returns HTML, not JSON |
23
+
24
+ ## The OpenAlex count trap
25
+
26
+ OpenAlex indexes the arXiv preprint record separately from the published record and
27
+ does not merge them. For REF-2532 (ROME) it returns `cited_by_count: 178` where
28
+ Semantic Scholar returns **3,205** — an 18× undercount. Title-search does not fix
29
+ it; the best-cited match was still the arXiv record.
30
+
31
+ This is a trap rather than a limitation because of *when* an agent reaches for it.
32
+ OpenAlex is the obvious fallback when Semantic Scholar throttles: unauthenticated,
33
+ generous limits, returns a plausible-looking integer. Substituting it silently
34
+ records counts an order of magnitude wrong, with no error and no signal. The
35
+ corpus then carries a number that looks like evidence and is not.
36
+
37
+ **Calibration rule.** Never substitute a citation-count source without checking it
38
+ against a known-high-count paper first. A source that returns 178 for a
39
+ 3,000-citation paper is not a fallback, it is data corruption. One calibration
40
+ query catches it.
41
+
42
+ **Provenance rule.** Record the source and the date with every count. A count
43
+ without a provenance line cannot be compared against a later refresh and cannot be
44
+ audited when two sources disagree. Record a null result as a null result —
45
+ `is_retracted: false, OpenAlex, 2026-09-12` — never as the absence of a check.
46
+
47
+ ## Throttling budget
48
+
49
+ Semantic Scholar is the best source for counts and the most aggressive throttler.
50
+ Measured: 4 of 12 succeeded on a first pass at ~4 s spacing; a retry pass at **25 s
51
+ spacing still lost 4 of 8**. The 429 body points at the API-key form.
52
+
53
+ Budget roughly five minutes of wall-clock for a 12-paper census, and **record
54
+ misses as misses** rather than substituting a source that has not been calibrated.
55
+
56
+ ## Permanent access limitations
57
+
58
+ PubPeer returns 403 to this client, so the corpus has never carried a PubPeer
59
+ signal; radars record "PubPeer not checked" as a permanent access limitation, which
60
+ is honest. DBLP returns an Anubis challenge page rather than JSON, which fails like
61
+ a parse error rather than a block — worth naming, since DBLP is the natural venue
62
+ fallback when Semantic Scholar throttles.
63
+
64
+ ## API keys
65
+
66
+ A Semantic Scholar key removes the throttling problem and is strongly recommended
67
+ for any batch. Key handling follows
68
+ [`token-security`](../../sdlc-complete/rules/token-security.md) without
69
+ exception: a mode-600 file, loaded at the point of use, never passed as a command
70
+ argument, never echoed, never committed.
71
+
72
+ ```bash
73
+ # Correct: loaded inline at point of use, scoped to the call
74
+ curl -s -H "x-api-key: $(cat ~/.config/semanticscholar/token)" \
75
+ "https://api.semanticscholar.org/graph/v1/paper/..."
76
+ ```
@@ -0,0 +1,31 @@
1
+ id: research/uncertainty-registered
2
+ name: Stated uncertainty must name an obstacle
3
+ description: >
4
+ An uncertainty written only into prose is invisible to the verification contract.
5
+ The contract governs declared checks and returns pass/incomplete/blocked for things
6
+ someone thought to declare, so "no OpenReview query was run" never surfaces as
7
+ incomplete and the "never report skipped verification as success" rule is never
8
+ violated — the skipped verification was never registered as verification at all.
9
+
10
+ Flags a clause that states an unperformed action against a verification target the
11
+ agent could have acted on (OpenReview, ACL Anthology, camera-ready, PDF, retraction
12
+ or citation census, code URL, venue) with no obstacle named nearby. Accepts the
13
+ statement once it names a specific obstacle — HTTP status, credential requirement,
14
+ rate limit, paywall, anti-bot wall, unknown endpoint — or records an outcome with a
15
+ date, which is what turns "I did not check" into "I could not check, because".
16
+
17
+ Matching is scoped to a clause, not a line: corpus prose keeps whole paragraphs and
18
+ changelog table rows on one line, and line-scoped matching related unrelated clauses.
19
+ A verification target is required precisely so the paper's own unverified claims are
20
+ left alone — this rule must not discourage honest limitation sections.
21
+
22
+ Severity is warn because this is a prose heuristic. Measured on a 2,544-reference
23
+ corpus: 34 flagged clauses, of which roughly 31 are genuine unperformed checks —
24
+ including every gap a hand post-induction audit had found independently. Raise to
25
+ error once a corpus is clean if you want it to gate.
26
+ severity: warn
27
+ applies-to:
28
+ glob: "documentation/references/**/*.md"
29
+ checks:
30
+ - type: unregistered-uncertainty
31
+ obstacleWithinLines: 2