kushi-agents 6.2.0 → 6.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kushi-agents",
3
- "version": "6.2.0",
3
+ "version": "6.2.1",
4
4
  "description": "Install Kushi — multi-source project evidence agent with Comprehensive Structured Capture (CSC) into weekly-only files across Email, Teams, OneNote, Loop, SharePoint, Meetings, CRM, ADO. Meetings retain a sibling verbatim/ audit folder. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -109,6 +109,19 @@ async function main() {
109
109
  await loadConfig(projectRoot, args.alias);
110
110
  const weekStart = args.week || ymd(currentIsoMonday());
111
111
 
112
+ // Validate entity is a Teams meeting join URL or meeting ID (not a meeting subject
113
+ // from discover fallback). Subjects produce 403/404 from Graph onlineMeetings.
114
+ // Fixture mode bypasses validation.
115
+ if (!args.fixture && !/^https?:\/\//i.test(args.entity) && !/^MS[a-z0-9_\-=]+$/i.test(args.entity)) {
116
+ await updateCell(projectRoot, args.alias, SOURCE, args.entity, weekStart, {
117
+ last_status: 'failed',
118
+ last_error: 'entity is not a Teams meeting join URL or meeting ID (subject fallback from discover)',
119
+ });
120
+ if (!args.dryRun) await emitLearningCandidate({ projectRoot, alias: args.alias, source: SOURCE, entity: args.entity, week: weekStart, error: { signature: 'entity-not-join-url', message: 'expected meetup-join URL or meeting ID', status: null }, context: { runner: 'pull-meetings' } });
121
+ emit({ source: SOURCE, entity: args.entity, week: weekStart, status: 'failed', errors: [{ signature: 'entity-not-join-url', message: `entity '${args.entity}' is not a Teams meeting join URL. Discover stored a meeting-subject fallback. Replace with a join URL like 'https://teams.microsoft.com/l/meetup-join/...' in boundaries.yml meetings.joinUrls.` }] });
122
+ return 0;
123
+ }
124
+
112
125
  const client = await buildClient({ fixture: args.fixture });
113
126
  const startedAt = new Date().toISOString();
114
127
 
@@ -126,6 +126,20 @@ async function main() {
126
126
  const weekStart = args.week || ymd(currentIsoMonday());
127
127
  const { fromIso, toIso } = weekBounds(weekStart);
128
128
 
129
+ // Validate entity is a OneNote section file ID (hex with dashes, 20+ chars),
130
+ // not a page title from discover fallback. Display names break Graph URL
131
+ // construction with errors like "Resource not found for the segment '30 - HCA - account team'".
132
+ // Fixture mode bypasses validation.
133
+ if (!args.fixture && !/^[0-9a-f][0-9a-f\-]{20,}$/i.test(String(args.entity).trim())) {
134
+ await updateCell(projectRoot, args.alias, SOURCE, args.entity, weekStart, {
135
+ last_status: 'failed',
136
+ last_error: 'entity is not a OneNote section file ID (display name fallback from discover)',
137
+ });
138
+ if (!args.dryRun) await emitLearningCandidate({ projectRoot, alias: args.alias, source: SOURCE, entity: args.entity, week: weekStart, error: { signature: 'entity-not-section-id', message: 'expected hex section file ID like 1-abc123def456...', status: null }, context: { runner: 'pull-onenote' } });
139
+ emit({ source: SOURCE, entity: args.entity, week: weekStart, status: 'failed', errors: [{ signature: 'entity-not-section-id', message: `entity '${args.entity}' is not a OneNote section file ID. Discover stored a section-name fallback. Replace with a hex section_file_id in boundaries.yml onenote.section_file_ids.` }] });
140
+ return 0;
141
+ }
142
+
129
143
  const client = await buildClient({ fixture: args.fixture });
130
144
  const startedAt = new Date().toISOString();
131
145
 
@@ -96,6 +96,19 @@ async function main() {
96
96
  const weekStart = args.week || ymd(currentIsoMonday());
97
97
  const { fromIso, toIso } = weekBounds(weekStart);
98
98
 
99
+ // Validate entity is a Graph chat ID (not a display name from discover fallback).
100
+ // Display names break Graph URL construction with cryptic 400s like
101
+ // "Resource not found for the segment '12'". Fixture mode bypasses validation.
102
+ if (!args.fixture && !/^19:[\w\-+=.]+@(thread\.v[12]|unq\.gbl\.spaces)$/i.test(args.entity)) {
103
+ await updateCell(projectRoot, args.alias, SOURCE, args.entity, weekStart, {
104
+ last_status: 'failed',
105
+ last_error: 'entity is not a Graph chat ID (display name fallback from discover)',
106
+ });
107
+ if (!args.dryRun) await emitLearningCandidate({ projectRoot, alias: args.alias, source: SOURCE, entity: args.entity, week: weekStart, error: { signature: 'entity-not-chat-id', message: 'expected 19:xxx@thread.v2 or 19:xxx@unq.gbl.spaces', status: null }, context: { runner: 'pull-teams' } });
108
+ emit({ source: SOURCE, entity: args.entity, week: weekStart, status: 'failed', errors: [{ signature: 'entity-not-chat-id', message: `entity '${args.entity}' is not a Graph chat ID. Discover stored a display-name fallback. Replace with a chat ID like '19:xxx@thread.v2' in boundaries.yml teams.chats.` }] });
109
+ return 0;
110
+ }
111
+
99
112
  const client = await buildClient({ fixture: args.fixture });
100
113
  const startedAt = new Date().toISOString();
101
114