Offer catalog sources to inbound-library as shared pointers (IR-WP-0010-T04).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 7780@bnt-lap001 Assistant-Session: 622cd705-cb31-4322-ba08-dd42e44fa583
This commit is contained in:
parent
1d4c55ef25
commit
b1a65e7214
5 changed files with 105 additions and 2 deletions
|
|
@ -194,6 +194,8 @@ def main(argv=None):
|
|||
briefs_command.add_argument('--inbox', type=Path, help='override the configured inbox for this run')
|
||||
pull_command = commands.add_parser('pull-briefs', help='retain briefs that inbound-library routed to this repo')
|
||||
pull_command.add_argument('--config', type=Path, default=Path('ops/schedule.json'))
|
||||
contribute_command = commands.add_parser('contribute-sources', help='offer catalog sources to inbound-library as shared pointers')
|
||||
contribute_command.add_argument('--config', type=Path, default=Path('ops/schedule.json'))
|
||||
publish_command = commands.add_parser('publish', help='record a reviewed publication linked to captures')
|
||||
publish_command.add_argument('input', type=Path)
|
||||
commands.add_parser('health', help='show durable scheduler health')
|
||||
|
|
@ -268,6 +270,13 @@ def main(argv=None):
|
|||
result['native'] = native_status()
|
||||
print(json.dumps(result, indent=2))
|
||||
return 0 if result['ok'] else 1
|
||||
elif args.command == 'contribute-sources':
|
||||
from .library_briefs import contribute_sources
|
||||
spec = json.loads(args.config.read_text()).get('library')
|
||||
if not spec:
|
||||
print('no "library" section in the schedule config', file=sys.stderr)
|
||||
return 2
|
||||
print(json.dumps(contribute_sources(args.root, spec), indent=2))
|
||||
elif args.command == 'pull-briefs':
|
||||
from .library_briefs import pull
|
||||
spec = json.loads(args.config.read_text()).get('library')
|
||||
|
|
|
|||
|
|
@ -166,3 +166,41 @@ def _write_markdown(root, provider, parsed, text, item, imported_at, subject, re
|
|||
f'- Imported: {imported_at}', '', text if text.endswith('\n') else text + '\n'])
|
||||
target.write_text(body, encoding='utf-8')
|
||||
return target.relative_to(root).as_posix()
|
||||
|
||||
|
||||
def contribute_sources(root, spec):
|
||||
"""Write this repo's primary sources into the inbound-library registry as shared
|
||||
URL pointers. URL and publisher come from catalog/sources.json; topics come from
|
||||
spec["contribute"]. Primary capture stays here; the library does not fetch them.
|
||||
|
||||
A file that this repo already wrote is updated in place. A file owned by another
|
||||
repo is refused.
|
||||
"""
|
||||
root = Path(root)
|
||||
library = Path(spec['root']).expanduser()
|
||||
target = library / 'registry' / 'sources'
|
||||
if not target.is_dir():
|
||||
raise LibraryUnavailable(f'inbound-library registry not found at {target}')
|
||||
catalog = {s['id']: s for s in json.loads((root / 'catalog' / 'sources.json').read_text())['sources']}
|
||||
owner = spec.get('repo', 'intelligence-radar')
|
||||
written = []
|
||||
for ident, topics in sorted(spec.get('contribute', {}).items()):
|
||||
if ident not in catalog:
|
||||
raise ValueError(f'contribute names unknown catalog source {ident}')
|
||||
entry = catalog[ident]
|
||||
source_id = f'ir-{ident}'
|
||||
record = {'id': source_id, 'owner_repo': owner, 'channel': 'url', 'url': entry['url'],
|
||||
'topics': sorted(topics), 'cadence': 'irregular', 'visibility': 'shared',
|
||||
'publisher': entry.get('publisher', ''),
|
||||
'notes': f'Primary source captured by {owner} (catalog/sources.json id '
|
||||
f'{ident}). Pointer only; inbound-library does not fetch it.'}
|
||||
path = target / f'{source_id}.json'
|
||||
if path.exists() and json.loads(path.read_text()).get('owner_repo') != owner:
|
||||
raise ValueError(f'{path.name} belongs to another repo')
|
||||
content = json.dumps(record, indent=2, ensure_ascii=False) + '\n'
|
||||
status = 'unchanged' if path.exists() and path.read_text() == content else \
|
||||
('updated' if path.exists() else 'created')
|
||||
if status != 'unchanged':
|
||||
atomic(path, content.encode())
|
||||
written.append({'source': source_id, 'status': status})
|
||||
return written
|
||||
|
|
|
|||
|
|
@ -7,7 +7,14 @@
|
|||
"library": {
|
||||
"root": "~/inbound-library",
|
||||
"repo": "intelligence-radar",
|
||||
"sources": {"grok-briefs-via-founder": "grok"}
|
||||
"sources": {"grok-briefs-via-founder": "grok"},
|
||||
"contribute": {
|
||||
"swe-bench": ["ai.benchmarks"],
|
||||
"anthropic-pricing": ["ai.pricing"],
|
||||
"anthropic-sonnet": ["ai.models"],
|
||||
"anthropic-sonnet-launch": ["ai.models"],
|
||||
"openrouter-models": ["ai.models", "ai.pricing"]
|
||||
}
|
||||
},
|
||||
"jobs": [
|
||||
{"id": "radar-daily", "cadence": "daily", "at": "21:30", "sources": "catalog/sources.json"},
|
||||
|
|
|
|||
|
|
@ -118,5 +118,39 @@ class LibraryBriefs(unittest.TestCase):
|
|||
('daily', '2026-10-06', 'complete'))
|
||||
|
||||
|
||||
class ContributeSources(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.tmp.name) / 'radar'
|
||||
self.library = Path(self.tmp.name) / 'library'
|
||||
(self.root / 'catalog').mkdir(parents=True)
|
||||
(self.library / 'registry' / 'sources').mkdir(parents=True)
|
||||
(self.root / 'catalog' / 'sources.json').write_text(json.dumps({'sources': [
|
||||
{'id': 'swe-bench', 'publisher': 'SWE-bench maintainers',
|
||||
'url': 'https://www.swebench.com/'}]}))
|
||||
self.spec = {'root': str(self.library), 'repo': 'intelligence-radar',
|
||||
'contribute': {'swe-bench': ['ai.benchmarks']}}
|
||||
|
||||
def tearDown(self):
|
||||
self.tmp.cleanup()
|
||||
|
||||
def test_create_then_unchanged_and_pointer_shape(self):
|
||||
self.assertEqual(library_briefs.contribute_sources(self.root, self.spec),
|
||||
[{'source': 'ir-swe-bench', 'status': 'created'}])
|
||||
self.assertEqual(library_briefs.contribute_sources(self.root, self.spec),
|
||||
[{'source': 'ir-swe-bench', 'status': 'unchanged'}])
|
||||
source = json.loads((self.library / 'registry' / 'sources' / 'ir-swe-bench.json').read_text())
|
||||
self.assertEqual((source['channel'], source['url'], source['visibility'], source['topics']),
|
||||
('url', 'https://www.swebench.com/', 'shared', ['ai.benchmarks']))
|
||||
|
||||
def test_refuses_another_repos_file_and_unknown_source(self):
|
||||
(self.library / 'registry' / 'sources' / 'ir-swe-bench.json').write_text(
|
||||
json.dumps({'id': 'ir-swe-bench', 'owner_repo': 'markitect'}))
|
||||
with self.assertRaises(ValueError):
|
||||
library_briefs.contribute_sources(self.root, self.spec)
|
||||
with self.assertRaises(ValueError):
|
||||
library_briefs.contribute_sources(self.root, {**self.spec, 'contribute': {'nope': []}})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ reports both as duplicates.
|
|||
|
||||
```task
|
||||
id: IR-WP-0010-T04
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "54945f3f-d651-5de2-8e03-c554ab34dc2c"
|
||||
```
|
||||
|
|
@ -145,6 +145,21 @@ re-ingest them.
|
|||
Acceptance: a second repo's subscription matches at least one contributed
|
||||
source.
|
||||
|
||||
Done 2026-10-06:
|
||||
- `contribute-sources` writes the five catalog sources into inbound-library as
|
||||
shared URL pointers. They are `ir-swe-bench`, `ir-anthropic-pricing`,
|
||||
`ir-anthropic-sonnet`, `ir-anthropic-sonnet-launch` and `ir-openrouter-models`.
|
||||
Their topics are `ai.benchmarks`, `ai.pricing` and `ai.models`, mapped in
|
||||
`ops/schedule.json` under `library.contribute`.
|
||||
- URL and publisher come from `catalog/sources.json`. Reruns are idempotent,
|
||||
and a file owned by another repo is refused. Primary capture stays here; the
|
||||
library lists the sources and does not fetch them.
|
||||
- The library gained the `sources --repo` discovery command.
|
||||
- Acceptance was verified against a temporary copy of the registry: a
|
||||
hypothetical `llm-connect` subscription to `ai.pricing` matched
|
||||
`ir-anthropic-pricing` and `ir-openrouter-models`. No real second consumer
|
||||
is subscribed yet, and none was registered on another repo's behalf.
|
||||
|
||||
## Run a week end to end, then retire the website-pull record
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue