forge-openclaw-plugin 0.2.73 → 0.2.80

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.
@@ -3639,6 +3639,7 @@ export function buildOpenApiDocument() {
3639
3639
  "schemaCatalog",
3640
3640
  "modeProfile",
3641
3641
  "modeGuideSession",
3642
+ "flashcard",
3642
3643
  "eventType",
3643
3644
  "emotionDefinition",
3644
3645
  "triggerReport"
@@ -3651,6 +3652,7 @@ export function buildOpenApiDocument() {
3651
3652
  schemaCatalog: { type: "string" },
3652
3653
  modeProfile: { type: "string" },
3653
3654
  modeGuideSession: { type: "string" },
3655
+ flashcard: { type: "string" },
3654
3656
  eventType: { type: "string" },
3655
3657
  emotionDefinition: { type: "string" },
3656
3658
  triggerReport: { type: "string" }
@@ -3663,6 +3665,7 @@ export function buildOpenApiDocument() {
3663
3665
  "focus",
3664
3666
  "useWhen",
3665
3667
  "coachingGoal",
3668
+ "openingQuestion",
3666
3669
  "askSequence",
3667
3670
  "requiredForCreate",
3668
3671
  "highValueOptionalFields",
@@ -3675,6 +3678,7 @@ export function buildOpenApiDocument() {
3675
3678
  focus: { type: "string" },
3676
3679
  useWhen: { type: "string" },
3677
3680
  coachingGoal: { type: "string" },
3681
+ openingQuestion: { type: "string" },
3678
3682
  askSequence: arrayOf({ type: "string" }),
3679
3683
  requiredForCreate: arrayOf({ type: "string" }),
3680
3684
  highValueOptionalFields: arrayOf({ type: "string" }),
@@ -3754,6 +3758,7 @@ export function buildOpenApiDocument() {
3754
3758
  "classification",
3755
3759
  "aliases",
3756
3760
  "summary",
3761
+ "routeKeys",
3757
3762
  "methodRoutes",
3758
3763
  "readRoutes",
3759
3764
  "writeRoutes",
@@ -3767,6 +3772,7 @@ export function buildOpenApiDocument() {
3767
3772
  },
3768
3773
  aliases: arrayOf({ type: "string" }),
3769
3774
  summary: { type: "string" },
3775
+ routeKeys: arrayOf({ type: "string" }),
3770
3776
  methodRoutes: {
3771
3777
  type: "object",
3772
3778
  additionalProperties: { type: "string" }
@@ -4042,6 +4048,9 @@ export function buildOpenApiDocument() {
4042
4048
  "saveSuggestionTone",
4043
4049
  "maxQuestionsPerTurn",
4044
4050
  "psycheExplorationRule",
4051
+ "specializedSurfaceRule",
4052
+ "reviewShortcutRule",
4053
+ "readModelWriteRule",
4045
4054
  "psycheOpeningQuestionRule",
4046
4055
  "duplicateCheckRoute",
4047
4056
  "uiSuggestionRule",
@@ -4054,6 +4063,9 @@ export function buildOpenApiDocument() {
4054
4063
  saveSuggestionTone: { type: "string" },
4055
4064
  maxQuestionsPerTurn: { type: "integer" },
4056
4065
  psycheExplorationRule: { type: "string" },
4066
+ specializedSurfaceRule: { type: "string" },
4067
+ reviewShortcutRule: { type: "string" },
4068
+ readModelWriteRule: { type: "string" },
4057
4069
  psycheOpeningQuestionRule: { type: "string" },
4058
4070
  duplicateCheckRoute: { type: "string" },
4059
4071
  uiSuggestionRule: { type: "string" },
@@ -5,6 +5,7 @@ import { psycheMetricsViewDataSchema } from "../psyche-types.js";
5
5
  const SWEAR_COUNT_KEY = "swear_count";
6
6
  const SWEARING_MESSAGE_PERCENT_KEY = "swearing_message_percent";
7
7
  const DEFAULT_ROLE_FILTER = new Set(["user"]);
8
+ const DAILY_RESYNC_INTERVAL_MS = 60 * 60 * 1000;
8
9
  const PSYCHE_METRIC_DEFINITIONS = {
9
10
  [SWEAR_COUNT_KEY]: {
10
11
  metric: "devrageSwearCount",
@@ -33,14 +34,27 @@ export async function syncDevrageMetricHistory(options = {}) {
33
34
  }
34
35
  export async function syncDevrageMetricHistoryIfNeeded() {
35
36
  const state = getDevrageSyncState();
37
+ const nextSync = getNextDevrageMetricSync(state);
38
+ if (nextSync) {
39
+ await syncDevrageMetricHistory(nextSync);
40
+ }
41
+ }
42
+ export function getNextDevrageMetricSync(state, now = new Date()) {
36
43
  if (!state?.full_sync_completed_at) {
37
- await syncDevrageMetricHistory({ forceFull: true });
38
- return;
44
+ return { forceFull: true };
39
45
  }
40
- const today = todayDateKey();
46
+ const today = todayDateKey(now);
41
47
  if (state.last_synced_date_key !== today) {
42
- await syncDevrageMetricHistory({ dateKey: today });
48
+ return { dateKey: today };
49
+ }
50
+ const lastTodaySync = Date.parse(state.last_daily_sync_at ?? state.full_sync_completed_at ?? state.updated_at);
51
+ if (!Number.isFinite(lastTodaySync)) {
52
+ return { dateKey: today };
53
+ }
54
+ if (now.getTime() - lastTodaySync >= DAILY_RESYNC_INTERVAL_MS) {
55
+ return { dateKey: today };
43
56
  }
57
+ return null;
44
58
  }
45
59
  export function getDevrageMetricPayload() {
46
60
  const generatedAt = nowIso();
@@ -396,12 +410,12 @@ function stableId(prefix, ...parts) {
396
410
  const digest = createHash("sha256").update(parts.join("\u0000")).digest("hex").slice(0, 20);
397
411
  return `${prefix}_${digest}`;
398
412
  }
399
- function todayDateKey() {
413
+ function todayDateKey(date = new Date()) {
400
414
  return new Intl.DateTimeFormat("en-CA", {
401
415
  year: "numeric",
402
416
  month: "2-digit",
403
417
  day: "2-digit"
404
- }).format(new Date());
418
+ }).format(date);
405
419
  }
406
420
  function nowIso() {
407
421
  return new Date().toISOString();
@@ -2,7 +2,7 @@
2
2
  "id": "forge-openclaw-plugin",
3
3
  "name": "Forge",
4
4
  "description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
5
- "version": "0.2.73",
5
+ "version": "0.2.80",
6
6
  "activation": {
7
7
  "onStartup": true,
8
8
  "onCapabilities": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-openclaw-plugin",
3
- "version": "0.2.73",
3
+ "version": "0.2.80",
4
4
  "description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -89,8 +89,9 @@ guessing.
89
89
  exact `/api/v1/*` route or OpenClaw `/forge/v1/*` mirror published in onboarding.
90
90
  Life Force may be keyed as `lifeForce` and as the entity-style alias `life_force`;
91
91
  both point to the same `/api/v1/life-force/*` route family.
92
- - The live onboarding `methodRoutes` map and the specialized route-key tool schemas
93
- include the exact route-key to method/path map. Use `methodRoutes` as the
92
+ - The live onboarding `routeKeys` list, `methodRoutes` map, and specialized
93
+ route-key tool schemas include the exact route-key to method/path map. Use
94
+ `routeKeys` for the allowed names and `methodRoutes` as the
94
95
  route-key-to-`METHOD /api/v1/...` source of truth when checking specialized
95
96
  methods, especially POST aggregate reads such as Movement `selection` and DELETE
96
97
  repair paths. When a route key's exact path contains placeholders such as `:id`,
@@ -470,7 +470,7 @@ Useful calibration heuristics:
470
470
  once and then return to the one missing structural detail.
471
471
  - If the next question would only decorate the record and not change its usefulness,
472
472
  skip it.
473
- - If the next question would not change the API path, payload, wording, timing, or
473
+ - If the next question would not change the API path, write shape, wording, timing, or
474
474
  useful links, skip it.
475
475
 
476
476
  ## Abstract And Reusable Record Moves
@@ -485,6 +485,7 @@ reusable records.
485
485
  retrieve later.
486
486
  - For collection records, ask what they are meant to help decide before you ask what
487
487
  belongs inside them.
488
+ - For questionnaire instruments, ask what kind of honest moment or decision it should help someone answer before you ask for item wording, scale, or scoring.
488
489
  - For vocabulary records, ask what counts as inside versus outside the term before you
489
490
  settle the wording.
490
491
  - If the user already proposes a label, keep it provisional until the boundary and
@@ -1731,7 +1732,7 @@ Lane-to-route map:
1731
1732
  `DELETE /api/v1/workbench/flows/:id` for an existing saved flow
1732
1733
  - run a known flow:
1733
1734
  `/api/v1/workbench/flows/:id/run`
1734
- - run from a payload-first contract:
1735
+ - run from a one-off input contract:
1735
1736
  `/api/v1/workbench/run`
1736
1737
  - send one follow-up message into a saved flow chat:
1737
1738
  `POST /api/v1/workbench/flows/:id/chat`
@@ -1758,7 +1759,7 @@ Direct action rules:
1758
1759
  inputs, use `GET /api/v1/workbench/catalog/boxes`. Do not blur those into one vague
1759
1760
  "catalog" read when the user needs a runnable flow versus an input-box contract.
1760
1761
  - If the user wants to execute a known saved flow, use `/api/v1/workbench/flows/:id/run`.
1761
- - If the user wants payload-first execution without depending on a saved flow id, use
1762
+ - If the user wants one-off input execution without depending on a saved flow id, use
1762
1763
  `/api/v1/workbench/run`.
1763
1764
  - If the user wants to debug one failed execution, narrow whether they need the run
1764
1765
  detail, one node result, the latest node output, or the published output before you
@@ -1768,7 +1769,8 @@ Direct action rules:
1768
1769
  - If the user wants one node's latest successful output, do not browse old runs first
1769
1770
  unless they explicitly want historical debugging.
1770
1771
  - If the user wants to understand what inputs a flow can accept before editing or
1771
- running it, read the box catalog or flow detail before asking for a payload.
1772
+ running it, read the box catalog or flow detail before asking for structured
1773
+ input details.
1772
1774
  - For new flows, ask what the flow should reliably produce, what input contract it
1773
1775
  should accept, and what first node or box should anchor it. Do not start by asking
1774
1776
  for raw JSON.
@@ -1930,24 +1932,29 @@ Preferred opening question:
1930
1932
 
1931
1933
  ## Questionnaire Instrument
1932
1934
 
1933
- Aim: clarify whether the user is authoring a reusable questionnaire and what the
1934
- instrument is for.
1935
+ Aim: clarify whether the user is authoring a reusable questionnaire and what honest
1936
+ moment, pattern, or decision the instrument should help someone notice.
1935
1937
 
1936
1938
  Arc:
1937
1939
 
1938
- 1. Ask what the questionnaire is meant to measure or surface.
1940
+ 1. Ask what honest moment, pattern, or decision the questionnaire should help someone
1941
+ notice.
1939
1942
  2. Ask who it is for and when it should be used.
1940
- 3. Ask what kind of honest moment or decision it should help someone answer before
1941
- getting into item wording.
1942
- 4. Reflect the practical use case back in plain language.
1943
- 5. Ask what would make the instrument distinct instead of redundant if a near-duplicate
1944
- risk is visible.
1945
- 6. Move to draft creation once the purpose is clear.
1943
+ 3. Ask what the respondent should understand after answering that they might otherwise
1944
+ miss.
1945
+ 4. Reflect the practical use case back in plain language before asking for item
1946
+ wording.
1947
+ 5. Ask what would make the instrument distinct instead of redundant if a
1948
+ near-duplicate risk is visible.
1949
+ 6. Ask about item shape, response scale, scoring, or provenance only after the purpose
1950
+ and use context are steady.
1951
+ 7. Move to draft creation once the purpose is clear.
1946
1952
 
1947
1953
  Helpful follow-up lanes:
1948
1954
 
1949
1955
  - what honest moment, decision, or review this instrument should support
1950
1956
  - who will answer it and under what circumstances
1957
+ - what the answers should help the respondent understand or choose
1951
1958
  - what would make the instrument distinct instead of redundant
1952
1959
 
1953
1960
  Route note:
@@ -1962,15 +1969,17 @@ Ready to act when:
1962
1969
 
1963
1970
  - the purpose is clear
1964
1971
  - the audience or use context is clear
1972
+ - the respondent-facing insight or decision is clear
1965
1973
  - the instrument is distinct enough to draft
1966
1974
 
1967
1975
  Preferred opening question:
1968
1976
 
1969
- - "What would this questionnaire help someone notice or track?"
1977
+ - "What honest moment or decision should this questionnaire help someone notice or track?"
1970
1978
 
1971
1979
  ## Questionnaire Run
1972
1980
 
1973
- Aim: clarify whether the user wants to start, continue, or complete one answer session.
1981
+ Aim: clarify whether the user wants to start, continue, review, or complete one answer
1982
+ session without turning the run into a mechanical form fill.
1974
1983
 
1975
1984
  Arc:
1976
1985
 
@@ -1978,13 +1987,16 @@ Arc:
1978
1987
  2. Ask which questionnaire or existing run this is about.
1979
1988
  3. If the user wants to continue or finish, ask what feels most stuck, unfinished, or
1980
1989
  important before asking for more content.
1981
- 4. If answering is still in progress, ask only for the next answer or note that matters.
1990
+ 4. If the user is reviewing answers, ask what the run should help them understand
1991
+ before proposing edits or completion.
1992
+ 5. If answering is still in progress, ask only for the next answer or note that matters.
1982
1993
 
1983
1994
  Helpful follow-up lanes:
1984
1995
 
1985
1996
  - whether the job is to begin, resume, review, or complete
1986
1997
  - what questionnaire or run is in scope
1987
1998
  - what next answer, uncertainty, or note is actually blocking progress
1999
+ - what the completed run should help the user understand or decide
1988
2000
 
1989
2001
  Route note:
1990
2002
 
@@ -2001,7 +2013,7 @@ Ready to act when:
2001
2013
 
2002
2014
  Preferred opening question:
2003
2015
 
2004
- - "Do you want to start, continue, review, or finish a questionnaire run?"
2016
+ - "What do you want from this questionnaire run right now: start, continue, review, or finish it?"
2005
2017
 
2006
2018
  ## Event Type
2007
2019