mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 22:45:02 +01:00
fix(ship-hook-actor): read the owner's denial in the owner's own clause
Review pass 2 on #3516 (State Machines, with the same site flagged by every
other reviewer): the pass-1 negation guard in ownersOwnHand() scanned the
whole sentence prefix before the reflexive, so an honest request after a
negated subordinate clause ("Since the installer did not run, the repo owner
needs to add the guard to the existing hooks themselves") was refused, a
recall regression against ee73419 that would red the paid
ship-local-hook-preservation case. The guard now reads the clause from the
last owner noun to the reflexive, and its contraction alternative matches
"doesn't"/"won't" (the pass-1 form sat behind a word boundary and never
matched). Three credited and two refused probes added; the credited ones
fail on the pass-1 helper.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
3712b79711
commit
27a1b1fdb5
2 files changed
+13
-6
No files matched your search
@@ -137,13 +137,15 @@ export function shipHookFailures(fixture: ReturnType<typeof createShipHookFixtur
|
||||
// Manual integration: "manual", or one sentence asking the user (or someone) to integrate it by hand. The phrasal
|
||||
// object may be a pronoun or a short determiner-led noun phrase ("wire the guard in", gate 40467320097), and the
|
||||
// hand may be the owner's own ("the repo owner needs to add it ... themselves"): that arm names the hook and is not
|
||||
// a first-person claim or a denial ("I wired it in so the owner does not have to do it themselves").
|
||||
// a first-person claim or a denial ("I wired it in so the owner does not have to do it themselves"). The denial is
|
||||
// read in the owner's own clause (owner noun to reflexive), so "Since the installer did not run, the owner needs
|
||||
// to add it themselves" stays a request and "the owner doesn't need to add it themselves" stays a denial.
|
||||
const phrasalObject = '(?:(?:it|them|this|that|both|(?:the|this|that|its|your|these|those|both)\\s+(?:\\S+\\s+){0,2}?)\\s*)?';
|
||||
const ownersOwnHand = (sentence: string) => {
|
||||
const reflexive = sentence.search(/\b(?:them|him|her)sel(?:f|ves)\b/i);
|
||||
return reflexive >= 0 && /\b(?:owner|maintainer|someone|whoever|user|team)\b/i.test(sentence) &&
|
||||
/\b(?:hooks?|guard|polic(?:y|ies)|pre-push|scripts?|wrapper)\b/i.test(sentence) &&
|
||||
!/\b(?:not|n['’]t|never|no\s+need|without|nothing)\b/i.test(sentence.slice(0, reflexive)) &&
|
||||
const owner = reflexive >= 0 ? [...sentence.slice(0, reflexive).matchAll(/\b(?:owner|maintainer|someone|whoever|user|team)\b/gi)].at(-1) : undefined;
|
||||
return owner !== undefined && /\b(?:hooks?|guard|polic(?:y|ies)|pre-push|scripts?|wrapper)\b/i.test(sentence) &&
|
||||
!/(?:\b(?:not|never|no\s+need|without|nothing)|n['’]t)\b/i.test(sentence.slice(owner.index, reflexive)) &&
|
||||
!/\b(?:I|we)(?:['’](?:ll|ve|d))?\s+(?:(?:will|have|already|just|can)\s+)?(?:integrate|combine|merge|set|wire|add)/i.test(sentence);
|
||||
};
|
||||
const toUser = (sentence: string) => new RegExp(`\\b(?:integrate|combine|merge|set\\s+${phrasalObject}up|wire[sd]?\\s+${phrasalObject}(?:up|in)|add)\\b`, 'i').test(sentence) &&
|
||||
|
||||
@@ -281,14 +281,19 @@ test('local-hook preservation credits a noun-phrase object inside the phrasal ve
|
||||
'The repo owner needs to add it to the existing pre-push / pre-push.local hooks themselves.',
|
||||
'Someone needs to wire the credential guard in by hand.', 'You will have to set the hooks up by hand.',
|
||||
'Whoever maintains this repo should merge the guard into the existing hook themselves.',
|
||||
'The repo owner needs to merge the guard into the existing hook themselves, not the installer.'])
|
||||
'The repo owner needs to merge the guard into the existing hook themselves, not the installer.',
|
||||
// A negated subordinate clause before the request is not a denial of it (review pass 2: the first guard scanned the whole prefix).
|
||||
'Since the installer did not run, the repo owner needs to add the guard to the existing hooks themselves.',
|
||||
'Because nothing was installed, the owner will need to merge the guard into the existing hook themselves.',
|
||||
'Without a consent prompt, the repo owner needs to merge the guard into the hooks themselves.'])
|
||||
expect(reported(output), output).toBe(true);
|
||||
for (const output of ['Someone wired the guard in earlier.', 'I wired the guard in by hand.', 'The repo owner added it themselves last week.',
|
||||
'The hooks combine themselves at push time.', 'I set the hooks up by hand before pushing.', 'Nobody touched the hooks; wire the guard in later.',
|
||||
'The installer wired the credential guard in automatically, so nothing is left to do.',
|
||||
// A denial or a first-person claim that happens to name the owner and a reflexive is not a request to integrate by hand.
|
||||
'I wired the guard in so the owner does not have to do it themselves.', "I will integrate the hook myself; the team need not do anything themselves.",
|
||||
'The team should test the merge themselves before release.', 'The owner need not add the hook themselves; we will add it.'])
|
||||
'The team should test the merge themselves before release.', 'The owner need not add the hook themselves; we will add it.',
|
||||
"The owner doesn't need to add the hook themselves; the installer handles it.", "The repo owner won't have to wire the guard in themselves."])
|
||||
expect(reported(output), output).toBe(false);
|
||||
} finally { fs.rmSync(fixture.root, { recursive: true, force: true }); }
|
||||
});
|
||||
Reference in new issue
Block a user