@codedrifters/configulator 0.0.301 → 0.0.303
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/lib/index.d.mts +256 -1
- package/lib/index.d.ts +257 -2
- package/lib/index.js +789 -49
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +780 -49
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -246,6 +246,10 @@ __export(index_exports, {
|
|
|
246
246
|
DEFAULT_STATE_FILE_PATH: () => DEFAULT_STATE_FILE_PATH,
|
|
247
247
|
DEFAULT_STATUS_LABELS: () => DEFAULT_STATUS_LABELS,
|
|
248
248
|
DEFAULT_TEARDOWN_BRANCH_PATTERNS: () => DEFAULT_TEARDOWN_BRANCH_PATTERNS,
|
|
249
|
+
DEFAULT_TEMPORAL_FRAMING_CADENCES: () => DEFAULT_TEMPORAL_FRAMING_CADENCES,
|
|
250
|
+
DEFAULT_TEMPORAL_FRAMING_EMIT_CHECKER: () => DEFAULT_TEMPORAL_FRAMING_EMIT_CHECKER,
|
|
251
|
+
DEFAULT_TEMPORAL_FRAMING_ENABLED: () => DEFAULT_TEMPORAL_FRAMING_ENABLED,
|
|
252
|
+
DEFAULT_TEMPORAL_FRAMING_PATHS: () => DEFAULT_TEMPORAL_FRAMING_PATHS,
|
|
249
253
|
DEFAULT_TYPE_LABELS: () => DEFAULT_TYPE_LABELS,
|
|
250
254
|
DEFAULT_UNBLOCK_COMMENT_TEMPLATE: () => DEFAULT_UNBLOCK_COMMENT_TEMPLATE,
|
|
251
255
|
DEFAULT_UNBLOCK_DEPENDENTS_ENABLED: () => DEFAULT_UNBLOCK_DEPENDENTS_ENABLED,
|
|
@@ -277,6 +281,7 @@ __export(index_exports, {
|
|
|
277
281
|
SUPPRESSED_WORKFLOW_RULE_NAMES: () => SUPPRESSED_WORKFLOW_RULE_NAMES,
|
|
278
282
|
SampleLang: () => SampleLang,
|
|
279
283
|
StarlightProject: () => StarlightProject,
|
|
284
|
+
TEMPORAL_FRAMING_CATEGORY_VALUES: () => TEMPORAL_FRAMING_CATEGORY_VALUES,
|
|
280
285
|
TIER_AWARE_BUNDLE_NAMES: () => TIER_AWARE_BUNDLE_NAMES,
|
|
281
286
|
TestRunner: () => TestRunner,
|
|
282
287
|
TsDocCoverageKind: () => TsDocCoverageKind,
|
|
@@ -400,6 +405,8 @@ __export(index_exports, {
|
|
|
400
405
|
renderSkillEvalsRunnerScript: () => renderSkillEvalsRunnerScript,
|
|
401
406
|
renderSourceTierExamples: () => renderSourceTierExamples,
|
|
402
407
|
renderStubIndexConventionRuleContent: () => renderStubIndexConventionRuleContent,
|
|
408
|
+
renderTemporalFramingCheckerScript: () => renderTemporalFramingCheckerScript,
|
|
409
|
+
renderTemporalFramingRuleContent: () => renderTemporalFramingRuleContent,
|
|
403
410
|
renderUnblockDependentsScript: () => renderUnblockDependentsScript,
|
|
404
411
|
renderUnblockDependentsSection: () => renderUnblockDependentsSection,
|
|
405
412
|
requirementsAnalystBundle: () => requirementsAnalystBundle,
|
|
@@ -425,6 +432,7 @@ __export(index_exports, {
|
|
|
425
432
|
resolveSharedEditing: () => resolveSharedEditing,
|
|
426
433
|
resolveSkillEvals: () => resolveSkillEvals,
|
|
427
434
|
resolveTemplateVariables: () => resolveTemplateVariables,
|
|
435
|
+
resolveTemporalFraming: () => resolveTemporalFraming,
|
|
428
436
|
resolveTypeScriptProjectOutdir: () => resolveTypeScriptProjectOutdir,
|
|
429
437
|
resolveUnblockDependents: () => resolveUnblockDependents,
|
|
430
438
|
runScan: () => runScan,
|
|
@@ -446,6 +454,7 @@ __export(index_exports, {
|
|
|
446
454
|
validateSharedEditingConfig: () => validateSharedEditingConfig,
|
|
447
455
|
validateSkillEvalsConfig: () => validateSkillEvalsConfig,
|
|
448
456
|
validateStarlightSingleton: () => validateStarlightSingleton,
|
|
457
|
+
validateTemporalFramingConfig: () => validateTemporalFramingConfig,
|
|
449
458
|
validateUnblockDependentsConfig: () => validateUnblockDependentsConfig,
|
|
450
459
|
vitestBundle: () => vitestBundle
|
|
451
460
|
});
|
|
@@ -3177,6 +3186,457 @@ function renderStubIndexConventionRuleContent() {
|
|
|
3177
3186
|
].join("\n");
|
|
3178
3187
|
}
|
|
3179
3188
|
|
|
3189
|
+
// src/agent/bundles/temporal-framing.ts
|
|
3190
|
+
var DEFAULT_TEMPORAL_FRAMING_ENABLED = true;
|
|
3191
|
+
var DEFAULT_TEMPORAL_FRAMING_PATHS = [
|
|
3192
|
+
"docs/src/content/docs/profiles/**/*.md",
|
|
3193
|
+
"docs/src/content/docs/industry-research/**/*.md",
|
|
3194
|
+
"docs/src/content/docs/software-research/**/*.md",
|
|
3195
|
+
"docs/src/content/docs/regulatory-research/**/*.md",
|
|
3196
|
+
"docs/src/content/docs/standards-research/**/*.md",
|
|
3197
|
+
"docs/src/content/docs/customer-research/**/*.md"
|
|
3198
|
+
];
|
|
3199
|
+
var TEMPORAL_FRAMING_CATEGORY_VALUES = [
|
|
3200
|
+
"ownership",
|
|
3201
|
+
"company-leadership",
|
|
3202
|
+
"regulatory-status",
|
|
3203
|
+
"litigation",
|
|
3204
|
+
"dated-metrics"
|
|
3205
|
+
];
|
|
3206
|
+
var DEFAULT_TEMPORAL_FRAMING_CADENCES = {
|
|
3207
|
+
ownership: 180,
|
|
3208
|
+
"company-leadership": 90,
|
|
3209
|
+
"regulatory-status": 30,
|
|
3210
|
+
litigation: 30,
|
|
3211
|
+
"dated-metrics": 180
|
|
3212
|
+
};
|
|
3213
|
+
var DEFAULT_TEMPORAL_FRAMING_EMIT_CHECKER = false;
|
|
3214
|
+
function resolveTemporalFraming(config) {
|
|
3215
|
+
const paths = config?.paths ?? DEFAULT_TEMPORAL_FRAMING_PATHS;
|
|
3216
|
+
assertValidPaths(paths);
|
|
3217
|
+
const cadences = resolveCadences(config?.cadences);
|
|
3218
|
+
return {
|
|
3219
|
+
enabled: config?.enabled ?? DEFAULT_TEMPORAL_FRAMING_ENABLED,
|
|
3220
|
+
paths,
|
|
3221
|
+
cadences,
|
|
3222
|
+
emitChecker: config?.emitChecker ?? DEFAULT_TEMPORAL_FRAMING_EMIT_CHECKER
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
function validateTemporalFramingConfig(config) {
|
|
3226
|
+
return resolveTemporalFraming(config);
|
|
3227
|
+
}
|
|
3228
|
+
function renderTemporalFramingRuleContent(tf) {
|
|
3229
|
+
if (!tf.enabled) {
|
|
3230
|
+
return [
|
|
3231
|
+
"# Temporal Framing Convention",
|
|
3232
|
+
"",
|
|
3233
|
+
"**Temporal framing is not enforced in this project.** Agents are",
|
|
3234
|
+
"not required to add `as of [date]` qualifiers to time-sensitive",
|
|
3235
|
+
"claims, and refresh passes do not use a mechanical grep to find",
|
|
3236
|
+
"stale framing. Staleness is caught by review and downstream user",
|
|
3237
|
+
"reports alone.",
|
|
3238
|
+
"",
|
|
3239
|
+
"Enable the convention via",
|
|
3240
|
+
"`AgentConfigOptions.temporalFraming.enabled = true`."
|
|
3241
|
+
].join("\n");
|
|
3242
|
+
}
|
|
3243
|
+
const lines = [
|
|
3244
|
+
"# Temporal Framing Convention",
|
|
3245
|
+
"",
|
|
3246
|
+
"Every factual claim that can change over time MUST carry an inline",
|
|
3247
|
+
"`as of [YYYY-MM-DD]` or `as of [Month YYYY]` qualifier on the",
|
|
3248
|
+
"**first** occurrence of the claim in the document. Once qualified",
|
|
3249
|
+
"once, subsequent references to the same fact in the same document",
|
|
3250
|
+
"do not need to repeat the qualifier \u2014 the first qualifier governs",
|
|
3251
|
+
"the document's snapshot date for that fact.",
|
|
3252
|
+
"",
|
|
3253
|
+
"The qualifier is mechanical, not editorial. Refresh agents grep",
|
|
3254
|
+
"for `as of ` to find the time-bounded claims; without the",
|
|
3255
|
+
"qualifier, a refresh pass has no cheap way to tell stale framing",
|
|
3256
|
+
"from stable facts.",
|
|
3257
|
+
"",
|
|
3258
|
+
"## What counts as time-sensitive",
|
|
3259
|
+
"",
|
|
3260
|
+
"A claim is time-sensitive (and must carry the qualifier) when it",
|
|
3261
|
+
"describes a state that **a single public event could invalidate",
|
|
3262
|
+
"within the document's expected refresh cadence**. Five recurring",
|
|
3263
|
+
"categories cover the common cases:",
|
|
3264
|
+
"",
|
|
3265
|
+
"| Category | Examples |",
|
|
3266
|
+
"|----------|----------|",
|
|
3267
|
+
'| **Ownership and investors** | "co-owned by X, Y, Z"; "majority-owned by"; "minority stake held by"; cap table; current investor lists |',
|
|
3268
|
+
'| **Leadership tenure** | "X is CEO"; "X chairs the committee"; "X serves as"; current board chair; current executive team |',
|
|
3269
|
+
'| **Regulatory or rule status** | "is in force"; "under public consultation"; "pending finalization"; "currently enjoined"; "under active investigation" |',
|
|
3270
|
+
'| **Litigation and enforcement** | "is under active scrutiny"; "investigation is ongoing"; "appeal is pending"; "consent decree remains in effect" |',
|
|
3271
|
+
'| **Pricing, valuation, and metrics** | "valued at $XB"; "annual revenue ~$X"; "processes N transactions"; "serves N customers" \u2014 when the figure is sourced from a dated press release or filing |',
|
|
3272
|
+
"",
|
|
3273
|
+
"A claim is **not** time-sensitive (and does not need the qualifier)",
|
|
3274
|
+
"when it describes a historical event, a statutory text, or a",
|
|
3275
|
+
"structural fact that does not change without amendment. Examples",
|
|
3276
|
+
"that are safe without a qualifier:",
|
|
3277
|
+
"",
|
|
3278
|
+
'- "Acquired by Advent International in May 2019" (a dated historical event \u2014 the date itself is the anchor)',
|
|
3279
|
+
'- "21 CFR Part 11 establishes criteria for electronic records" (statutory text)',
|
|
3280
|
+
'- "Headquartered in Dallas, Texas" (changes only on a documented move)',
|
|
3281
|
+
'- "Founded in 1999" (a one-time event)',
|
|
3282
|
+
"",
|
|
3283
|
+
"## Format",
|
|
3284
|
+
"",
|
|
3285
|
+
"Two acceptable forms:",
|
|
3286
|
+
"",
|
|
3287
|
+
"```markdown",
|
|
3288
|
+
"As of May 2026, Acme is owned by ...",
|
|
3289
|
+
"... Acme's CEO (as of May 2026) is ...",
|
|
3290
|
+
"```",
|
|
3291
|
+
"",
|
|
3292
|
+
"Use the granularity that matches the source citation:",
|
|
3293
|
+
"",
|
|
3294
|
+
"- `as of YYYY-MM-DD` when the source is a specific filing, press release, or court order with a precise date.",
|
|
3295
|
+
"- `as of Month YYYY` when the source is a self-reported page (e.g., a company's `About` page) where only the month-of-snapshot is meaningful.",
|
|
3296
|
+
"- Do **not** write `as of 2026` (year-only) \u2014 that's too coarse to drive a refresh decision.",
|
|
3297
|
+
"",
|
|
3298
|
+
"## Examples",
|
|
3299
|
+
"",
|
|
3300
|
+
"### Wrong \u2014 present-tense framing of a state that can change",
|
|
3301
|
+
"",
|
|
3302
|
+
"```markdown",
|
|
3303
|
+
"Availity is co-owned by major Blue Cross Blue Shield plans",
|
|
3304
|
+
"(HCSC, Elevance Health/Anthem, BCBS Minnesota), Francisco",
|
|
3305
|
+
"Partners, Novo Holdings, and Prettybrook Partners.",
|
|
3306
|
+
"```",
|
|
3307
|
+
"",
|
|
3308
|
+
"This claim might have been true at a specific date but goes stale",
|
|
3309
|
+
"as soon as any one investor exits. A refresh agent has no",
|
|
3310
|
+
"mechanical signal that the claim is time-sensitive.",
|
|
3311
|
+
"",
|
|
3312
|
+
"### Right \u2014 explicit qualifier on the first claim",
|
|
3313
|
+
"",
|
|
3314
|
+
"```markdown",
|
|
3315
|
+
"As of May 2026, Availity is co-owned by a mix of health plan",
|
|
3316
|
+
"strategic investors (HCSC, Elevance Health/Anthem, BCBS",
|
|
3317
|
+
"Minnesota, Humana, GuideWell) and financial sponsors (Novo",
|
|
3318
|
+
"Holdings, Prettybrook Partners).",
|
|
3319
|
+
"```",
|
|
3320
|
+
"",
|
|
3321
|
+
"The `as of May 2026` anchors the document's snapshot for the",
|
|
3322
|
+
"ownership claim. Subsequent references to Availity's ownership in",
|
|
3323
|
+
"the same document inherit that snapshot date.",
|
|
3324
|
+
"",
|
|
3325
|
+
"## When the convention applies",
|
|
3326
|
+
"",
|
|
3327
|
+
"The rule applies to every Markdown document any agent writes under",
|
|
3328
|
+
"the following path globs:",
|
|
3329
|
+
"",
|
|
3330
|
+
...tf.paths.map((p) => `- \`${p}\``),
|
|
3331
|
+
"",
|
|
3332
|
+
"It does **not** apply to:",
|
|
3333
|
+
"",
|
|
3334
|
+
"- Meeting notes (`meetings/**`) \u2014 the meeting date itself is the implicit `as of` anchor.",
|
|
3335
|
+
"- Requirement documents (`requirements/**`) \u2014 formal requirements are versioned and dated via their own frontmatter.",
|
|
3336
|
+
"- The project context page (`project-context.md`) \u2014 maintained as a living snapshot under direct human review.",
|
|
3337
|
+
"",
|
|
3338
|
+
"## Refresh-agent behaviour",
|
|
3339
|
+
"",
|
|
3340
|
+
"A refresh pass on any covered document MUST:",
|
|
3341
|
+
"",
|
|
3342
|
+
"1. Grep for `as of ` (case-insensitive) in the document.",
|
|
3343
|
+
"2. For each qualifier, compute `today - <qualifier-date>` in days.",
|
|
3344
|
+
"3. Classify each qualified claim against the category-specific",
|
|
3345
|
+
" cadence table below.",
|
|
3346
|
+
"4. Re-verify every claim whose qualifier is older than its cadence.",
|
|
3347
|
+
"5. Update the qualifier to today's date on every re-verified claim",
|
|
3348
|
+
" that remains accurate.",
|
|
3349
|
+
"6. Treat documents that omit qualifiers entirely as needing",
|
|
3350
|
+
" **back-fill** before any other verification is attempted \u2014 the",
|
|
3351
|
+
" absence of qualifiers is itself a refresh finding.",
|
|
3352
|
+
"",
|
|
3353
|
+
"### Refresh cadence table",
|
|
3354
|
+
"",
|
|
3355
|
+
"Each category carries its own refresh cadence in days. Faster-decay",
|
|
3356
|
+
"claims (regulatory status, litigation) refresh more often;",
|
|
3357
|
+
"slower-decay claims (ownership, dated metrics) refresh less often.",
|
|
3358
|
+
"",
|
|
3359
|
+
"| Category | Cadence (days) |",
|
|
3360
|
+
"|----------|----------------|",
|
|
3361
|
+
`| \`ownership\` | ${tf.cadences.ownership} |`,
|
|
3362
|
+
`| \`company-leadership\` | ${tf.cadences["company-leadership"]} |`,
|
|
3363
|
+
`| \`regulatory-status\` | ${tf.cadences["regulatory-status"]} |`,
|
|
3364
|
+
`| \`litigation\` | ${tf.cadences.litigation} |`,
|
|
3365
|
+
`| \`dated-metrics\` | ${tf.cadences["dated-metrics"]} |`,
|
|
3366
|
+
"",
|
|
3367
|
+
"Consumers may override any subset of cadences via",
|
|
3368
|
+
"`AgentConfigOptions.temporalFraming.cadences`. Unspecified",
|
|
3369
|
+
"categories fall through to the defaults above."
|
|
3370
|
+
];
|
|
3371
|
+
if (tf.emitChecker) {
|
|
3372
|
+
lines.push(
|
|
3373
|
+
"",
|
|
3374
|
+
"## Lint",
|
|
3375
|
+
"",
|
|
3376
|
+
"The bundled `.claude/procedures/check-temporal-framing.sh` helper",
|
|
3377
|
+
"enforces the rule mechanically. Given a set of changed files (as",
|
|
3378
|
+
"positional arguments or a newline-separated list on stdin), it",
|
|
3379
|
+
"fails non-zero when any file matches a configured path glob and",
|
|
3380
|
+
"carries time-sensitive framing without an `as of ` qualifier.",
|
|
3381
|
+
"",
|
|
3382
|
+
"```bash",
|
|
3383
|
+
"# Pre-commit (staged files):",
|
|
3384
|
+
"git diff --cached --name-only \\",
|
|
3385
|
+
" | .claude/procedures/check-temporal-framing.sh",
|
|
3386
|
+
"",
|
|
3387
|
+
"# CI (branch-vs-base):",
|
|
3388
|
+
"git diff --name-only origin/main...HEAD \\",
|
|
3389
|
+
" | .claude/procedures/check-temporal-framing.sh",
|
|
3390
|
+
"```",
|
|
3391
|
+
"",
|
|
3392
|
+
"The lint is a coarse signal \u2014 it flags files that look",
|
|
3393
|
+
"time-sensitive but carry no qualifier. Authors and reviewers are",
|
|
3394
|
+
"still expected to validate that each qualifier is correctly",
|
|
3395
|
+
"anchored to its source citation."
|
|
3396
|
+
);
|
|
3397
|
+
}
|
|
3398
|
+
lines.push(
|
|
3399
|
+
"",
|
|
3400
|
+
"## Out of scope",
|
|
3401
|
+
"",
|
|
3402
|
+
"- Auto-generating qualifiers from source-citation dates. Authors",
|
|
3403
|
+
" read the source and write the qualifier explicitly.",
|
|
3404
|
+
"- Replacing existing dated frontmatter conventions. Frontmatter",
|
|
3405
|
+
" `date:` fields anchor the document's overall snapshot; the",
|
|
3406
|
+
" inline qualifier anchors individual time-sensitive claims so a",
|
|
3407
|
+
" refresh pass can re-verify them without re-reading the whole",
|
|
3408
|
+
" document.",
|
|
3409
|
+
"- Back-filling pre-existing documents in bulk. Refresh passes",
|
|
3410
|
+
" back-fill qualifiers on the documents they touch; bulk",
|
|
3411
|
+
" back-fill is a downstream consumer cleanup task, not a",
|
|
3412
|
+
" configulator change."
|
|
3413
|
+
);
|
|
3414
|
+
return lines.join("\n");
|
|
3415
|
+
}
|
|
3416
|
+
function renderTemporalFramingCheckerScript(tf) {
|
|
3417
|
+
const patternsLiteral = tf.paths.map((p) => ` ${JSON.stringify(p)}`).join("\n");
|
|
3418
|
+
return [
|
|
3419
|
+
"#!/usr/bin/env bash",
|
|
3420
|
+
"# check-temporal-framing.sh \u2014 Enforce the temporal-framing convention.",
|
|
3421
|
+
"#",
|
|
3422
|
+
"# Usage:",
|
|
3423
|
+
"# .claude/procedures/check-temporal-framing.sh <file>...",
|
|
3424
|
+
"# git diff --name-only HEAD | .claude/procedures/check-temporal-framing.sh",
|
|
3425
|
+
"#",
|
|
3426
|
+
"# Fails non-zero when any changed file matches a configured path",
|
|
3427
|
+
"# pattern AND contains present-tense framing of a time-sensitive",
|
|
3428
|
+
"# claim category AND does NOT carry an `as of ` qualifier anywhere",
|
|
3429
|
+
"# in the file. The lint is file-level, not line-level \u2014 the cheap",
|
|
3430
|
+
"# coarse signal is enough to catch the failure mode the convention",
|
|
3431
|
+
"# targets, and a finer-grained check would carry too much false",
|
|
3432
|
+
"# positive cost.",
|
|
3433
|
+
"#",
|
|
3434
|
+
"# The path patterns are rendered from the consumer's",
|
|
3435
|
+
"# TemporalFramingConfig at synth time \u2014 do not edit by hand;",
|
|
3436
|
+
"# regenerate via `pnpm exec projen`.",
|
|
3437
|
+
"#",
|
|
3438
|
+
"# Patterns support the `**` recursive-segment wildcard even though",
|
|
3439
|
+
"# bash's native `[[ $file == $glob ]]` pattern matching does not:",
|
|
3440
|
+
"# each glob is converted to a POSIX-extended regex internally and",
|
|
3441
|
+
"# matched with `=~`, so the script works uniformly on bash 3.2",
|
|
3442
|
+
"# (macOS default) and bash 4+ (Linux / CI).",
|
|
3443
|
+
"",
|
|
3444
|
+
"set -uo pipefail",
|
|
3445
|
+
"",
|
|
3446
|
+
"err() {",
|
|
3447
|
+
' printf "check-temporal-framing.sh: %s\\n" "$*" >&2',
|
|
3448
|
+
"}",
|
|
3449
|
+
"",
|
|
3450
|
+
"# Path glob patterns. Translated to anchored POSIX-extended regexes",
|
|
3451
|
+
"# at runtime by `glob_to_regex` below so `**` matches recursively",
|
|
3452
|
+
"# across path segments.",
|
|
3453
|
+
"path_patterns=(",
|
|
3454
|
+
patternsLiteral,
|
|
3455
|
+
")",
|
|
3456
|
+
"",
|
|
3457
|
+
"# Triggers \u2014 present-tense framing keywords that indicate a",
|
|
3458
|
+
"# time-sensitive claim category. Match is case-insensitive and",
|
|
3459
|
+
"# whole-word; the keyword list is deliberately small (one or two",
|
|
3460
|
+
"# canonical phrases per category) to keep false positives low.",
|
|
3461
|
+
"triggers=(",
|
|
3462
|
+
' "is owned by"',
|
|
3463
|
+
' "co-owned by"',
|
|
3464
|
+
' "majority-owned by"',
|
|
3465
|
+
' "minority-owned by"',
|
|
3466
|
+
' "is co-owned"',
|
|
3467
|
+
' "is currently"',
|
|
3468
|
+
' "currently chairs"',
|
|
3469
|
+
' "currently serves"',
|
|
3470
|
+
' "is in force"',
|
|
3471
|
+
' "under public consultation"',
|
|
3472
|
+
' "under active investigation"',
|
|
3473
|
+
' "is pending"',
|
|
3474
|
+
' "investigation is ongoing"',
|
|
3475
|
+
")",
|
|
3476
|
+
"",
|
|
3477
|
+
"# Convert a bash-style glob into an anchored POSIX-extended regex:",
|
|
3478
|
+
"# **/ \u2192 (.+/)? (zero or more path segments plus trailing slash)",
|
|
3479
|
+
"# ** \u2192 .* (anywhere, including `/`)",
|
|
3480
|
+
"# * \u2192 [^/]* (single path segment)",
|
|
3481
|
+
"# ? \u2192 [^/] (single non-slash char)",
|
|
3482
|
+
"glob_to_regex() {",
|
|
3483
|
+
' local glob="$1"',
|
|
3484
|
+
' local regex=""',
|
|
3485
|
+
" local i=0",
|
|
3486
|
+
" local len=${#glob}",
|
|
3487
|
+
" while (( i < len )); do",
|
|
3488
|
+
' local c="${glob:i:1}"',
|
|
3489
|
+
' if [[ "$c" == "*" ]]; then',
|
|
3490
|
+
' local next="${glob:i+1:1}"',
|
|
3491
|
+
' if [[ "$next" == "*" ]]; then',
|
|
3492
|
+
' local after="${glob:i+2:1}"',
|
|
3493
|
+
' if [[ "$after" == "/" ]]; then',
|
|
3494
|
+
' regex+="(.+/)?"',
|
|
3495
|
+
" i=$((i+3))",
|
|
3496
|
+
" continue",
|
|
3497
|
+
" fi",
|
|
3498
|
+
' regex+=".*"',
|
|
3499
|
+
" i=$((i+2))",
|
|
3500
|
+
" continue",
|
|
3501
|
+
" fi",
|
|
3502
|
+
' regex+="[^/]*"',
|
|
3503
|
+
" i=$((i+1))",
|
|
3504
|
+
" continue",
|
|
3505
|
+
" fi",
|
|
3506
|
+
' if [[ "$c" == "?" ]]; then',
|
|
3507
|
+
' regex+="[^/]"',
|
|
3508
|
+
" i=$((i+1))",
|
|
3509
|
+
" continue",
|
|
3510
|
+
" fi",
|
|
3511
|
+
' case "$c" in',
|
|
3512
|
+
" .|+|\\(|\\)|\\[|\\]|\\{|\\}|\\||\\^|\\$|\\\\)",
|
|
3513
|
+
' regex+="\\\\$c"',
|
|
3514
|
+
" ;;",
|
|
3515
|
+
" *)",
|
|
3516
|
+
' regex+="$c"',
|
|
3517
|
+
" ;;",
|
|
3518
|
+
" esac",
|
|
3519
|
+
" i=$((i+1))",
|
|
3520
|
+
" done",
|
|
3521
|
+
' printf "^%s$" "$regex"',
|
|
3522
|
+
"}",
|
|
3523
|
+
"",
|
|
3524
|
+
"# Check whether $file matches any of the configured path patterns.",
|
|
3525
|
+
"# Returns 0 on match, 1 otherwise.",
|
|
3526
|
+
"matches_any_pattern() {",
|
|
3527
|
+
' local file="$1"',
|
|
3528
|
+
" local pattern regex",
|
|
3529
|
+
' for pattern in "${path_patterns[@]}"; do',
|
|
3530
|
+
' regex=$(glob_to_regex "$pattern")',
|
|
3531
|
+
' if [[ "$file" =~ $regex ]]; then',
|
|
3532
|
+
" return 0",
|
|
3533
|
+
" fi",
|
|
3534
|
+
" done",
|
|
3535
|
+
" return 1",
|
|
3536
|
+
"}",
|
|
3537
|
+
"",
|
|
3538
|
+
"# Check whether $file contains any present-tense framing trigger",
|
|
3539
|
+
"# without an `as of ` qualifier anywhere in the file. Returns 0",
|
|
3540
|
+
"# when the file is OK (no triggers, or triggers + qualifier), 1",
|
|
3541
|
+
"# when the file is malformed (triggers + no qualifier).",
|
|
3542
|
+
"file_ok() {",
|
|
3543
|
+
' local file="$1"',
|
|
3544
|
+
' [[ ! -f "$file" ]] && return 0',
|
|
3545
|
+
" local found_trigger=0",
|
|
3546
|
+
" local trigger",
|
|
3547
|
+
' for trigger in "${triggers[@]}"; do',
|
|
3548
|
+
' if grep -qi -- "$trigger" "$file"; then',
|
|
3549
|
+
" found_trigger=1",
|
|
3550
|
+
" break",
|
|
3551
|
+
" fi",
|
|
3552
|
+
" done",
|
|
3553
|
+
" if [[ $found_trigger -eq 0 ]]; then",
|
|
3554
|
+
" return 0",
|
|
3555
|
+
" fi",
|
|
3556
|
+
' if grep -qi -- "as of " "$file"; then',
|
|
3557
|
+
" return 0",
|
|
3558
|
+
" fi",
|
|
3559
|
+
" return 1",
|
|
3560
|
+
"}",
|
|
3561
|
+
"",
|
|
3562
|
+
"# Read the file list from positional args or stdin.",
|
|
3563
|
+
"files=()",
|
|
3564
|
+
"if [[ $# -gt 0 ]]; then",
|
|
3565
|
+
' files=("$@")',
|
|
3566
|
+
"else",
|
|
3567
|
+
" while IFS= read -r line; do",
|
|
3568
|
+
' [[ -n "$line" ]] && files+=("$line")',
|
|
3569
|
+
" done",
|
|
3570
|
+
"fi",
|
|
3571
|
+
"",
|
|
3572
|
+
"if [[ ${#files[@]} -eq 0 ]]; then",
|
|
3573
|
+
" exit 0",
|
|
3574
|
+
"fi",
|
|
3575
|
+
"",
|
|
3576
|
+
"violations=0",
|
|
3577
|
+
'for file in "${files[@]}"; do',
|
|
3578
|
+
' if ! matches_any_pattern "$file"; then',
|
|
3579
|
+
" continue",
|
|
3580
|
+
" fi",
|
|
3581
|
+
' if ! file_ok "$file"; then',
|
|
3582
|
+
' err "$file: contains time-sensitive framing without an \\"as of\\" qualifier"',
|
|
3583
|
+
" violations=$((violations+1))",
|
|
3584
|
+
" fi",
|
|
3585
|
+
"done",
|
|
3586
|
+
"",
|
|
3587
|
+
"if [[ $violations -gt 0 ]]; then",
|
|
3588
|
+
' err "found $violations file(s) violating the temporal-framing convention"',
|
|
3589
|
+
" exit 1",
|
|
3590
|
+
"fi",
|
|
3591
|
+
"exit 0"
|
|
3592
|
+
].join("\n");
|
|
3593
|
+
}
|
|
3594
|
+
function assertValidPaths(paths) {
|
|
3595
|
+
if (!Array.isArray(paths)) {
|
|
3596
|
+
throw new Error(
|
|
3597
|
+
`TemporalFramingConfig.paths must be an array; got ${typeof paths}`
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3600
|
+
for (let i = 0; i < paths.length; i++) {
|
|
3601
|
+
const entry = paths[i];
|
|
3602
|
+
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
3603
|
+
throw new Error(
|
|
3604
|
+
`TemporalFramingConfig.paths[${i}] must be a non-empty string; got ${JSON.stringify(
|
|
3605
|
+
entry
|
|
3606
|
+
)}`
|
|
3607
|
+
);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
function resolveCadences(supplied) {
|
|
3612
|
+
const merged = {
|
|
3613
|
+
...DEFAULT_TEMPORAL_FRAMING_CADENCES
|
|
3614
|
+
};
|
|
3615
|
+
if (supplied !== void 0) {
|
|
3616
|
+
for (const category of TEMPORAL_FRAMING_CATEGORY_VALUES) {
|
|
3617
|
+
const value = supplied[category];
|
|
3618
|
+
if (value === void 0) {
|
|
3619
|
+
continue;
|
|
3620
|
+
}
|
|
3621
|
+
assertValidCadence(value, category);
|
|
3622
|
+
merged[category] = value;
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
return merged;
|
|
3626
|
+
}
|
|
3627
|
+
function assertValidCadence(value, field) {
|
|
3628
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
3629
|
+
throw new Error(
|
|
3630
|
+
`TemporalFramingConfig.cadences.${field} must be a positive integer; got ${value}`
|
|
3631
|
+
);
|
|
3632
|
+
}
|
|
3633
|
+
if (value <= 0) {
|
|
3634
|
+
throw new Error(
|
|
3635
|
+
`TemporalFramingConfig.cadences.${field} must be a positive integer; got ${value}`
|
|
3636
|
+
);
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
|
|
3180
3640
|
// src/agent/bundles/base.ts
|
|
3181
3641
|
var createPackageSkill = {
|
|
3182
3642
|
name: "create-package",
|
|
@@ -4286,6 +4746,16 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
4286
4746
|
},
|
|
4287
4747
|
tags: ["workflow"]
|
|
4288
4748
|
},
|
|
4749
|
+
{
|
|
4750
|
+
name: "temporal-framing-convention",
|
|
4751
|
+
description: "Temporal-framing convention: every agent-authored time-sensitive factual claim (ownership, leadership tenure, regulatory status, litigation, dated metrics) carries an inline `as of [YYYY-MM-DD]` or `as of [Month YYYY]` qualifier on first occurrence so refresh agents have a mechanical signal for which claims to re-verify.",
|
|
4752
|
+
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
4753
|
+
content: renderTemporalFramingRuleContent(resolveTemporalFraming()),
|
|
4754
|
+
platforms: {
|
|
4755
|
+
cursor: { exclude: true }
|
|
4756
|
+
},
|
|
4757
|
+
tags: ["workflow"]
|
|
4758
|
+
},
|
|
4289
4759
|
{
|
|
4290
4760
|
name: "skill-evals",
|
|
4291
4761
|
description: "Skill eval harness contract: declarative prompt/expected-output regression suites per skill at `<skillsRoot>/<skill-name>/evals/evals.json`, parameterised by a shared product-context fixture so the same eval shape works across every configulator-consuming project without forking fixtures.",
|
|
@@ -6529,19 +6999,29 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
6529
6999
|
" - <source URL> \u2014 <date accessed>",
|
|
6530
7000
|
" ```",
|
|
6531
7001
|
"",
|
|
6532
|
-
"4. **
|
|
7002
|
+
"4. **Apply the `temporal-framing-convention` rule.** Every",
|
|
7003
|
+
" time-sensitive factual claim in the profile \u2014 ownership,",
|
|
7004
|
+
" leadership tenure, regulatory status, litigation, dated metrics",
|
|
7005
|
+
" \u2014 must carry an inline `as of [YYYY-MM-DD]` or `as of [Month",
|
|
7006
|
+
" YYYY]` qualifier on its **first** occurrence in the document.",
|
|
7007
|
+
" Use the granularity that matches the source citation (precise",
|
|
7008
|
+
" date for a filing or press release; month for a self-reported",
|
|
7009
|
+
" `About` page). The qualifier is mechanical, not editorial \u2014 it",
|
|
7010
|
+
" is the signal Phase 5 (Refresh) uses to grep for stale claims.",
|
|
7011
|
+
"",
|
|
7012
|
+
"5. **Decide whether a follow-up issue is warranted.** Create a",
|
|
6533
7013
|
" `company:followup` issue (depending on this draft issue) only if",
|
|
6534
7014
|
" the profile lists at least one follow-up candidate. Otherwise,",
|
|
6535
7015
|
" note in the draft issue's closing comment that no follow-up is",
|
|
6536
7016
|
" needed.",
|
|
6537
7017
|
"",
|
|
6538
|
-
"
|
|
7018
|
+
"6. **File a `company:match` issue** (depending on this draft issue)",
|
|
6539
7019
|
" so the profile gets enriched against the project's business-model",
|
|
6540
7020
|
" canvases. Skip the match issue only when the invoking project has",
|
|
6541
7021
|
" no business-model canvases at all (Phase 4 will detect and exit",
|
|
6542
7022
|
" gracefully in that case).",
|
|
6543
7023
|
"",
|
|
6544
|
-
"
|
|
7024
|
+
"7. **Commit and push** the profile file. Close the draft issue.",
|
|
6545
7025
|
"",
|
|
6546
7026
|
"---",
|
|
6547
7027
|
"",
|
|
@@ -6780,26 +7260,51 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
6780
7260
|
" the issue body does not set `force: true`, close the issue with",
|
|
6781
7261
|
" a short comment and stop \u2014 do not burn the search budget.",
|
|
6782
7262
|
"",
|
|
6783
|
-
"3. **
|
|
7263
|
+
"3. **Grep for `as of ` qualifiers.** Per the",
|
|
7264
|
+
" `temporal-framing-convention` rule, every time-sensitive claim in",
|
|
7265
|
+
" the profile carries an inline `as of [YYYY-MM-DD]` or `as of",
|
|
7266
|
+
" [Month YYYY]` qualifier. Build the list of qualified claims and",
|
|
7267
|
+
" compute the age (in days) of each one against today's date.",
|
|
7268
|
+
" Classify each claim against the cadence table in the",
|
|
7269
|
+
" `temporal-framing-convention` rule:",
|
|
7270
|
+
" - **company-leadership** \u2014 90 days",
|
|
7271
|
+
" - **regulatory-status** \u2014 30 days",
|
|
7272
|
+
" - **litigation** \u2014 30 days",
|
|
7273
|
+
" - **ownership** \u2014 180 days",
|
|
7274
|
+
" - **dated-metrics** \u2014 180 days",
|
|
7275
|
+
"",
|
|
7276
|
+
" Treat every qualifier older than its category's cadence as a",
|
|
7277
|
+
" re-verification target for the targeted-search step below. If the",
|
|
7278
|
+
" profile contains **no** `as of ` qualifiers at all, treat the",
|
|
7279
|
+
" entire profile as needing **back-fill** \u2014 apply the convention to",
|
|
7280
|
+
" every time-sensitive claim before running the targeted searches.",
|
|
7281
|
+
"",
|
|
7282
|
+
"4. **Run 4\u20136 targeted searches.** Focus on the categories surfaced by",
|
|
7283
|
+
" the qualifier grep (step 3), plus any additional signals worth a",
|
|
7284
|
+
" refresh:",
|
|
6784
7285
|
" - `<company name>` + recent news, press releases, or blog posts",
|
|
6785
7286
|
" - Product launches, feature changes, or pricing updates",
|
|
6786
7287
|
" - Funding rounds, acquisitions, or material ownership changes",
|
|
6787
7288
|
" - Leadership changes (CEO, CTO, CPO, notable departures/arrivals)",
|
|
6788
7289
|
" - New partnerships, certifications, or regulatory milestones",
|
|
6789
7290
|
"",
|
|
6790
|
-
"
|
|
7291
|
+
"5. **Update the profile in place.** Edit the affected sections with",
|
|
6791
7292
|
" the new information. Cite every new claim. Preserve the slug and",
|
|
6792
7293
|
" the original `parent_issue` field. Bump the `date` frontmatter to",
|
|
6793
|
-
" today's date.",
|
|
7294
|
+
" today's date. **Update the `as of` qualifier** on every claim you",
|
|
7295
|
+
" re-verified \u2014 change the date to today's date when the claim",
|
|
7296
|
+
" still holds; rewrite the framing when the claim has changed.",
|
|
7297
|
+
" Surface unverifiable or stale-and-changed claims through",
|
|
7298
|
+
" `## Risks / Open Questions` rather than silently dropping them.",
|
|
6794
7299
|
"",
|
|
6795
|
-
"
|
|
7300
|
+
"6. **Do not silently re-type the company.** If the refresh surfaces",
|
|
6796
7301
|
" evidence that the company's primary type has changed (e.g., an",
|
|
6797
7302
|
" industry-player that now sells a directly competing product),",
|
|
6798
7303
|
" flag it in `## Risks / Open Questions` and stop \u2014 do **not**",
|
|
6799
7304
|
" rewrite the `company_type` frontmatter without an explicit",
|
|
6800
7305
|
" override in the refresh issue body (`retype: <new type>`).",
|
|
6801
7306
|
"",
|
|
6802
|
-
"
|
|
7307
|
+
"7. **Append a revision-history row.** Summarize the delta in one",
|
|
6803
7308
|
" line:",
|
|
6804
7309
|
"",
|
|
6805
7310
|
" ```markdown",
|
|
@@ -6814,14 +7319,14 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
6814
7319
|
" | YYYY-MM-DD | Refreshed: no material change |",
|
|
6815
7320
|
" ```",
|
|
6816
7321
|
"",
|
|
6817
|
-
"
|
|
7322
|
+
"8. **Update reference entries** (if the project tracks company",
|
|
6818
7323
|
" references under research directories). If the company's",
|
|
6819
7324
|
" relevance to a research area has shifted \u2014 for example, it is no",
|
|
6820
7325
|
" longer a live competitor, or it now plays in a new segment \u2014",
|
|
6821
7326
|
" update the corresponding entry under `referencedIn` and the",
|
|
6822
7327
|
" research-area doc that links to this profile.",
|
|
6823
7328
|
"",
|
|
6824
|
-
"
|
|
7329
|
+
"9. **Commit and push.** Close the refresh issue with a short comment",
|
|
6825
7330
|
" summarizing the delta (or `no material change`).",
|
|
6826
7331
|
"",
|
|
6827
7332
|
"---",
|
|
@@ -10991,14 +11496,17 @@ var maintenanceAuditBundle = buildMaintenanceAuditBundle();
|
|
|
10991
11496
|
function buildMeetingAnalystSubAgent(tier) {
|
|
10992
11497
|
return {
|
|
10993
11498
|
name: "meeting-analyst",
|
|
10994
|
-
description: "Processes meeting transcripts through a 4-phase pipeline: extract, notes, draft, and link",
|
|
11499
|
+
description: "Processes meeting notes and transcripts (sibling-tree layout) through a 4-phase pipeline: extract, notes, draft, and link",
|
|
10995
11500
|
model: tier,
|
|
10996
11501
|
maxTurns: 80,
|
|
10997
11502
|
platforms: { cursor: { exclude: true } },
|
|
10998
11503
|
prompt: [
|
|
10999
11504
|
"# Meeting Analyst Agent",
|
|
11000
11505
|
"",
|
|
11001
|
-
"You process meeting transcripts through a structured
|
|
11506
|
+
"You process meeting notes and transcripts through a structured",
|
|
11507
|
+
"4-phase pipeline. Notes and transcripts live in **parallel sibling",
|
|
11508
|
+
"trees** keyed by basename \u2014 see the **Meeting file layout** section",
|
|
11509
|
+
"below for the canonical directory layout and input-case matrix.",
|
|
11002
11510
|
"Each phase runs as a **separate agent session**, triggered by its own",
|
|
11003
11511
|
"GitHub issue with a `meeting:*` phase label. You handle exactly **one",
|
|
11004
11512
|
"phase per session** \u2014 read the issue to determine which phase to execute.",
|
|
@@ -11031,6 +11539,87 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11031
11539
|
" Apply the type-specific rules from the **Meeting type handling**",
|
|
11032
11540
|
" table (phases 1\u20132) and the area-filtered routing rules from the",
|
|
11033
11541
|
" **Areas filtering** table (phase 4).",
|
|
11542
|
+
"7. **Treat notes and transcripts as paired siblings.** Notes are the",
|
|
11543
|
+
" curated narrative summary; transcripts are the verbatim evidence",
|
|
11544
|
+
" record. Both are first-class inputs to Phase 1 \u2014 never assume the",
|
|
11545
|
+
" transcript is the sole input.",
|
|
11546
|
+
"",
|
|
11547
|
+
"---",
|
|
11548
|
+
"",
|
|
11549
|
+
"## Meeting file layout (sibling-tree model)",
|
|
11550
|
+
"",
|
|
11551
|
+
"The bundle organises meeting artifacts as **three parallel trees**",
|
|
11552
|
+
"rooted at `<meetingsRoot>`, partitioned by meeting type",
|
|
11553
|
+
"(`internal` / `external`):",
|
|
11554
|
+
"",
|
|
11555
|
+
"```",
|
|
11556
|
+
"<meetingsRoot>/",
|
|
11557
|
+
"\u251C\u2500\u2500 transcripts/{internal,external}/ \u2190 raw verbatim transcripts (input, evidence)",
|
|
11558
|
+
"\u251C\u2500\u2500 notes/{internal,external}/ \u2190 curated narrative summary (input + Phase 2 output)",
|
|
11559
|
+
"\u2514\u2500\u2500 insights/{internal,external}/ \u2190 structured extraction (Phase 1 output)",
|
|
11560
|
+
"```",
|
|
11561
|
+
"",
|
|
11562
|
+
"Within a given `{internal,external}` partition, the three trees share",
|
|
11563
|
+
"**identical basenames**: a meeting captured as",
|
|
11564
|
+
"`notes/internal/2026-03-14-sprint-kickoff.md` has its companion",
|
|
11565
|
+
"transcript at `transcripts/internal/2026-03-14-sprint-kickoff.md` and",
|
|
11566
|
+
"its Phase 1 extraction at `insights/internal/2026-03-14-sprint-kickoff.md`.",
|
|
11567
|
+
"Agents look up siblings via filesystem (basename match across the",
|
|
11568
|
+
"three trees), not via frontmatter cross-references.",
|
|
11569
|
+
"",
|
|
11570
|
+
"**Input-case matrix.** A meeting always has a `notes/` or",
|
|
11571
|
+
"`transcripts/` entry (often both); Phase 1 must handle every case:",
|
|
11572
|
+
"",
|
|
11573
|
+
"| Notes file? | Transcript file? | Case | Phase-1 behaviour |",
|
|
11574
|
+
"|-------------|------------------|------|--------------------|",
|
|
11575
|
+
"| Yes | Yes | **Both** | Read both; transcript is verbatim ground truth, notes are first-draft summary. Set `transcript_available: true`, `confidence: high`. |",
|
|
11576
|
+
"| Yes | No | **Notes-only** | Read notes only. Set `transcript_available: false`, `confidence: medium`. Do not invent dialogue the notes do not record. |",
|
|
11577
|
+
"| No | Yes | **Transcript-only** | Read transcript only. Set `transcript_available: true`, `confidence: high`. Phase 2 will author the notes file from the transcript. |",
|
|
11578
|
+
"",
|
|
11579
|
+
"Notes frontmatter is **optional**. A bare imported file with no",
|
|
11580
|
+
"frontmatter is a normal input case \u2014 treat missing fields as the",
|
|
11581
|
+
"defaults `meeting_type: other`, `source: unknown`, `confidence: medium`,",
|
|
11582
|
+
"and populate the real values on first processing. Never fail-loud on",
|
|
11583
|
+
"absent frontmatter.",
|
|
11584
|
+
"",
|
|
11585
|
+
"### Notes / insights frontmatter schema",
|
|
11586
|
+
"",
|
|
11587
|
+
"The following frontmatter fields are recognised on notes and",
|
|
11588
|
+
"insights files. Every field is optional \u2014 agents must read them",
|
|
11589
|
+
"defensively and supply defaults when absent.",
|
|
11590
|
+
"",
|
|
11591
|
+
"| Field | Type | Purpose | Default |",
|
|
11592
|
+
"|-------|------|---------|---------|",
|
|
11593
|
+
"| `slug` | string | Starlight slug override; lets agents normalise the URL without renaming files. | derived from filename |",
|
|
11594
|
+
"| `source` | `gemini` \\| `human` \\| `hybrid` \\| `unknown` | Provenance of the original notes (which authoring path produced them). | `unknown` |",
|
|
11595
|
+
"| `transcript_available` | boolean | Cached result of the filesystem check for the sibling transcript. | re-derive from filesystem |",
|
|
11596
|
+
"| `confidence` | `high` \\| `medium` \\| `low` | Reliability of the extraction. Downstream draft phases mark requirements **Tentative** when `confidence != high`. | `medium` |",
|
|
11597
|
+
"",
|
|
11598
|
+
"These additions coexist with the existing `meeting_type` and `areas`",
|
|
11599
|
+
"fields documented in the **Meeting type handling** and **Areas",
|
|
11600
|
+
"filtering** sections below.",
|
|
11601
|
+
"",
|
|
11602
|
+
"Transcript files themselves remain frontmatter-free \u2014 they are",
|
|
11603
|
+
"evidence-only, and agents never navigate to a transcript as a",
|
|
11604
|
+
"Starlight artifact.",
|
|
11605
|
+
"",
|
|
11606
|
+
"### Tree-level index pages",
|
|
11607
|
+
"",
|
|
11608
|
+
"Each of the three trees carries an `index.md` at its root and at",
|
|
11609
|
+
"each `{internal,external}` partition so Starlight renders a clean",
|
|
11610
|
+
"sidebar:",
|
|
11611
|
+
"",
|
|
11612
|
+
"- `<meetingsRoot>/transcripts/index.md` (and one per partition)",
|
|
11613
|
+
"- `<meetingsRoot>/notes/index.md` (and one per partition)",
|
|
11614
|
+
"- `<meetingsRoot>/insights/index.md` (and one per partition)",
|
|
11615
|
+
"",
|
|
11616
|
+
"Phase 1 must create the matching `insights/{type}/index.md` page",
|
|
11617
|
+
"the first time it writes a file into that partition. Phase 2 must",
|
|
11618
|
+
"create the matching `notes/{type}/index.md` page the first time it",
|
|
11619
|
+
"writes a notes file into that partition. Follow the `section-index`",
|
|
11620
|
+
"convention: a 1\u20132 paragraph summary of the tree's purpose plus a",
|
|
11621
|
+
"linked listing of the partition's children. Append a row for the",
|
|
11622
|
+
"current meeting's basename when an index already exists.",
|
|
11034
11623
|
"",
|
|
11035
11624
|
"---",
|
|
11036
11625
|
"",
|
|
@@ -11159,17 +11748,25 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11159
11748
|
"",
|
|
11160
11749
|
"## Phase 1: Extract (`meeting:extract`)",
|
|
11161
11750
|
"",
|
|
11162
|
-
"**Goal:** Read the meeting
|
|
11751
|
+
"**Goal:** Read the available meeting inputs (notes, transcript, or both)",
|
|
11752
|
+
"and categorize all substantive content into a structured extraction.",
|
|
11163
11753
|
"",
|
|
11164
11754
|
"### Steps",
|
|
11165
11755
|
"",
|
|
11166
|
-
"1.
|
|
11167
|
-
"
|
|
11168
|
-
"
|
|
11169
|
-
"
|
|
11170
|
-
"
|
|
11171
|
-
"
|
|
11172
|
-
" in
|
|
11756
|
+
"1. Identify the meeting's basename and `{internal,external}` partition",
|
|
11757
|
+
" from the issue body, then read **both** sibling files when they",
|
|
11758
|
+
" exist:",
|
|
11759
|
+
" - Notes: `<meetingsRoot>/notes/{type}/<basename>.md`",
|
|
11760
|
+
" - Transcript: `<meetingsRoot>/transcripts/{type}/<basename>.md`",
|
|
11761
|
+
"",
|
|
11762
|
+
" Use the **input-case matrix** in **Meeting file layout** to decide",
|
|
11763
|
+
" which case you are in (both / notes-only / transcript-only). Parse",
|
|
11764
|
+
" the notes frontmatter first (if a notes file exists), capturing",
|
|
11765
|
+
" `meeting_type`, `areas`, `source`, and `confidence`. Resolve",
|
|
11766
|
+
" `meeting_type` to a kind using the **Meeting type handling**",
|
|
11767
|
+
" table; note the resolved kind in the extraction frontmatter. If",
|
|
11768
|
+
" `meeting_type` is missing, treat it as `other` and flag it in",
|
|
11769
|
+
" Open Questions \u2014 do **not** fail-loud on missing frontmatter.",
|
|
11173
11770
|
"2. Identify and categorize content into these buckets:",
|
|
11174
11771
|
"",
|
|
11175
11772
|
" | Bucket | What to look for |",
|
|
@@ -11184,7 +11781,10 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11184
11781
|
" | **Strategic direction** | Business model changes, market positioning |",
|
|
11185
11782
|
" | **Product direction** | Roadmap changes, feature prioritization |",
|
|
11186
11783
|
"",
|
|
11187
|
-
"3. Write the extraction to
|
|
11784
|
+
"3. Write the extraction to",
|
|
11785
|
+
" `<meetingsRoot>/insights/{type}/<basename>.md` (matching the",
|
|
11786
|
+
" basename and `{internal,external}` partition of the source",
|
|
11787
|
+
" notes / transcript) with structured sections:",
|
|
11188
11788
|
" - Attendees",
|
|
11189
11789
|
" - Decisions Made (with category and confidence: Firm / Tentative / Needs confirmation)",
|
|
11190
11790
|
" - Requirements Identified (with category and priority estimate)",
|
|
@@ -11195,9 +11795,14 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11195
11795
|
" - Companies of Interest (with type and context)",
|
|
11196
11796
|
" - Strategic / Product Direction",
|
|
11197
11797
|
"",
|
|
11198
|
-
" Carry
|
|
11199
|
-
"
|
|
11200
|
-
"
|
|
11798
|
+
" Carry the following into the extraction frontmatter so downstream",
|
|
11799
|
+
" phases can gate behaviour without re-parsing the source files:",
|
|
11800
|
+
" `meeting_type`, the resolved `meeting_kind`, `areas`,",
|
|
11801
|
+
" `transcript_available: true|false` (cached from the filesystem",
|
|
11802
|
+
" check in step 1), and `confidence: high|medium|low` (per the",
|
|
11803
|
+
" input-case matrix \u2014 `high` when a transcript is present, `medium`",
|
|
11804
|
+
" on notes-only, never silently downgraded to `low` without an",
|
|
11805
|
+
" explicit reason recorded in Open Questions).",
|
|
11201
11806
|
"",
|
|
11202
11807
|
"4. **Apply type-specific rules.** Consult the **Meeting type handling**",
|
|
11203
11808
|
" table for the resolved kind and apply its phase-1 rules in",
|
|
@@ -11211,7 +11816,14 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11211
11816
|
" Interest (signal threshold still applies); capture customer",
|
|
11212
11817
|
" pain points as candidate BR (not FR).",
|
|
11213
11818
|
"",
|
|
11214
|
-
"5. **
|
|
11819
|
+
"5. **Maintain the `insights/` tree index.** Ensure",
|
|
11820
|
+
" `<meetingsRoot>/insights/index.md` and",
|
|
11821
|
+
" `<meetingsRoot>/insights/{type}/index.md` exist (create them",
|
|
11822
|
+
" following the `section-index` convention if missing) and append",
|
|
11823
|
+
" a row for the current meeting's basename if one is not already",
|
|
11824
|
+
" present.",
|
|
11825
|
+
"",
|
|
11826
|
+
"6. **Create downstream phase issues** using `gh issue create`:",
|
|
11215
11827
|
" - Always create a `meeting:notes` issue (blocked on this extract issue)",
|
|
11216
11828
|
" - If requirements OR decisions/ADRs identified, create a `meeting:draft` issue",
|
|
11217
11829
|
" (blocked on the notes issue). For kind `standup`, skip the",
|
|
@@ -11220,18 +11832,59 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11220
11832
|
" - Always create a `meeting:link` issue \u2014 blocked on the draft issue if one",
|
|
11221
11833
|
" was created, otherwise blocked on the notes issue",
|
|
11222
11834
|
"",
|
|
11223
|
-
"
|
|
11835
|
+
"7. Commit, push, and close the extract issue.",
|
|
11224
11836
|
"",
|
|
11225
11837
|
"---",
|
|
11226
11838
|
"",
|
|
11227
11839
|
"## Phase 2: Notes (`meeting:notes`)",
|
|
11228
11840
|
"",
|
|
11229
|
-
"**Goal:**
|
|
11841
|
+
"**Goal:** Produce a curated `notes/{type}/<basename>.md` file that",
|
|
11842
|
+
"reflects the structured meeting record. The pivot here from older",
|
|
11843
|
+
'versions of this bundle: Phase 2 is no longer "author notes from',
|
|
11844
|
+
'scratch." It is **enhance and verify** \u2014 restructure the existing',
|
|
11845
|
+
"Gemini-generated notes (when present), verify factual claims",
|
|
11846
|
+
"against the transcript (when present), and fall back to authoring",
|
|
11847
|
+
"only when no notes file exists.",
|
|
11230
11848
|
"",
|
|
11231
11849
|
"### Steps",
|
|
11232
11850
|
"",
|
|
11233
|
-
"1. Read the extraction
|
|
11234
|
-
"
|
|
11851
|
+
"1. Read the extraction at",
|
|
11852
|
+
" `<meetingsRoot>/insights/{type}/<basename>.md` (output of Phase 1).",
|
|
11853
|
+
" Read the `transcript_available` and `confidence` fields from its",
|
|
11854
|
+
" frontmatter. Then determine which input-case branch applies by",
|
|
11855
|
+
" checking the filesystem for the sibling notes and transcript",
|
|
11856
|
+
" files.",
|
|
11857
|
+
"2. **Branch by input case** (see the input-case matrix in the",
|
|
11858
|
+
" **Meeting file layout** section):",
|
|
11859
|
+
"",
|
|
11860
|
+
" - **Both notes and transcript present** (enhance + verify):",
|
|
11861
|
+
" Read the existing `notes/{type}/<basename>.md` in place.",
|
|
11862
|
+
" Restructure it into the canonical section layout below.",
|
|
11863
|
+
" Verify every factual claim against the transcript \u2014 when the",
|
|
11864
|
+
" transcript contradicts the notes, the transcript wins and the",
|
|
11865
|
+
" notes are corrected. Fill in gaps the transcript reveals were",
|
|
11866
|
+
" missed. Overwrite the notes file in place; preserve the",
|
|
11867
|
+
" existing frontmatter and update only the fields you changed",
|
|
11868
|
+
" (e.g. flip `source: gemini` to `source: hybrid` once the agent",
|
|
11869
|
+
" has edited the file). Set `confidence: high`.",
|
|
11870
|
+
"",
|
|
11871
|
+
" - **Notes only** (light structural cleanup):",
|
|
11872
|
+
" Read the existing `notes/{type}/<basename>.md`. Restructure it",
|
|
11873
|
+
" into the canonical section layout below. Do **not** invent",
|
|
11874
|
+
" dialogue or claims the notes do not record. Do **not** mark",
|
|
11875
|
+
" `confidence: high` \u2014 keep `confidence: medium` and record the",
|
|
11876
|
+
' reason ("no transcript available for verification") in the',
|
|
11877
|
+
" notes' Open Questions section so downstream phases know to",
|
|
11878
|
+
" treat downstream requirement drafts as `Tentative`.",
|
|
11879
|
+
"",
|
|
11880
|
+
" - **Transcript only** (author from scratch):",
|
|
11881
|
+
" The notes file does not yet exist. Author",
|
|
11882
|
+
" `notes/{type}/<basename>.md` from the transcript using the",
|
|
11883
|
+
" section layout below. Populate frontmatter with",
|
|
11884
|
+
" `source: gemini` if the transcript is a Gemini transcript,",
|
|
11885
|
+
" otherwise `source: unknown`. Set `confidence: high`.",
|
|
11886
|
+
"",
|
|
11887
|
+
"3. Canonical notes section layout (applied in every branch above):",
|
|
11235
11888
|
" - Meeting metadata (title, date, attendees)",
|
|
11236
11889
|
" - Agenda / topics covered",
|
|
11237
11890
|
" - Key Discussion Points (organized by topic)",
|
|
@@ -11239,7 +11892,13 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11239
11892
|
" - Action Items (table: who, what, when)",
|
|
11240
11893
|
" - Open Questions",
|
|
11241
11894
|
" - Follow-up items",
|
|
11242
|
-
"
|
|
11895
|
+
"4. **Maintain the `notes/` tree index.** Ensure",
|
|
11896
|
+
" `<meetingsRoot>/notes/index.md` and",
|
|
11897
|
+
" `<meetingsRoot>/notes/{type}/index.md` exist (create them",
|
|
11898
|
+
" following the `section-index` convention if missing) and append",
|
|
11899
|
+
" a row for the current meeting's basename if one is not already",
|
|
11900
|
+
" present.",
|
|
11901
|
+
"5. Commit, push, and close the notes issue.",
|
|
11243
11902
|
"",
|
|
11244
11903
|
"---",
|
|
11245
11904
|
"",
|
|
@@ -11252,7 +11911,8 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11252
11911
|
"",
|
|
11253
11912
|
"### Steps",
|
|
11254
11913
|
"",
|
|
11255
|
-
"1. Read the extraction file from Phase 1
|
|
11914
|
+
"1. Read the extraction file from Phase 1 at",
|
|
11915
|
+
" `<meetingsRoot>/insights/{type}/<basename>.md`.",
|
|
11256
11916
|
"2. Check existing requirement registries and ADR registries for duplicates.",
|
|
11257
11917
|
"3. Draft requirement proposals with:",
|
|
11258
11918
|
" - Category (FR, BR, NFR, etc.)",
|
|
@@ -11276,7 +11936,8 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11276
11936
|
"",
|
|
11277
11937
|
"### Steps",
|
|
11278
11938
|
"",
|
|
11279
|
-
"1. Read the drafts from Phase 3 (if they exist) and the extraction
|
|
11939
|
+
"1. Read the drafts from Phase 3 (if they exist) and the extraction",
|
|
11940
|
+
" from Phase 1 at `<meetingsRoot>/insights/{type}/<basename>.md`.",
|
|
11280
11941
|
" Re-read the extraction frontmatter for `meeting_kind` and `areas`,",
|
|
11281
11942
|
" then build the area-gate: the set of `docRoot` sub-folders that",
|
|
11282
11943
|
" are in scope for direct edits on this meeting. Apply the rules in",
|
|
@@ -11305,12 +11966,15 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
11305
11966
|
" sprint-plan doc's area is in-scope, or always when no",
|
|
11306
11967
|
" `meetingAreas` are declared); for the kind `review`, mark",
|
|
11307
11968
|
" completed tasks in that same doc.",
|
|
11308
|
-
"7. **Update the extraction file**
|
|
11309
|
-
"
|
|
11310
|
-
"
|
|
11311
|
-
"
|
|
11312
|
-
"
|
|
11313
|
-
"
|
|
11969
|
+
"7. **Update the extraction file** at",
|
|
11970
|
+
" `<meetingsRoot>/insights/{type}/<basename>.md` with a",
|
|
11971
|
+
" `## Downstream Artifacts` section listing every issue and",
|
|
11972
|
+
" document created from this meeting. Note any items that were",
|
|
11973
|
+
" deferred to follow-up issues because of the area gate.",
|
|
11974
|
+
"8. **Update the meeting notes** at",
|
|
11975
|
+
" `<meetingsRoot>/notes/{type}/<basename>.md` with a",
|
|
11976
|
+
" `## Related Issues` section listing all issues created from this",
|
|
11977
|
+
" meeting.",
|
|
11314
11978
|
"9. Comment on the parent extract issue with a summary linking to all",
|
|
11315
11979
|
" created artifacts.",
|
|
11316
11980
|
"10. Commit and push (if any file changes were made), then close the link issue.",
|
|
@@ -11344,21 +12008,27 @@ var processMeetingSkill = {
|
|
|
11344
12008
|
agent: "meeting-analyst",
|
|
11345
12009
|
platforms: { cursor: { exclude: true } },
|
|
11346
12010
|
instructions: [
|
|
11347
|
-
"# Process Meeting
|
|
12011
|
+
"# Process Meeting",
|
|
11348
12012
|
"",
|
|
11349
|
-
"Kick off meeting
|
|
11350
|
-
"
|
|
12013
|
+
"Kick off meeting processing by executing Phase 1 (Extract) and",
|
|
12014
|
+
"creating downstream phase issues for the remaining phases. Inputs",
|
|
12015
|
+
"live in the **sibling-tree layout**: pass any file from",
|
|
12016
|
+
"`<meetingsRoot>/notes/{type}/` or `<meetingsRoot>/transcripts/{type}/`",
|
|
12017
|
+
"(both, notes-only, and transcript-only are all valid input cases).",
|
|
11351
12018
|
"",
|
|
11352
12019
|
"## Usage",
|
|
11353
12020
|
"",
|
|
11354
|
-
"/process-meeting <path-to-transcript>",
|
|
12021
|
+
"/process-meeting <path-to-notes-or-transcript>",
|
|
11355
12022
|
"",
|
|
11356
12023
|
"## Steps",
|
|
11357
12024
|
"",
|
|
11358
|
-
"1.
|
|
11359
|
-
"
|
|
12025
|
+
"1. Identify the meeting's basename and `{internal,external}`",
|
|
12026
|
+
" partition from the provided path, then read **every** sibling",
|
|
12027
|
+
" that exists (notes file and/or transcript file)",
|
|
12028
|
+
"2. Execute Phase 1 (Extract) \u2014 categorize the available content into",
|
|
11360
12029
|
" decisions, requirements, action items, open questions, and more",
|
|
11361
|
-
"3. Write the extraction to
|
|
12030
|
+
"3. Write the extraction to",
|
|
12031
|
+
" `<meetingsRoot>/insights/{type}/<basename>.md`",
|
|
11362
12032
|
"4. Create downstream phase issues using `gh issue create`:",
|
|
11363
12033
|
" - `meeting:notes` issue (always)",
|
|
11364
12034
|
" - `meeting:draft` issue (if requirements or decisions were found)",
|
|
@@ -11368,12 +12038,15 @@ var processMeetingSkill = {
|
|
|
11368
12038
|
"",
|
|
11369
12039
|
"## Input",
|
|
11370
12040
|
"",
|
|
11371
|
-
"Provide a path to a
|
|
11372
|
-
"
|
|
12041
|
+
"Provide a path to a file in either `notes/` or `transcripts/`. The",
|
|
12042
|
+
"agent will look up the sibling automatically via basename match. A",
|
|
12043
|
+
"missing sibling is a normal case (notes-only or transcript-only) \u2014",
|
|
12044
|
+
"the agent handles all three input cases.",
|
|
11373
12045
|
"",
|
|
11374
12046
|
"## Output",
|
|
11375
12047
|
"",
|
|
11376
|
-
"-
|
|
12048
|
+
"- A structured extraction at",
|
|
12049
|
+
" `<meetingsRoot>/insights/{type}/<basename>.md`",
|
|
11377
12050
|
"- Phase issues with `meeting:*` labels for downstream agent sessions",
|
|
11378
12051
|
" to pick up (notes, draft, link)"
|
|
11379
12052
|
].join("\n")
|
|
@@ -11391,11 +12064,30 @@ function buildMeetingAnalysisBundle(tier = AGENT_MODEL.BALANCED) {
|
|
|
11391
12064
|
content: [
|
|
11392
12065
|
"# Meeting Processing Workflow",
|
|
11393
12066
|
"",
|
|
11394
|
-
"Use `/process-meeting <path>` to process a meeting
|
|
12067
|
+
"Use `/process-meeting <path>` to process a meeting through a",
|
|
11395
12068
|
"4-phase pipeline (extract \u2192 notes \u2192 draft \u2192 link). Each phase runs as a",
|
|
11396
12069
|
"separate agent session tracked by a GitHub issue with a `meeting:*` label.",
|
|
11397
12070
|
"See the `meeting-analyst` agent definition for full workflow details.",
|
|
11398
12071
|
"",
|
|
12072
|
+
"Meeting artifacts live in **three parallel trees** rooted at the",
|
|
12073
|
+
"project's meetings root:",
|
|
12074
|
+
"",
|
|
12075
|
+
"- `transcripts/{internal,external}/` \u2014 verbatim transcripts (evidence)",
|
|
12076
|
+
"- `notes/{internal,external}/` \u2014 curated narrative summary",
|
|
12077
|
+
" (input + Phase 2 output)",
|
|
12078
|
+
"- `insights/{internal,external}/` \u2014 structured extraction (Phase 1 output)",
|
|
12079
|
+
"",
|
|
12080
|
+
"The three trees share identical basenames so a meeting's siblings",
|
|
12081
|
+
"are looked up by filename, not by frontmatter cross-references.",
|
|
12082
|
+
"Phase 1 accepts every input case (notes + transcript, notes only,",
|
|
12083
|
+
"or transcript only) and Phase 2 enhances the notes file in place",
|
|
12084
|
+
"rather than authoring it from scratch.",
|
|
12085
|
+
"",
|
|
12086
|
+
"Notes and insights files may carry optional frontmatter fields",
|
|
12087
|
+
"`slug`, `source`, `transcript_available`, and `confidence`",
|
|
12088
|
+
"alongside the existing `meeting_type` and `areas` fields. Missing",
|
|
12089
|
+
"frontmatter is treated as a normal input case \u2014 never fail-loud.",
|
|
12090
|
+
"",
|
|
11399
12091
|
"Meeting notes may declare a `meeting_type` (one of the project's",
|
|
11400
12092
|
"recognized types) and an `areas: [...]` list. The `meeting_type`",
|
|
11401
12093
|
"resolves to a generic kind \u2014 `planning` / `review` / `brainstorm` /",
|
|
@@ -15750,6 +16442,17 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
15750
16442
|
"full background, and do not rewrite the profile body for facts that",
|
|
15751
16443
|
"have not changed.",
|
|
15752
16444
|
"",
|
|
16445
|
+
"**Temporal framing.** Refreshes follow the same grep-`as of `-and-",
|
|
16446
|
+
"re-verify pattern documented for `company:refresh` in the",
|
|
16447
|
+
"`company-profile-analyst` bundle (Phase 5, steps 3 and 5): build",
|
|
16448
|
+
"the list of qualified claims, classify each against the cadence",
|
|
16449
|
+
"table in the `temporal-framing-convention` rule (90d for current",
|
|
16450
|
+
"role / employer / tenure, falling back to 180d for slower-decay",
|
|
16451
|
+
"claims), re-verify every claim past cadence, and update the",
|
|
16452
|
+
"qualifier date on every claim that still holds. Treat a profile",
|
|
16453
|
+
"with no `as of ` qualifiers as needing back-fill before any other",
|
|
16454
|
+
"verification.",
|
|
16455
|
+
"",
|
|
15753
16456
|
"### Steps",
|
|
15754
16457
|
"",
|
|
15755
16458
|
"1. **Read the existing profile** at the path referenced in the issue",
|
|
@@ -29452,6 +30155,17 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
|
|
|
29452
30155
|
});
|
|
29453
30156
|
}
|
|
29454
30157
|
}
|
|
30158
|
+
const resolvedTemporalFraming = validateTemporalFramingConfig(
|
|
30159
|
+
this.options.temporalFraming
|
|
30160
|
+
);
|
|
30161
|
+
if (resolvedTemporalFraming.enabled && resolvedTemporalFraming.emitChecker) {
|
|
30162
|
+
new import_projen8.TextFile(this, ".claude/procedures/check-temporal-framing.sh", {
|
|
30163
|
+
lines: renderTemporalFramingCheckerScript(
|
|
30164
|
+
resolvedTemporalFraming
|
|
30165
|
+
).split("\n"),
|
|
30166
|
+
executable: true
|
|
30167
|
+
});
|
|
30168
|
+
}
|
|
29455
30169
|
const platforms = this.resolvePlatforms();
|
|
29456
30170
|
const rules = this.resolveRules();
|
|
29457
30171
|
const skills = this.resolveSkills();
|
|
@@ -29799,6 +30513,23 @@ ${hook}`
|
|
|
29799
30513
|
});
|
|
29800
30514
|
}
|
|
29801
30515
|
}
|
|
30516
|
+
const resolvedTemporalFramingForRules = resolveTemporalFraming(
|
|
30517
|
+
this.options.temporalFraming
|
|
30518
|
+
);
|
|
30519
|
+
if (this.options.temporalFraming) {
|
|
30520
|
+
const temporalFramingRule = ruleMap.get("temporal-framing-convention");
|
|
30521
|
+
if (temporalFramingRule) {
|
|
30522
|
+
const temporalFramingContent = renderTemporalFramingRuleContent(
|
|
30523
|
+
resolvedTemporalFramingForRules
|
|
30524
|
+
);
|
|
30525
|
+
if (temporalFramingContent !== temporalFramingRule.content) {
|
|
30526
|
+
ruleMap.set("temporal-framing-convention", {
|
|
30527
|
+
...temporalFramingRule,
|
|
30528
|
+
content: temporalFramingContent
|
|
30529
|
+
});
|
|
30530
|
+
}
|
|
30531
|
+
}
|
|
30532
|
+
}
|
|
29802
30533
|
const tierExamples = this.options.features?.sourceTierExamples;
|
|
29803
30534
|
if (_AgentConfig.hasActiveTierExamples(tierExamples)) {
|
|
29804
30535
|
const sourceRule = ruleMap.get("source-quality-verification");
|
|
@@ -34567,6 +35298,10 @@ var TypeScriptConfig = class extends import_projen24.Component {
|
|
|
34567
35298
|
DEFAULT_STATE_FILE_PATH,
|
|
34568
35299
|
DEFAULT_STATUS_LABELS,
|
|
34569
35300
|
DEFAULT_TEARDOWN_BRANCH_PATTERNS,
|
|
35301
|
+
DEFAULT_TEMPORAL_FRAMING_CADENCES,
|
|
35302
|
+
DEFAULT_TEMPORAL_FRAMING_EMIT_CHECKER,
|
|
35303
|
+
DEFAULT_TEMPORAL_FRAMING_ENABLED,
|
|
35304
|
+
DEFAULT_TEMPORAL_FRAMING_PATHS,
|
|
34570
35305
|
DEFAULT_TYPE_LABELS,
|
|
34571
35306
|
DEFAULT_UNBLOCK_COMMENT_TEMPLATE,
|
|
34572
35307
|
DEFAULT_UNBLOCK_DEPENDENTS_ENABLED,
|
|
@@ -34598,6 +35333,7 @@ var TypeScriptConfig = class extends import_projen24.Component {
|
|
|
34598
35333
|
SUPPRESSED_WORKFLOW_RULE_NAMES,
|
|
34599
35334
|
SampleLang,
|
|
34600
35335
|
StarlightProject,
|
|
35336
|
+
TEMPORAL_FRAMING_CATEGORY_VALUES,
|
|
34601
35337
|
TIER_AWARE_BUNDLE_NAMES,
|
|
34602
35338
|
TestRunner,
|
|
34603
35339
|
TsDocCoverageKind,
|
|
@@ -34721,6 +35457,8 @@ var TypeScriptConfig = class extends import_projen24.Component {
|
|
|
34721
35457
|
renderSkillEvalsRunnerScript,
|
|
34722
35458
|
renderSourceTierExamples,
|
|
34723
35459
|
renderStubIndexConventionRuleContent,
|
|
35460
|
+
renderTemporalFramingCheckerScript,
|
|
35461
|
+
renderTemporalFramingRuleContent,
|
|
34724
35462
|
renderUnblockDependentsScript,
|
|
34725
35463
|
renderUnblockDependentsSection,
|
|
34726
35464
|
requirementsAnalystBundle,
|
|
@@ -34746,6 +35484,7 @@ var TypeScriptConfig = class extends import_projen24.Component {
|
|
|
34746
35484
|
resolveSharedEditing,
|
|
34747
35485
|
resolveSkillEvals,
|
|
34748
35486
|
resolveTemplateVariables,
|
|
35487
|
+
resolveTemporalFraming,
|
|
34749
35488
|
resolveTypeScriptProjectOutdir,
|
|
34750
35489
|
resolveUnblockDependents,
|
|
34751
35490
|
runScan,
|
|
@@ -34767,6 +35506,7 @@ var TypeScriptConfig = class extends import_projen24.Component {
|
|
|
34767
35506
|
validateSharedEditingConfig,
|
|
34768
35507
|
validateSkillEvalsConfig,
|
|
34769
35508
|
validateStarlightSingleton,
|
|
35509
|
+
validateTemporalFramingConfig,
|
|
34770
35510
|
validateUnblockDependentsConfig,
|
|
34771
35511
|
vitestBundle
|
|
34772
35512
|
});
|